使用Laravel和Angular创建一个单页的评论应用

开发 前端
目前,Laravel和Angular均已经成为了Web发展世界里非常著名的工具。Laravel以给PHP社区引入的伟大内容著称,Angular以其惊人的前端工具及简单著称。组合这两大框架似乎是合乎逻辑的下一步。

完整代码:https://github.com/scotch-io/laravel-angular-comment-app

目前,Laravel和Angular均已经成为了Web发展世界里非常著名的工具。Laravel以给PHP社区引入的伟大内容著称,Angular以其惊人的前端工具及简单著称。组合这两大框架似乎是合乎逻辑的下一步。

在我们的使用环境下,我们将使用Laravel作为后端的RESTful APIAngular作为前端,以创建一个简单的单页的评论应用。

下面是一个简单的例子,展示了如何开始使用这两种技术,所以不用害怕什么额外的数据库性的东西、如何处理子评论什么的。

我们将创建什么

这将是一个简单的单页评论应用程序:

  • RESTful Laravel API处理获取、创建和删除评论;

  • Angular前端负责显示我们创建的表单和评论;

  • 能够新建评论并把它添加到我们的W/O页面刷新列表;

  • 能够删除评论并把它从W/O页面刷新列表移除。

总体上,这些都是非常简单的概念。我们重点是关注Laravel与Angular如何一起协作的错综复杂关系。

laravel-angular-single-page-application 

Laravel后端

设置Laravel

继续设置好你的Laravel,我们将做一些基础工作使我们的后端实现评论的增删改查:

  • 创建一个数据库迁移

  • 将样本评论植入数据库

  • 为我们的API创建路由表

  • 创建一个“全部获取”路由表让Angular出来路由

  • 为评论创建一个资源控制器

准备数据库迁移

我们要一个简单的、存储评论的结构体,只需要包括内容和作者。让我们创建Laravel迁移来创建评论。

我们来运行artisan命令创建评论迁移,这样就可以在我们的数据库里建立评论表:

    php artisan migrate:make create_comments_table --create=comments

我们将使用Laravel模式构建器创建所需的“内容”和“作者”域。Laravel也会创建id和timestamps列,这样我们可以知道这条评论是什么时候添加的。以下是评论表的代码:

  1. // app/database/migrations/####_##_##_######_create_comments_table.php  
  2. ...  
  3.  
  4.     /**  
  5.      * Run the migrations.  
  6.      *  
  7.      * @return void  
  8.      */ 
  9.     public function up()  
  10.     {  
  11.         Schema::create('comments', function(Blueprint $table)  
  12.         {  
  13.             $table->increments('id');  
  14.  
  15.             $table->string('text');  
  16.             $table->string('author');  
  17.  
  18.             $table->timestamps();  
  19.         });  
  20.     }  
  21. ...  

确定你在“app/config/database.php”文件中用正确的凭证调整了数据库设置。现在我们运行迁移,这样就能用所需的列创建这张表:

   php artisan migrate

laravel-angular-migrate 

评论模型

我们将用Laravel Eloquent模型与数据库进行交互。这很容易做到,让我们来创建一个模型:“app/models/Comment.php”:

  1. <?php  
  2.  
  3. // app/models/Comment.php  
  4.  
  5. class Comment extends Eloquent {  
  6.         // let eloquent know that these attributes will be available for mass assignment  
  7.     protected $fillable = array('author''text');   
  8. }  

现在有了表和模型,让我们通过Laravel Seeding向表中添加一个样本数据。

播种数据库

我们需要一些评论来测试几件事。让我们创建一个种子文件并插入三个样本评论到数据库。

创建一个文件:“app/database/seeds/CommentTableSeeder.php”,并添加以下代码:

  1. <?php  
  2. // app/database/seeds/CommentTableSeeder.php  
  3.  
  4. class CommentTableSeeder extends Seeder   
  5. {  
  6.  
  7.     public function run()  
  8.     {  
  9.         DB::table('comments')->delete();  
  10.  
  11.         Comment::create(array(  
  12.             'author' => 'Chris Sevilleja',  
  13.             'text' => 'Look I am a test comment.' 
  14.         ));  
  15.  
  16.         Comment::create(array(  
  17.             'author' => 'Nick Cerminara',  
  18.             'text' => 'This is going to be super crazy.' 
  19.         ));  
  20.  
  21.         Comment::create(array(  
  22.             'author' => 'Holly Lloyd',  
  23.             'text' => 'I am a master of Laravel and Angular.' 
  24.         ));  
  25.     }  
  26.  
  27. }  

