Laravel5.3とAngularJS1.6でコメントシステムを作ってみた

Laravel5の勉強と、以前から興味のあったAngularJSでコメントシステムを作ってみました。

参考サイト)
LaravelとAngularJSでコメントシステムを作ってみた
Create a Laravel and Angular Single Page Comment Application

Laravel5.3のインストール

2017年3月現在の最新は5.4のようですがハマるのが怖ったため5.3にしました。
PHPのバージョンは7.0.8です。

>composer create-project --prefer-dist laravel/laravel Comment_Application "5.3.*"

~略~
Writing lock file
Generating autoload files
> Illuminate\Foundation\ComposerScripts::postUpdate
> php artisan optimize
Generating optimized class loader
The compiled class file has been removed.
> php artisan key:generate
Application key [base64:PXxr3jaeCdAB8tEHlU8uuLisrbPE801G06i1H9kRdRM=] set successfully.

Laravel環境設定

composer.jsonがあったので依存ライブラリを取得してみました。

>composer install

Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Nothing to install or update
~略~
    `-- url-parse-lax@1.0.0
      `-- prepend-http@1.0.4

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules\chokidar\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.1: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

node.jsのパッケージをインストールします。

>npm install -g bower
>npm install

AngularJSの取得

>bower init

~略~
(エンターですべてデフォルト値を選択しました)

? Looks good? Yes
>bower install angular --save

#ついでにbootstrapも入れました。
>bower install bootstrap-sass-official --save

~略~
bower bootstrap-sass#^3.3.7              install bootstrap-sass#3.3.7
bower jquery#1.9.1 - 3                   install jquery#3.1.1

bootstrap-sass#3.3.7 bower_components\bootstrap-sass
└── jquery#3.1.1

jquery#3.1.1 bower_components\jquery

「–save」することでbower.jsonへ追加されます。

.envファイルにDB情報を設定します。

~略~

config/app.phpファイルの変更

'timezone' => 'UTC' → 'timezone' => 'Asia/Tokyo'
'locale' => 'en', → 'locale' => 'ja'

commentsテーブルの作成

下記コマンドにより database/migrations/XXXX_create_comments_table.php が作成されます。

>php artisan make:migration create_comments_table --create=comments

XXXX_create_comments_table.php にはあらかじめ主キーとタイムスタンプのカラムが記載されているのでtextカラムとauthorカラムを追加しました。

class CreateCommentsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('comments', function (Blueprint $table) {
            $table->increments('id');

            $table->string('text');
            $table->string('author');

            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('comments');
    }
}

DBのマイグレーション

前述のマイグレーションファイルを基にテーブルが作成されます。

>php artisan migrate

Migration table created successfully.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
Migrated: 2017_02_28_081528_create_comments_table

モデルの作成

app/Models配下にCommentテーブルのモデルを作成します。

php artisan make:model Models\Comment

モデルの$fillableプロパティでデータの保存を行いたいカラムを設定します。

class Comment extends Model
{
    protected $fillable = array('author', 'text');

}

シーダーの作成

>php artisan make:seeder CommentTableSeeder

作成したシーダーへ初期データを記載します。

class CommentTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('comments')->delete();

        Comment::create(array(
            'author' => '名無しさん',
            'text' => '今日はいい天気ですね。気持ちが良いですね。'
        ));

        Comment::create(array(
            'author' => '山田さん',
            'text' => '久しぶり。山田です。'
        ));

        Comment::create(array(
            'author' => '太郎さん',
            'text' => 'Laravelって便利なんですね。はじめて知りました。'
        ));
    }
}

DatabaseSeederにCommentTableSeederの呼び出しを追加します。

class DatabaseSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        Eloquent::unguard();

        $this->call('CommentTableSeeder');
        $this->command->info('Comment table seeded.');
    }
}

初期データの登録

>php artisan db:seed

コントローラーの作成

CommentControllerを作成します。

>php artisan make:controller CommentController

作成したコントローラーへindex, store, destroyを追加します。

class CommentController extends Controller
{
    public function index()
    {
        return response()->json(Comment::get());
    }

    public function store(Request $request)
    {
        Comment::create(array(
            'author' => $request->input('author'),
            'text' => $request->input('text')
        ));

        return response()->json(array('success' => true));
    }

    public function destroy($id)
    {
        Comment::destroy($id);

        return response()->json(array('success' => true));
    }
}

ルーティングの設定

routes/web.php

Route::get('/', function () {
//    return view('welcome');
    return View::make('index');
});

routes/api.php

Route::get('/user', function (Request $request) {
    return $request->user();
})->middleware('auth:api');