要调用这个播种机文件,我们要修改“app/database/seeds/DatabaseSeeder.php”并添加以下代码:

  1. // app/database/seeds/DatabaseSeeder.php  
  2.  
  3.  
  4. /**  
  5.  * Run the database seeds.  
  6.  *  
  7.  * @return void  
  8.  */ 
  9. public function run()  
  10. {  
  11.     Eloquent::unguard();  
  12.  
  13.     $this->call('CommentTableSeeder');  
  14.     $this->command->info('Comment table seeded.');  
  15. }  

现在我们通过artisan命令来运行我们的播种机。

  php artisan db:seed

laravel-angular-database-seed

现在我们拥有一个包含评论表的数据库、一个Eloquent模型和一些数据库样本。一天的工作还不算糟。。。但我们还远没有结束。

#p#

评论资源控制器(app/controllers/CommentController.php)

我们将使用Laravel资源控制器处理评论的API函数。因为使用Angular显示一个资源以及创建和更新表单,在没有创建和编辑函数的情况下,我们将通过artisan命令创建一个资源控制器。

让我们用artisan创建资源控制器。

    php artisan controller:make CommentController --only=index,store,destroy

对于示例应用,我们只会在资源控制器中使用这三个函数。为了扩展,你要包含所有的诸如更新、显示等函数,来实现一个更成熟的应用。

laravel-angular-create-controller

我们已经创建了控制器,就不需要创建和编辑函数啦,因为Angular,而不是Laravel会处理显示表单的工作。Laravel只负责把数据返回给前端。只为了想让事情简单化,我们也从实例应用提出了更新函数。我们将处理创建、显示和删除评论。

要回传数据,我们想以JSON形式返回数据。我们来浏览一下新建的控制器并添加相应的函数。

  1. <?php  
  2. // app/controllers/CommentController.php  
  3.  
  4. class CommentController extends \BaseController {  
  5.  
  6.     /**  
  7.      * Send back all comments as JSON  
  8.      *  
  9.      * @return Response  
  10.      */ 
  11.     public function index()  
  12.     {  
  13.         return Response::json(Comment::get());  
  14.     }  
  15.  
  16.     /**  
  17.      * Store a newly created resource in storage.  
  18.      *  
  19.      * @return Response  
  20.      */ 
  21.     public function store()  
  22.     {  
  23.         Comment::create(array(  
  24.             'author' => Input::get('author'),  
  25.             'text' => Input::get('text')  
  26.         ));  
  27.  
  28.         return Response::json(array('success' => true));  
  29.     }  
  30.  
  31.     /**  
  32.      * Remove the specified resource from storage.  
  33.      *  
  34.      * @param  int  $id  
  35.      * @return Response  
  36.      */ 
  37.     public function destroy($id)  
  38.     {  
  39.         Comment::destroy($id);  
  40.  
  41.         return Response::json(array('success' => true));  
  42.     }  
  43.  
  44. }  

你可以看到用Laravel和Eloquent处理增删改查多么容易。处理我们所需的函数简直难以置信的简单。

随着控制器的准备完成,我们后端最后要做的一件事就是路由。

补充阅读:Simple Laravel CRUD with Resource Controllers

我们的路由表(app/routes.php)

随着数据库的准备就绪,我们来处理Laravel应用的路由表吧。既然它有自己的路由,我们将会用到路由表发送数据给前端。我们也要给后台API提供路由表,从而可以让人访问我们的评论数据。

让我们创建Angular指向路由表。我们需要一个主页路由表和一个发送用户给Angular的“全部获取”路由表。这保证了用户无论怎样都能访问我们的网站,它们会被路由到Angular前端。