Route::resource('comments', 'CommentController',
    array('only' => array('index', 'store', 'destroy')));

確認します

>php artisan route:list
+--------+----------+------------------------+------------------+------------------------------------------------+--------------+
| Domain | Method   | URI                    | Name             | Action                                         | Middleware   |
+--------+----------+------------------------+------------------+------------------------------------------------+--------------+
|        | GET|HEAD | /                      |                  | Closure                                        | web          |
|        | POST     | api/comments           | comments.store   | App\Http\Controllers\CommentController@store   | api          |
|        | GET|HEAD | api/comments           | comments.index   | App\Http\Controllers\CommentController@index   | api          |
|        | DELETE   | api/comments/{comment} | comments.destroy | App\Http\Controllers\CommentController@destroy | api          |
|        | GET|HEAD | api/user               |                  | Closure                                        | api,auth:api |
+--------+----------+------------------------+------------------+------------------------------------------------+--------------+

SCSSの設定

resources/assets/sass/app.scss

// Fonts
@import url(https://fonts.googleapis.com/css?family=Raleway:300,400,600);

// Variables
@import "variables";

// Bootstrap
// @import "node_modules/bootstrap-sass/assets/stylesheets/bootstrap";
@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap";

gulpfile.js

const elixir = require('laravel-elixir');

require('laravel-elixir-vue-2');

/*
 |--------------------------------------------------------------------------
 | Elixir Asset Management
 |--------------------------------------------------------------------------
 |
 | Elixir provides a clean, fluent API for defining some basic Gulp tasks
 | for your Laravel application. By default, we are compiling the Sass
 | file for your application as well as publishing vendor resources.
 |
 */

elixir((mix) => {
    mix.sass('app.scss')
    .copy('bower_components/bootstrap-sass/assets/fonts/bootstrap/**', 'public/fonts/bootstrap')
    .scripts([
            "bower_components/jquery/dist/jquery.js",
            "bower_components/bootstrap-sass/assets/javascripts/bootstrap.min.js",
            "bower_components/angular/angular.js"
        ], 'public/js/app.js', './'
    );

       //.webpack('app.js');
});

Angularの各ファイルを作成

public/js/services/commentService.js

angular.module('commentService', [])

    .factory('Comment', function($http) {

        return {
            // すべてのコメントを取得する
            get : function() {
                return $http.get('/api/comments');
            },

            // コメントを保存する。
            save : function(commentData) {
                return $http({
                    method: 'POST',
                    url: '/api/comments',
                    headers: { 'Content-Type' : 'application/x-www-form-urlencoded' },
                    data: $.param(commentData)
                });
            },

            // コメントを削除する
            destroy : function(id) {
                return $http.delete('/api/comments/' + id);
            }
        }

    });

public/js/controllers/mainCtrl.js

angular.module('mainCtrl', [])

// コメントサービスをコントローラーに挿入する
    .controller('mainController', function($scope, $http, Comment) {

        // コメントフォームのデータを保持するオブジェクト
        $scope.commentData = {};

        // ロードアイコンの表示
        $scope.loading = true;

        // すべてのコメントを取得して、 $scope.comments にわたす
        Comment.get()
            .then(function onSuccess(response) {
            $scope.comments = response.data;
            $scope.loading = false;
        });
            // .success(function(data) {
            //     $scope.comments = data;
            //     $scope.loading = false;
            // });

        // 送信データのコントローラー
        $scope.submitComment = function() {
            $scope.loading = true;

            // コメントを保存する。
            Comment.save($scope.commentData)
                .then(function onSuccess(response) {
                    Comment.get()
                        .then(function onSuccess(responseData) {
                            $scope.comments = responseData.data;
                            $scope.loading = false;
                        });
                }, function onError(response) {
                    console.log(response.data);
                });
                // .success(function(data) {
                //
                //     // 成功した場合、コメントリストをリフレッシュする
                //     Comment.get()
                //         .success(function(getData) {
                //             $scope.comments = getData;
                //             $scope.loading = false;
                //         });
                //
                // })
                // .error(function(data) {
                //     console.log(data);
                // });
        };

        // コメント削除のコントローラー
        $scope.deleteComment = function(id) {
            $scope.loading = true;

            Comment.destroy(id)
                .then(function onSuccess(response) {
                    Comment.get()
                        .then(function onSuccess(responseData) {
                            $scope.comments = responseData.data;
                            $scope.loading = false;
                        });
                });
                // .success(function(data) {
                //
                //     // 成功した場合、コメントリストをリフレッシュする
                //     Comment.get()
                //         .success(function(getData) {
                //             $scope.comments = getData;
                //             $scope.loading = false;
                //         });
                //
                // });
        };

    });

public/js/app/app.js
#Angularのモジュールを登録しています。gulpで作成したファイルと同名で紛らわしいですが別物です。

var commentApp = angular.module('commentApp', ['mainCtrl', 'commentService']);

gulpを実行してscss→css(app.css)の作成と、jqueryとbootstrap、angularを結合したjsファイルを作成します。

>gulp
[02:16:36] Using gulpfile D:\XXX\gulpfile.js
[02:16:36] Starting 'all'...
[02:16:36] Starting 'sass'...
[02:16:37] Finished 'sass' after 1.06 s
[02:16:37] Starting 'copy'...
[02:16:37] Finished 'copy' after 62 ms
[02:16:37] Starting 'scripts'...
[02:16:37] Finished 'scripts' after 300 ms
[02:16:37] Finished 'all' after 1.43 s
[02:16:37] Starting 'default'...
┌───────────────┬──────────────────────────┬─────────────────────────────────────────────────────────────────────┬────────────────────────┐
│ Task          │ Summary                  │ Source Files                                                        │ Destination            │
├───────────────┼──────────────────────────┼─────────────────────────────────────────────────────────────────────┼────────────────────────┤
│ mix.sass()    │ 1. Compiling Sass        │ resources\assets\sass\app.scss                                      │ public\css\app.css     │
│               │ 2. Autoprefixing CSS     │                                                                     │                        │
│               │ 3. Concatenating Files   │                                                                     │                        │
│               │ 4. Writing Source Maps   │                                                                     │                        │
│               │ 5. Saving to Destination │                                                                     │                        │
├───────────────┼──────────────────────────┼─────────────────────────────────────────────────────────────────────┼────────────────────────┤
│ mix.copy()    │ 1. Saving to Destination │ bower_components/bootstrap-sass/assets/fonts/bootstrap/**/**/*      │ public/fonts/bootstrap │
├───────────────┼──────────────────────────┼─────────────────────────────────────────────────────────────────────┼────────────────────────┤
│ mix.scripts() │ 1. Concatenating Files   │ bower_components\jquery\dist\jquery.js                              │ public/js/app.js       │
│               │ 2. Writing Source Maps   │ bower_components\bootstrap-sass\assets\javascripts\bootstrap.min.js │                        │
│               │ 3. Saving to Destination │ bower_components\angular\angular.js                                 │                        │
└───────────────┴──────────────────────────┴─────────────────────────────────────────────────────────────────────┴────────────────────────┘
[02:16:37] Finished 'default' after 16 ms

viewの作成

resources/views/index.blade.php

<!doctype html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Laravel と Angular の コメントシステム</title>
    {{--<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css">--}}
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css">
    <link rel="stylesheet" href="/css/app.css">
    <script src="/js/app.js"></script>

    <style>
        body 		{ padding-top:30px; }
        form 		{ padding-bottom:20px; }
        .comment 	{ padding-bottom:20px; }
    </style>

    {{--<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>--}}
    {{--<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js"></script>--}}

    <script src="js/controllers/mainCtrl.js"></script>
    <script src="js/services/commentService.js"></script>
    <script src="js/app/app.js"></script>

</head>
<body class="container" ng-app="commentApp" ng-controller="mainController">
<div class="col-md-8 col-md-offset-2">

    <div class="page-header">
        <h2>Laravel と Angular の コメントシステム</h2>
    </div>

    <form ng-submit="submitComment()">

        <div class="form-group">
            <input type="text" class="form-control input-sm" name="author" ng-model="commentData.author" placeholder="名前">
        </div>

        <div class="form-group">
            <input type="text" class="form-control input-lg" name="comment" ng-model="commentData.text" placeholder="コメントをどうぞ">
        </div>

        <div class="form-group text-right">
            <button type="submit" class="btn btn-primary btn-lg">コメントする</button>
        </div>
    </form>

    <p class="text-center" ng-show="loading"><span class="fa fa-meh-o fa-5x fa-spin"></span></p>

    <div class="comment" ng-hide="loading" ng-repeat="comment in comments">
        <h3>コメント #@{{ comment.id }} <small>by @{{ comment.author }}</h3>
        <p>@{{ comment.text }}</p>
        <p><a href="#" ng-click="deleteComment(comment.id)" class="text-muted">削除</a></p>
    </div>

</div>

</body>
</html>

以上で完了です。
2017-03-01_02h35_18

スポンサーリンク
google

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

スポンサーリンク
google