我们将以...(请击鼓)...api作为API路由表前缀。通过这种方式,如果有人想获取所有的评论,他们将使用URL:http://example.com/api/comments 。这只是有意义的前进和一些基础API创建的好策略。

  1. <?php  
  2. // app/routes.php  
  3.  
  4. // =============================================  
  5. // HOME PAGE ===================================  
  6. // =============================================  
  7. Route::get('/'function()  
  8. {  
  9.     // we dont need to use Laravel Blade  
  10.     // we will return a PHP file that will hold all of our Angular content  
  11.     // see the "Where to Place Angular Files" below to see ideas on how to structure your app  
  12.     return View::make('index'); // will return app/views/index.php  
  13. });  
  14.  
  15. // =============================================  
  16. // API ROUTES ==================================  
  17. // =============================================  
  18. Route::group(array('prefix' => 'api'), function() {  
  19.  
  20.     // since we will be using this just for CRUD, we won't need create and edit  
  21.     // Angular will handle both of those forms  
  22.     // this ensures that a user can't access api/create or api/edit when there's nothing there  
  23.     Route::resource('comments''CommentController',   
  24.         array('only' => array('index''store''destroy')));  
  25. });  
  26.  
  27. // =============================================  
  28. // CATCH ALL ROUTE =============================  
  29. // =============================================  
  30. // all routes that are not home or api will be redirected to the frontend  
  31. // this allows angular to route them  
  32. App::missing(function($exception)  
  33. {  
  34.     return View::make('index');  
  35. });  

我们现在有路由表来处理Laravel要做的三件主要事情。

处理“全部获取”路由表:在Laravel里,你可以用几种方式实现这个。通常,用以上代码并得到整个应用的“全部获取”不太理想。另一种选择是,你可以使用Laravel控制器的丢失方法来获取路由表。

测试所有的路由表 让我们确保所需的路由表都有了。我们会用到artisan查看所有的路由表:

   php artisan routes

这个命令让我们看到所有的路由表以及一个自上而下的应用视图。

laravel-angular-artisan-routes

从上图我们能看到HTTP动词和获取所有评论,获取、创建和销毁一条评论的路由表。在API路由表的顶部,可以看到一个用户如何通过主页路由表路由到Angular的。

后台完成

终于!我们Laravel API的后台也完成了。我们已经做了很多,但还有很多工作要做。我们已经建立并播种了数据库,创建了模型和控制器,也建好了路由表。我们来继续完成Angular前端的工作。

将Angular文件放在哪

我看到这个问题很多次被问到了。我到底应该把Angular文件放在哪呢,还有如何使Laravel和Angular一起工作。这有一篇文章讲怎样使Laravel Blade和Angular一起工作。本文假设我们从未使用过Blade。

让Angular来处理前端,我们需要Laravel将用户导向到index.php文件。我们可以把它放在几个不同的地方。默认情况下,当你使用:

  1. // app/routes.php  
  2. Route::get('/'function() {  
  3.  
  4.     return View::make('index');      
  5.  
  6. });  

这将返回app/views/index.php。Laravel默认情况下将在app/views文件夹查找。

一些人想要将Angular文件和Laravel 文件完全分开。他们想要让他们的整个应用程序放在public文件夹中。这样做很简单:只需要将默认的View的位置设置为public文件夹即可。可以通过修改app/config/view.php文件来完成设置。

  1. // app/config/view.php  
  2. ...  
  3.       
  4.     // make laravel look in public/views for view files  
  5.     'paths' => array(__DIR__.'/../../public/views'),  
  6.  
  7. ...  

现在,return View::make('index') 将会查找public/views/index.php文件。你完全可以配置你想如何组织你的app。一些人认为将整个Angular应用程序放在public文件夹中好处比较多,这样可以很容易的处理路由并且如果将来有需要的话,可以完全的将后端的RESTful API 和前端的Angular区分开来。

为了Angular能进行路由,那么你的部分文件需被放置在public 文件夹中,但是这已经超出了本文的范围。 如果你需更多单页Angular 路由的信息,请查看  单页Angular 应用路由

让我们假设所有东西都使用默认,并且我们的主视图文件是在我们的app/ views 文件夹下,然后我们继续。 

使用Laravel和Angular 路由 如果使用Laravel和Angular 路由时冲突了,会导致很多的问题。Laravel将作为主路由掌控你的应用程序。Angular 路由只会发生在, 当Laravel路由我们的用户, 到Angular主路由(index.php)这种情况。 这就是为什么我们使用Laravel掌控所有的路由。Laravel将处理API路由和将任意不知如何路由发送到Angular。然后,你可以为你的Angular 应用设置所有的路由来处理出不同的视图。

#p#

前端的Angular

准备我们的应用程序

我们的Angular程序中的每一件事都要在public文件夹中处理。这可以有助于我们将它和后端的app文件夹中的文件很好的区分开来。

让我们看一下我们的public文件夹中的组织结构。我们创建了模块化的Angular程序,因为这是最佳实践。现在,我们程序分成的各个部分很容易进行测试和处理。

  1. public/  
  2. ----- js/  
  3. ---------- controllers/                // where we will put our angular controllers  
  4. --------------- mainCtrl.js   
  5. ---------- services/                 // angular services  
  6. --------------- commentService.js   
  7. ---------- app.js 

Angular Service public/js/services/commentService.js

  1. // public/js/services/commentService.js  
  2. angular.module('commentService', [])  
  3.  
  4.     .factory('Comment'function($http) {  
  5.  
  6.         return {  
  7.             // get all the comments  
  8.             get : function() {  
  9.                 return $http.get('/api/comments');  
  10.             },  
  11.  
  12.             // save a comment (pass in comment data)  
  13.             save : function(commentData) {  
  14.                 return $http({  
  15.                     method: 'POST',  
  16.                     url: '/api/comments',  
  17.                     headers: { 'Content-Type' : 'application/x-www-form-urlencoded' },  
  18.                     data: $.param(commentData)  
  19.                 });  
  20.             },  
  21.  
  22.             // destroy a comment  
  23.             destroy : function(id) {  
  24.                 return $http.delete('/api/comments/' + id);  
  25.             }  
  26.         }  
  27.  
  28.     });  

这就是我们的Angular service,包含了3个不同的函数。这些是我们唯一所需要的函数,因为它们将会和我们Laravel中的路由api相对应。

我们的service将会返回一个promise对象。这些将会用来处理我们的控制器。这里的命名约定同样也和我们的Laravel控制器保持一致。

完成了我们的Angular service,让我们开始着手我们的控制器并使用它。

Angular控制器public/js/controllers/mainCtrl.js

该控制器实现了我们应用的绝大部分功能。我们在这里面创建处理提交表单和删除评论的函数。

  1. // public/js/controllers/mainCtrl.js  
  2. angular.module('mainCtrl', [])  
  3.  
  4.     // 在控制器中诸如Comment服务  
  5.     .controller('mainController'function($scope$http, Comment) {  
  6.         // 持有新评论所有表单数据的对象  
  7.         $scope.commentData = {};  
  8.  
  9.         // 调用显示加载图标的变量  
  10.         $scope.loading = true;  
  11.  
  12.         // 先获取所有的评论,然后绑定它们到$scope.comments对象         // 使用服务中定义的函数  
  13.         // GET ALL COMMENTS ====================================================  
  14.         Comment.get()  
  15.             .success(function(data) {  
  16.                 $scope.comments = data;  
  17.                 $scope.loading = false;  
  18.             });  
  19.  
  20.         // 处理提交表单的函数  
  21.         // SAVE A COMMENT ======================================================  
  22.         $scope.submitComment = function() {  
  23.             $scope.loading = true;  
  24.  
  25.             // 保存评论。在表单间传递评论  
  26.             // 使用在服务中创建的函数  
  27.             Comment.save($scope.commentData)  
  28.                 .success(function(data) {  
  29.  
  30.                     // 如果成功,我们需要刷新评论列表  
  31.                     Comment.get()  
  32.                         .success(function(getData) {  
  33.                             $scope.comments = getData;  
  34.                             $scope.loading = false;  
  35.                         });  
  36.  
  37.                 })  
  38.                 .error(function(data) {  
  39.                     console.log(data);  
  40.                 });  
  41.         };  
  42.  
  43.         // 处理删除评论的函数  
  44.         // DELETE A COMMENT ====================================================  
  45.         $scope.deleteComment = function(id) {  
  46.             $scope.loading = true;   
  47.  
  48.             // 使用在服务中创建的函数  
  49.             Comment.destroy(id)  
  50.                 .success(function(data) {  
  51.  
  52.                     // 如果成功,我们需要刷新评论列表  
  53.                     Comment.get()  
  54.                         .success(function(getData) {  
  55.                             $scope.comments = getData;  
  56.                             $scope.loading = false;  
  57.                         });  
  58.  
  59.                 });  
  60.         };  
  61.  
  62.     });  

正如你在控制器中看到的,我们已经注入了Comment服务并使用它来实现主要的功能:获得,保存以及删除。使用这样的服务避免用$http get或put来污染我们的控制器。

连接到我们的应用public/js/app.js

在Angular方面,我们已经创建了服务和控制器。现在让我们将一起连接起来,这样我们可以使用ng-app和ng-controller将它应用到我们的应用中。

这就是创建Angular应用的代码。我们将把服务和控制器注入。这是最佳实践的做法,这能够使我们的应用程序模块化,且各个不同部分都是可测可扩展的。

  1. // public/js/app.js  
  2. var commentApp = angular.module('commentApp', ['mainCtrl''commentService']);  

就这样,没有太多工作。现在我们切实实现了我们的观点,我们可以看Angular的各部分是如何一起工作的。

#p#

我们的主视图app/views/index.php

到目前为止,在做完一切准备工作后,我们仍然不能从浏览器中看到任何内容。因为Laravel控制着我们的主路由,我们需要定义我们的视图文件,且将所有路由请求返回return View::make('index');。

让我们先创建视图。我们将使用我们已创建的所有Angular内容。我们已已使用Angular创建的主要部分将是我们将在index.php中主要使用的部件:

  • ng-app和ng-controller:通过将它们附加到body标签上来应用它们

  • ng-repeat:通过循环将评论显示到模板中

  • submitComment():使用ng-submit将这个函数附加到表单上

  • Loading Icons:我们将创建一个称作loading的变量。如果它被设为true,我们将显示一个加载图标并隐藏评论

  • deleteComment():我们将附加这个函数到一个删除链接,以便我们删除评论

现在让我们来写实现我们观点的实际代码。我们将对主要重要的部分做注释,这样我们就能够看到一切是如何正常工作的。

  1. <!-- app/views/index.php -->  
  2. <!doctype html>  
  3. <html>  
  4. <head>  
  5.     <meta charset="UTF-8">  
  6.     <title>Laravel and Angular Comment System</title>  
  7.  
  8.     <!-- CSS -->  
  9.     <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css"> <!-- load bootstrap via cdn -->  
  10.     <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> <!-- load fontawesome -->  
  11.     <style>  
  12.         body         { padding-top:30px; }  
  13.         form         { padding-bottom:20px; }  
  14.         .comment     { padding-bottom:20px; }  
  15.     </style>  
  16.  
  17.     <!-- JS -->  
  18.     <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>  
  19.     <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js"></script> <!-- load angular -->  
  20.  
  21.     <!-- ANGULAR -->  
  22.     <!-- all angular resources will be loaded from the /public folder -->  
  23.         <script src="js/controllers/mainCtrl.js"></script> <!-- load our controller -->  
  24.         <script src="js/services/commentService.js"></script> <!-- load our service -->  
  25.         <script src="js/app.js"></script> <!-- load our application -->  
  26.  
  27. </head>  
  28. <!-- declare our angular app and controller -->  
  29. <body ng-app="commentApp" ng-controller="mainController">  
  30. <div class="col-md-8 col-md-offset-2">  
  31.  
  32.     <!-- PAGE TITLE =============================================== -->  
  33.     <div>  
  34.         <h2>Laravel and Angular Single Page Application</h2>  
  35.         <h4>Commenting System</h4>  
  36.     </div>  
  37.  
  38.     <!-- NEW COMMENT FORM =============================================== -->  
  39.     <form ng-submit="submitComment()"> <!-- ng-submit will disable the default form action and use our function -->  
  40.  
  41.         <!-- AUTHOR -->  
  42.         <div>  
  43.             <input type="text" class="form-control input-sm" name="author" ng-model="commentData.author" placeholder="Name">  
  44.         </div>  
  45.  
  46.         <!-- COMMENT TEXT -->  
  47.         <div>  
  48.             <input type="text" class="form-control input-lg" name="comment" ng-model="commentData.text" placeholder="Say what you have to say">  
  49.         </div>  
  50.           
  51.         <!-- SUBMIT BUTTON -->  
  52.         <div class="form-group text-right">      
  53.             <button type="submit" class="btn btn-primary btn-lg">Submit</button>  
  54.         </div>  
  55.     </form>  
  56.  
  57.     <!-- LOADING ICON =============================================== -->  
  58.     <!-- show loading icon if the loading variable is set to true -->  
  59.     <p ng-show="loading"><span class="fa fa-meh-o fa-5x fa-spin"></span></p>  
  60.  
  61.     <!-- THE COMMENTS =============================================== -->  
  62.     <!-- hide these comments if the loading variable is true -->  
  63.     <div ng-hide="loading" ng-repeat="comment in comments">  
  64.         <h3>Comment #{{ comment.id }} <small>by {{ comment.author }}</h3>  
  65.         <p>{{ comment.text }}</p>  
  66.  
  67.         <p><a href="#" ng-click="deleteComment(comment.id)">Delete</a></p>  
  68.     </div>  
  69.  
  70. </div>  
  71. </body>  
  72. </html>  

laravel-angular-single-page-application

现在我们终于实现了我们的观点,将所有已创造的部分组合了起来。你可以去试玩一下这个应用。所有部件都应很好地结合在一起,评论的创建和删除也应该不用刷新页面。

测试

确保你测试了 Github repo 的应用.下面是做好这一过程的步骤

  1. 复制 repo:git clone git@github.com:scotch-io/laravel-angular-comment-app

  2. 安装Laravel:composer install --prefer-dist

  3. 修改数据库连接 inapp/config/database.php

  4. 数据迁移 database:php artisan migrate

  5. 打好种子 database:php artisan db:seed

  6. 浏览你的应用!

结论

以往本文在介绍使用 Laravel 和Angular上为你提供了帮助. 你可以在此基础上创建使用更多API的 Laravel 应用, 甚至创建自己的 Angular routing .

如果有什么提议请告知. 我们会及时更新这篇文章.

英文原文:Create a Laravel and Angular Single Page Comment Application

译文来自:http://www.oschina.net/translate/create-a-laravel-and-angular-single-page-comment-application

责任编辑:林师授 来源: 开源中国社区 编译
相关推荐

2014-09-09 10:49:59

AngularJS单页应用

2016-11-01 21:02:47

javascriptreact.jsreact-route

2022-02-18 08:43:19

Spring Boo应用程序RabbitMQ

2018-08-26 22:39:08

单页应用HATEOAS

2011-05-11 10:58:39

iOS

2023-05-10 08:05:41

GoWeb应用

2014-09-19 10:54:47

用户体验单页面

2012-04-19 17:42:46

Titanium布局

2017-09-18 09:03:36

线程安全单例

2011-03-15 19:45:27

Windows Azu

2019-07-16 16:05:51

PythonScribusRGB

2020-09-01 20:53:26

DocsifyGitHub Page文档网站

2017-09-18 09:17:07

线程安全单例

2010-08-13 13:05:30

Flex应用程序

2015-05-27 07:44:34

日历控件 jQueryCSS3

2018-11-14 19:00:24

PythonRedis共享单车

2023-11-03 11:57:04

2023-03-30 13:22:45

nginxweb服务器

2017-08-08 14:15:24

2009-08-19 04:14:00

线性链表
点赞
收藏

51CTO技术栈公众号