- 投稿日:2019-05-21T22:30:35+09:00
AWS Cloud9でLaravelの開発環境構築
はじめに
AWS Cloud9でLaravelの開発環境を構築する手順です。
Cloud9の起動
ブラウザでCloud9を起動します。
コンソールの表示
コンソールが表示されていない場合は、F6キーを押下してコンソールを表示します。
コンソールとは、以下のような「bash」とタブに表示されている場所です。
コンソールでは、コマンドでサーバーを操作することが出来ます。
コマンドの実行方法
コマンドの実行方法がわからない場合は、以下の動画を参考にしてください。
PHP7.3のインストール
2019/05/19時点では、EC2のAmazon LinuxにインストールされているPHPのバージョンは5.6.40であるため、PHP7.3にアップデートします。
以下のコマンドを実行します。
sudo amazon-linux-extras install php7.3以下の表示となったら、「y」を入力し、Enterキーを押下します。
以下のように表示されれば完了。
composerのインストール
composerは、PHPのパッケージ管理ツールです。
パッケージ管理ツールがあれば、便利なライブラリを簡単に自分のWebサイトに反映することが出来ます。以下のコマンドを実行します。
curl -sS https://getcomposer.org/installer | php
以下のように表示されるまで待ちます。
以下のコマンドを実行します。
sudo mv composer.phar /usr/local/bin/composer
実行は一瞬で完了して、以下のような表示になります。
以下のコマンドを実行します。
composer以下のように表示されれば、composerのインストールは完了です。
必要なライブラリののインストール
以下のコマンドを実行します。
sudo yum install php php-mbstring php-pdo php-gd php-xml以下の表示となったら、「y」を入力し、Enterキーを押下します。
以下の表示になったらインストールは完了です。
laravelのプロジェクトの作成
以下のコマンドを実行します。(「myproject」の部分は好みの名前に変更してください。)
composer create-project --prefer-dist laravel/laravel myproject "5.5.*"以下のように表示されればlaravelのプロジェクトが完成です。
以下のコマンドでプロジェクトのカレントディレクトリに移動します。(「myproject」は、laravelプロジェクト作成時に指定した名前に変えてください。)
cd myproject
以下のコマンドを実行します。
php artisan key:generate以下のように表示されれば成功です。
Webサーバーの起動
以下のコマンドを実行します。
php artisan serve --port=8080以下のように表示されればWebサーバーの起動に成功
Cloud9の右上の「Preview」をクリックして、Preview Running Applicationをクリックする。
Cloud9内部にブラウザが起動し、Laravelの画面が表示される。
参考
https://laraweb.net/environment/3953/
https://dev.classmethod.jp/cloud/aws/my_first_aws_han/
- 投稿日:2019-05-21T19:32:42+09:00
自習用学んだことメモ帳(完全自分用)
- 投稿日:2019-05-21T17:29:52+09:00
51歳からのプログラム 備忘 eloquent データ登録 save()
$model->fill($param)->save();
で、よくしてしまう
save();
の用法ミス。何度も迷走するところ
試行錯誤して時間をかけてしまうので備忘メモ。間違コード
$param[1]=['氏名'=>'山田','住所'=>'北海道','職業'=>'会社員']; $param[2]=['氏名'=>'佐藤','住所'=>'佐賀','職業'=>'主婦']; $param[3]=['氏名'=>'三田','住所'=>'千葉','職業'=>'会社員']; $param[4]=['氏名'=>'井上','住所'=>'長野','職業'=>'自営業']; $param[5]=['氏名'=>'田中','住所'=>'山口','職業'=>'会社員']; $model=new Model;// Modelのインスタンス生成 <- ここが間違い箇所 foreach($param as $key => $value) { $model->fill($value)->save(); }結果は、models(DBテーブル)に一行追加されただけ。
$modelインスタンスは、
models(DBテーブル)の一行分のデータフィールドを操作するインスタンス。
newすることで、新しいデータフィールドを作成して、それをインスタンスで操作する。
newが一度だと、新規に作成する一行しか操作できない。
(一行分のインスタンスしか生成されてない)
上記のコードでは、newは一回だから、
foreachで配列を5回まわしても、
一行のmodels(DBテーブル)に対してしか操作できてない
5行分のmodels(DBテーブル)フィールドを操作するには
5回newしないとね!修正
foreach($param as $key =>$value) { $model=new Model; $model->fill($value)->save(); }
- 投稿日:2019-05-21T16:44:03+09:00
コントローラからViewに値を渡す
ビューの作成
ビューはアプリケーションとして動作するHTMLにより構成されており、コントローラ/アプリケーションロジックをプレゼンテーションロジックから分離します。ビューは
resources/views
ディレクトリに保存する。resources/view/greeting.blade.php<html> <body> <h1>Hello,{{$name}}</h1> </body> </html>このビューを
resources/views/greeting.blade.php
として保存しているので以下のようにグローバルview
ヘルパ関数を使用し結果を返す。Route::get(`/`,function(){ Return view (`greeting`,[`name` => `James]); });二つ目の引数はビューで使用するデータの配列。上記の例ではビューに```name```変数を渡しそれをBlade記法を使用しているビューの中に表示される。 #ビューにデータを渡す 簡単にデータを配列でビューに渡せる。 ```php return view(`greetings`,[`name` => `Victoria`]);この方法で情報を渡す場合その情報はキー/値ペアの配列。ビューの中で各値へは対抗するキーへアクセスできる。例えば
<?php echo $key; ?>のように表示可能。全データを
viewヘルパ関数に渡す代わりに``with
メソッドでビューに渡すデータを個別に追加することもできる。return view(`greeting`)->with(`name`,`Victoria`);参照
- 投稿日:2019-05-21T16:08:33+09:00
スキルシート
コントローラー
アクションを適切に追加できる
コントローラはユーザーからのリクエストを受け取り、モデルやビューなどと連携し結果をユーザーに返す役割をする部分です。
Webページの具体的な処理はコントローラを使って行うのが基本です。コントローラはMVCアーキテクチャの基本となるもの。
ルーティングはアクセスしたアドレスを元に処理を割り振るための機能。
ルーティングはWebページを作って表示させるためのものではない。
具体的に実行すべき処理は別に用意されていてそれを特定アドレスに割り振って呼び出すためのもの。
呼び出される「具体的に実行すべき処理」を実装するために用意されているのが「コントローラ」。
MVCは「Model-view-Controller」の略。
これはアプリケーションの処理をMVCの3つの要素の組み合わせとして構築していく考え。
Model
データ処理全般を担当。具体的にはデータベースアクセスに関する処理全般を扱う。View
画面表示を担当。表示に使うテンプレートなどがこれに相当。Controller
全体の制御を担当。必要に応じてModelを使ってデータを取得したり、Viewを利用して画面表示を作成。ModelやViewは特定の機能に特化。これに対してControllerは処理全般の制御を担当し、プログラムの本体部分。
Laravelの開発はまずControllerを作るところから始まる。
Webアプリケーションにアクセスするとコントローラが処理を行う。必要に応じてビューやモデルを利用し画面表示やデータベースのデータなどを受け取っていく。
参照
https://www.javadrive.jp/rails/controller/
https://qiita.com/shg3/items/8561a650d12bd13249b2
- 投稿日:2019-05-21T15:32:48+09:00
laravel5.8-slack簡単通知
準備
まず、Slack側でWebhookUrlを作成しておきます。リンク
laravel5.8以降は、composerからSlackチャンネルのインストールが必要なので入れます。
コマンドcomposer require laravel/slack-notification-channel.envファイルにSlackに通知するため、WebhookUrlとChannelを指定する。
.envSLACK_CHANNEL=#test SLACK_WEBHOOK_URL=https://hooks.slack.com/services/自分用設定を変えたので、反映させるためにキャッシュを消します。
コマンドphp artisan config:cache作成
Notification
laravelの機能のNotificationを利用する。
コマンドphp artisan make:notification SlackNotificationSlackNotification<?php namespace App\Notifications; use Carbon\Carbon; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Messages\SlackAttachment; use Illuminate\Notifications\Notification; use Illuminate\Notifications\Messages\SlackMessage; class SlackNotification extends Notification { use Queueable; protected $content; protected $channel; public function __construct($message) { $this->channel = env('SLACK_CHANNEL'); $this->content = $message; } public function via($notifiable) { return ['slack']; } public function toArray($notifiable) { return [ // ]; } public function toSlack($notifiable) { return (new SlackMessage) ->from('管理者') ->image('https://larapet.hinaloe.net/wp-content/uploads/sites/15/2017/03/cropped-86f8cf99663ac01836df2fa9c56890ff-1.png') ->to($this->channel) ->content('Hello') ->attachment(function (SlackAttachment $attachment) { $attachment ->title('ユーザー', '') ->field('名前', 'testUser') ->field('メールアドレス', 'test@co.jp') ->timestamp(Carbon::now()); }); } }SlackAttachmentの参考記事・SlackAttachmentチートシート
・viaメソッド どこのチャンネルに飛ばすか
・toSlackメソッド もしfromの名前を動的に変えたいなどがあれば、constructで指定します。
SlackAttachmentを指定するといろいろ通知を工夫できます。Nortificableをuseしたクラスを用意する。
use Notifiableを記述したクラスならなんでもOK。Modelだとデフォルトでそうなっている場合があるので、基本そこの指定なのかな(しらない) 今回は、別クラスを用意してみます。
app/Services/SlackService<?php namespace App\Services; use Illuminate\Notifications\Notifiable; use App\Notifications\SlackNotification; class SlackService { use Notifiable; public function send($message = "test") { $this->notify(new SlackNotification($message)); } protected function routeNotificationForSlack() { return env('SLACK_WEBHOOK_URL'); } }・routeNotificationForSlack routeNotificationFor○○の○○の部分で書かれたサービス名をもとに、Laravelが自動的にドライバ情報を読み込んでくれる
・send $this->notifyで、SlackNotificationを発火させてる。これで基本準備は完了したので、てきとうなRoute作って呼び出してみる。
web.phpRoute::get('/slackTest', function (){ (new \App\Services\SlackService())->send(); });こんな感じで出れば完了。
参考にさせていただいた記事
https://www.ritolab.com/entry/110
https://qiita.com/10monori/items/a78fb7e270b141c793b1
- 投稿日:2019-05-21T15:27:29+09:00
【30分クッキング】Laravelで投稿アプリの機能を作成
はじめに
Laravelで汎用的に開発を進められるようにするべく、
チュートリアル形式で記事を作成したのでご参考になれば幸いです。【目的】
・汎用的に使えるレシピを提供 → Laravelでの開発効率アップを目指すこんな方におすすめ
・Laravelを書籍などで一通り勉強された方
前提条件
・RESTful APIを利用したCRUD機能 ※分からない方はLaravelの公式ドキュメント参照
・VirtualBoxとVagrantで開発
・Vueは今回はなし
・認証はひとまずなし(記事テーブルに外部キーのフィールドのみ持たせておく)完成イメージ
【実装した機能】
・記事の投稿 ・記事の描画 ・記事の削除 ・詳細ページの描画所要時間:30分ほど
※すでにLaravelプロジェクトを構築した方に限る
※初回はいろいろインストール等に時間がかかりますLaravelプロジェクト構築
下記からさくっと環境構築してください
すでにされたことがある方なら10分くらいでできるはずです
Mac用の記事ですが、Windowsでも基本は同じです
https://qiita.com/7968/items/68b3566d92d2b007038e記事テーブル定義
postsテーブル
※テーブル名を任意に変更した場合、それ以降名前を変更してください
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| user_id | int(11) | NO | | NULL | |
| title | varchar(255) | NO | | NULL | |
| message | varchar(255) | NO | | NULL | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
+------------+------------------+------+-----+---------+----------------+手順レシピ
1.マイグレーションファイル生成〜編集〜マイグレート
マイグレーションファイル生成
$ php artisan make:migration create_posts_table
/database/migrations/xxxx_xx_xx_xxxxxx_create_posts_table.php// 中略 public function up() { Schema::create('posts', function (Blueprint $table) { $table->increments('id'); //追加したいデータ型とカラムを追加 $table->integer('user_id'); // 今回は使いませんが、リレーションするとき必要 $table->string('title'); $table->string('message'); $table->timestamps(); }); } // 中略マイグレート
$ php artisan migrate
2.モデル作成
$ php artisan make:model Post
※モデル名はキャメル記法の単数形/app/Post.php<?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model { // 初期設定を定義する protected $table = 'posts'; protected $guarded = array('id'); // 以下独自でいろいろ定義可能 // public function getData() // { // return $this->id. ": this is :" . $this->message; // } }「$guarded」に関してまとめられた記事です
https://qiita.com/kk_take/items/3e0639ed605f74c346193.コントローラー作成
$ php artisan make:controller PostController --resource
「--resource」をつけることでRESTfulなデータになります/Http/Controllers/PostController.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; // Eloquentを使うので必ず入れてください use App\Post; // Validatorを使うのに必要 use Validator; class PostController extends Controller { public function index() { $items = Post::all(); return view('post.index', ['items' => $items]); // ビューの描画 // return $items->toArray(); // JSONデータで描画 } // 描画はindexでしているので、不要 // public function create() // { // return view('post.create'); // } public function store(Request $request) { $post = new Post; $form = $request->all(); // 最低限なバリデーション処理です。ここでは特に説明はしません。 $rules = [ 'user_id' => 'integer|required', // 2項目以上条件がある場合は「 | 」を挟む 'title' => 'required', 'message' => 'required', ]; $message = [ 'user_id.integer' => 'System Error', 'user_id.message' => 'System Error', 'title.required'=> 'タイトルが入力されていません', 'message.required'=> 'メッセージが入力されていません' ]; $validator = Validator::make($form, $rules, $message); if($validator->fails()){ return redirect('/post') ->withErrors($validator) ->withInput(); }else{ // 本来は「$post->fill($form)->save();」で1行にまとめた方がスッキリします // なぜか上記書き方だとエラーになってしまいます // 分かる方、逆に教えていただけると幸いです unset($form['_token']); $post->user_id = $request->user_id; $post->title = $request->title; $post->message = $request->message; $post->save(); return redirect('/post'); } } public function show($id) { $item = Post::find($id); return view('post.show', ['item' => $item]); } // 描画はshowでしているので不要 // public function edit($id) // { // } // public function update(Request $request, $id) // { // UPDATE処理をビュー含めて下記に追加しました。 // } public function destroy($id) { $items = Post::find($id)->delete(); return redirect('/post'); } }RESTfulなチートシートはこちらを参照
https://qiita.com/fagai/items/a1bf55b6249aee03a6244.ルーティング設定
ルーティングを設定します。この1行で自動でCRUDに対応するルーティングを設定してくれます。
非常に便利でコードも見通しのいいものになります。/routes/web.php// RESTfulサービスのルーティング Route::resource('/post', 'PostController');5.ビューを作成する
まずはベースのBladeテンプレート
※一応Bootstrap入れておきます/views/layouts/postapp.blade.php<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>@yield('title')</title> <!-- <link href="{{ asset('css/app.css') }}" rel="stylesheet"> デフォルトCSS --> <!-- CDN Bootstrap --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <!-- /public/css/bootstrap.min.css --> <!-- <link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet"> --> <link href="{{ asset('css/post.css') }}" rel="stylesheet"> </head> <body> <div class="header"> <!-- header --> <h1>Laravel投稿アプリ</h1> </div> <div class="container"> <div class="content"> <h3>@yield('maincopy')</h3> @yield('content') </div> </div> <div class="footer"> <!-- footer --> </div> </body> </html>次にTopページ
/views/post/index.blade.php@extends('layouts.postapp') @section('title', '投稿アプリ') @section('content') @section('maincopy', '投稿してください') <!-- 投稿フォーム --> <form action="/post" method="post"> {{ csrf_field() }} <!-- value仮入れ(Userモデルとリレーションするのに必要) --> <input type="hidden" name="user_id" value="1"> @if($errors->has('title')) <div class="error_msg">{{ $errors->first('title') }}</div> @endif <input type="text" class="form" name="title" placeholder="タイトル" value="{{ old('title') }}"> @if($errors->has('message')) <div class="error_msg">{{ $errors->first('message') }}</div> @endif <div> <textarea class="form" name="message" placeholder="メッセージ">{{ old('message') }}</textarea> </div> <input type="submit" class="create" value="投 稿"> </form> <!-- 記事描画部分 --> @if(count($items) > 0) @foreach($items as $item) <div class="alert alert-primary" role="alert"> <a href="/post/{{ $item->id }}" class="alert-link">{{ $item->title }}</a> <form action="/post/{{ $item->id }}" method="POST"> {{ csrf_field() }} <input type="hidden" name="_method" value="DELETE"> <input type="submit" class="delete" value="削除"> </form> </div> @endforeach @else <div>投稿記事がありません</div> @endif @endsection最後に記事詳細ページ
/views/post/show.blade.php@extends('layouts.postapp') @section('title', '詳細記事') @section('content') @section('maincopy', '詳細記事') @if($item !== '') <div class="headcopy">Title</div><hr> <div class="text">{{ $item->title }}</div> <div class="headcopy">Message</div><hr> <div class="text">{{ $item->message }}</div> @endif <a href="/post"><img src="{{ asset('img/edit.svg') }}" class="add" alt="topへ"></a> @endsectionsrc="{{ asset('img/edit.svg') }}"の部分、
publicフォルダに「img」フォルダをつくり、そこにアイコン画像を入れてください
※UIはこちらのサイトから無料でダウンロードすることができます
https://www.ikonate.com/6.スタイルを調整する
/public/css/post.cssbody { width: 100%; background-color: #fff; } hr { margin: 0; padding: 0; } .header { color: #fff; text-align: center; background: #6495ed; margin: 0 0 20px 0; padding: 7vh; } .footer { font-size: 12px; color: #4169e1; text-align: center; margin: 50px 0 0 0; } h1 { color: #fff; font-size: 20px; font-weight: normal; } h3 { color: #4169e1; font-size: 16px; font-weight: normal; } .error_msg { color: #cd5c5c; font-size: 12px; margin: 10px 0 0 0; } .form { color: #4169e1; font-size: 12px; width: 100%; margin: 10px auto 10px; padding: 10px; border: none; outline: none; border-radius: 10px; box-sizing: border-box; box-shadow: 0 0 3px rgba(65,105,255,0.4); } .form:last-child { margin-bottom: 20px; } .form:focus { box-shadow: 0 0 7px #4169e1; } input[type=text] { height: 35px; } textarea { height: 50px; transition: 1s; } textarea:focus { height: 150px; } input[class=create] { width: 100%; font-size: 15px; font-weight: 100; color: #fff; margin: 0 auto 50px; padding: 5px 0 5px 0; background: #6495ed; border:1px solid #4169e1; border-radius: 5px; box-sizing: border-box; transition: 1s; } input[class=create]:hover { box-shadow: 0 0 7px #4169e1; opacity: .7; } input[class=delete] { font-size: 13px; font-weight: 100; color: #4169e1; margin: 5px 0 0 0; padding: 0; background: none; border: none; } img.add { width: 35px; background: #fff; padding: 5px; box-sizing: border-box; border-radius: 50%; position: absolute; top: 5px; right: 5px; transition: .5s; } img.add:hover { box-shadow: 0 0 7px #4169e1; opacity: .7; } .headcopy { color: #ccc; font-size: 15px; font-weight: bold; margin: 0 0 -6px 0; } .text { font-size: 15px; margin: 10px 0 20px 0; }CSSもシンプルにするため、モバイル版CSSのみにしています。
おのおので、良い感じのブレイクポイントのところでレスポンシブにしていただければと思います。
192.168.10.10/post
でアクセス機能追加
記事のUPDATE
/Http/Controllers/PostController.php// 中略 public function update(Request $request, $id) { $post = Post::find($id); $form = $request->all(); // バリデーションは省略。追加したい場合はcreateメソッドを参照してください。 unset($form['_token']); $post->user_id = $request->user_id; $post->title = $request->title; $post->message = $request->message; $post->save(); return redirect('/post'); } // 中略/views/post/show.blade.php<!--中略--> @if($item !== '') <div class="headcopy">Title</div><hr> <div class="text">{{ $item->title }}</div> <div class="headcopy">Message</div><hr> <div class="text">{{ $item->message }}</div> <!--ここから追加--> <form action="/post/{{$item->id}}" method="POST"> {{ csrf_field() }} <!-- value仮入れ(Userモデルとリレーションするのに必要) --> <input type="hidden" name="user_id" value="1"> <input type="text" class="form" name="title" placeholder="タイトル" value="{{ $item->title }}"> <div> <textarea class="form" name="message" placeholder="メッセージ">{{ $item->message }}</textarea> </div> <input type="hidden" name="_method" value="PUT"> <input type="submit" class="create" value="変 更"> </form> <!--ここまで追加--> @endif <!--中略-->あとがき
慣れればこの最低限の記事投稿機能を1時間もあれば実装できるかと思います。
この他にもUserモデルとのリレーション、画像投稿など出来次第、別ページを作成し、更新していきたいと思います。その際はこのページにURLリンクをつけますので、そちらからジャンプお願いします。もし、うまくいかない・分からない部分や、ここはこうした方が良いよと部分がございましたら、何なりとご意見お願いします。参考資料
参考書籍: PHPフレームワーク Laravel入門
https://blog.hiroyuki90.com/articles/laravel-books/
公式ドキュメント: https://readouble.com/laravel/
環境構築: https://qiita.com/7968/items/68b3566d92d2b007038e
RESTfulに関して: https://qiita.com/fagai/items/a1bf55b6249aee03a624
guardedに関して: https://qiita.com/kk_take/items/3e0639ed605f74c34619
UIアイコン提供サイト: https://www.ikonate.com/
- 投稿日:2019-05-21T15:27:29+09:00
Laravelで投稿アプリの機能を作成
はじめに
Laravelで汎用的に開発を進められるようにするべく、
チュートリアル形式で記事を作成したのでご参考になれば幸いです。【目的】
・汎用的に使えるレシピを提供 → Laravelでの開発効率アップを目指すこんな方におすすめ
・Laravelを書籍などで一通り勉強された方
前提条件
・RESTful APIを利用したCRUD機能 ※分からない方はLaravelの公式ドキュメント参照
・VirtualBoxとVagrantで開発
・Vueは今回はなし
・認証はひとまずなし(記事テーブルに外部キーのフィールドのみ持たせておく)完成イメージ
【実装した機能】
・記事の投稿 ・記事の描画 ・記事の削除 ・詳細ページの描画Laravelプロジェクト構築
下記からさくっと環境構築してください
すでにされたことがある方なら10分くらいでできるはずです
Mac用の記事ですが、Windowsでも基本は同じです
https://qiita.com/7968/items/68b3566d92d2b007038e記事テーブル定義
postsテーブル
※テーブル名を任意に変更した場合、それ以降名前を変更してください
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| user_id | int(11) | NO | | NULL | |
| title | varchar(255) | NO | | NULL | |
| message | varchar(255) | NO | | NULL | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
+------------+------------------+------+-----+---------+----------------+手順レシピ
1.マイグレーションファイル生成〜編集〜マイグレート
マイグレーションファイル生成
$ php artisan make:migration create_posts_table
/database/migrations/xxxx_xx_xx_xxxxxx_create_posts_table.php// 中略 public function up() { Schema::create('posts', function (Blueprint $table) { $table->increments('id'); //追加したいデータ型とカラムを追加 $table->integer('user_id'); // 今回は使いませんが、リレーションするとき必要 $table->string('title'); $table->string('message'); $table->timestamps(); }); } // 中略マイグレート
$ php artisan migrate
2.モデル作成
$ php artisan make:model Post
※モデル名はキャメル記法の単数形/app/Post.php<?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model { // 初期設定を定義する protected $table = 'posts'; protected $guarded = array('id'); // 以下独自でいろいろ定義可能 // public function getData() // { // return $this->id. ": this is :" . $this->message; // } }「$guarded」に関してまとめられた記事です
https://qiita.com/kk_take/items/3e0639ed605f74c346193.コントローラー作成
$ php artisan make:controller PostController --resource
「--resource」をつけることでRESTfulなデータになります/Http/Controllers/PostController.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; // Eloquentを使うので必ず入れてください use App\Post; // Validatorを使うのに必要 use Validator; class PostController extends Controller { public function index() { $items = Post::all(); return view('post.index', ['items' => $items]); // ビューの描画 // return $items->toArray(); // JSONデータで描画 } public function create() { return view('post.create'); } public function store(Request $request) { $post = new Post; $form = $request->all(); // 最低限なバリデーション処理です。ここでは特に説明はしません。 $rules = [ 'user_id' => 'integer|required', // 2項目以上条件がある場合は「 | 」を挟む 'title' => 'required', 'message' => 'required', ]; $message = [ 'user_id.integer' => 'System Error', 'user_id.message' => 'System Error', 'title.required'=> 'タイトルが入力されていません', 'message.required'=> 'メッセージが入力されていません' ]; $validator = Validator::make($form, $rules, $message); if($validator->fails()){ return redirect('/post') ->withErrors($validator) ->withInput(); }else{ // 本来は「$post->fill($form)->save();」で1行にまとめた方がスッキリします // なぜか上記書き方だとエラーになってしまいます // 分かる方、逆に教えていただけると幸いです unset($form['_token']); $post->user_id = $request->user_id; $post->title = $request->title; $post->message = $request->message; $post->save(); return redirect('/post'); } } public function show($id) { $item = Post::find($id); return view('post.show', ['item' => $item]); } // public function edit($id) // { // } // public function update(Request $request, $id) // { // UPDATE処理できたら更新しておきます // } public function destroy($id) { $items = Post::find($id)->delete(); return redirect('/post'); } }RESTfulなチートシートはこちらを参照
https://qiita.com/fagai/items/a1bf55b6249aee03a6244.ルーティング設定
ルーティングを設定します。この1行で自動でCRUDに対応するルーティングを設定してくれます。
非常に便利でコードも見通しのいいものになります。/routes/web.php// RESTfulサービスのルーティング Route::resource('/post', 'PostController');5.ビューを作成する
まずはベースのBladeテンプレート
※一応Bootstrap入れておきます/views/layouts/postapp.blade.php<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>@yield('title')</title> <!-- <link href="{{ asset('css/app.css') }}" rel="stylesheet"> デフォルトCSS --> <!-- CDN Bootstrap --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <!-- /public/css/bootstrap.min.css --> <!-- <link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet"> --> <link href="{{ asset('css/post.css') }}" rel="stylesheet"> </head> <body> <div class="header"> <!-- header --> <h1>Laravel投稿アプリ</h1> </div> <div class="container"> <div class="content"> <h3>@yield('maincopy')</h3> @yield('content') </div> </div> <div class="footer"> <!-- footer --> </div> </body> </html>次にTopページ
/views/post/index.blade.php@extends('layouts.postapp') @section('title', '投稿アプリ') @section('content') @section('maincopy', '投稿してください') <!-- 投稿フォーム --> <form action="/post" method="post"> {{ csrf_field() }} <!-- value仮入れ(Userモデルとリレーションするのに必要) --> <input type="hidden" name="user_id" value="1"> @if($errors->has('title')) <div class="error_msg">{{ $errors->first('title') }}</div> @endif <input type="text" class="form" name="title" placeholder="タイトル" value="{{ old('title') }}"> @if($errors->has('message')) <div class="error_msg">{{ $errors->first('message') }}</div> @endif <div> <textarea class="form" name="message" placeholder="メッセージ">{{ old('message') }}</textarea> </div> <input type="submit" class="create" value="投 稿"> </form> <!-- 記事描画部分 --> @if(count($items) > 0) @foreach($items as $item) <div class="alert alert-primary" role="alert"> <a href="/post/{{ $item->id }}" class="alert-link">{{ $item->title }}</a> <form action="/post/{{ $item->id }}" method="POST"> {{ csrf_field() }} <input type="hidden" name="_method" value="DELETE"> <input type="submit" class="delete" value="削除"> </form> </div> @endforeach @else <div>投稿記事がありません</div> @endif @endsection最後に記事詳細ページ
/views/post/show.blade.php@extends('layouts.postapp') @section('title', '詳細記事') @section('content') @section('maincopy', '詳細記事') @if($item !== '') <div class="headcopy">Title</div><hr> <div class="text">{{ $item->title }}</div> <div class="headcopy">Message</div><hr> <div class="text">{{ $item->message }}</div> @endif <a href="/post"><img src="{{ asset('img/edit.svg') }}" class="add" alt="topへ"></a> @endsectionsrc="{{ asset('img/edit.svg') }}"の部分、
publicフォルダに「img」フォルダをつくり、そこにアイコン画像を入れてください
※UIはこちらのサイトから無料でダウンロードすることができます
https://www.ikonate.com/6.スタイルを調整する
/public/css/post.cssbody { width: 100%; background-color: #fff; } hr { margin: 0; padding: 0; } .header { color: #fff; text-align: center; background: #6495ed; margin: 0 0 20px 0; padding: 7vh; } .footer { font-size: 12px; color: #4169e1; text-align: center; margin: 50px 0 0 0; } h1 { color: #fff; font-size: 20px; font-weight: normal; } h3 { color: #4169e1; font-size: 16px; font-weight: normal; } .error_msg { color: #cd5c5c; font-size: 12px; margin: 10px 0 0 0; } .form { color: #4169e1; font-size: 12px; width: 100%; margin: 10px auto 10px; padding: 10px; border: none; outline: none; border-radius: 10px; box-sizing: border-box; box-shadow: 0 0 3px rgba(65,105,255,0.4); } .form:last-child { margin-bottom: 20px; } .form:focus { box-shadow: 0 0 7px #4169e1; } input[type=text] { height: 35px; } textarea { height: 50px; transition: 1s; } textarea:focus { height: 150px; } input[class=create] { width: 100%; font-size: 15px; font-weight: 100; color: #fff; margin: 0 auto 50px; padding: 5px 0 5px 0; background: #6495ed; border:1px solid #4169e1; border-radius: 5px; box-sizing: border-box; transition: 1s; } input[class=create]:hover { box-shadow: 0 0 7px #4169e1; opacity: .7; } input[class=delete] { font-size: 13px; font-weight: 100; color: #4169e1; margin: 5px 0 0 0; padding: 0; background: none; border: none; } img.add { width: 35px; background: #fff; padding: 5px; box-sizing: border-box; border-radius: 50%; position: absolute; top: 5px; right: 5px; transition: .5s; } img.add:hover { box-shadow: 0 0 7px #4169e1; opacity: .7; } .headcopy { color: #ccc; font-size: 15px; font-weight: bold; margin: 0 0 -6px 0; } .text { font-size: 15px; margin: 10px 0 20px 0; }CSSもシンプルにするため、モバイル版CSSのみにしています。
おのおので、良い感じのブレイクポイントのところでレスポンシブにしていただければと思います。
192.168.10.10/post
でアクセスあとがき
慣れればこの最低限の記事投稿機能を1時間もあれば実装できるかと思います。
この他にも記事のUPDATEや、Userモデルとのリレーション、画像投稿など出来次第、こちらに更新していきたいと思います。もし、うまくいかない・分からない部分や、ここはこうした方が良いよと部分がございましたら、何なりとご意見お願いします。参考資料
参考書籍: PHPフレームワーク Laravel入門
https://blog.hiroyuki90.com/articles/laravel-books/
公式ドキュメント: https://readouble.com/laravel/
環境構築: https://qiita.com/7968/items/68b3566d92d2b007038e
RESTfulに関して: https://qiita.com/fagai/items/a1bf55b6249aee03a624
guardedに関して: https://qiita.com/kk_take/items/3e0639ed605f74c34619
UIアイコン提供サイト: https://www.ikonate.com/
- 投稿日:2019-05-21T15:27:29+09:00
【30分クッキング】Laravelで投稿アプリの機能を作成 ~CRUD編~
はじめに
Laravelで汎用的に開発を進められるようにするべく、
チュートリアル形式で記事を作成したのでご参考になれば幸いです。【目的】
・汎用的に使えるレシピを提供 → Laravelでの開発効率アップを目指すこんな方におすすめ
・Laravelを書籍などで一通り勉強された方
前提条件
・RESTful APIを利用したCRUD機能 ※分からない方はLaravelの公式ドキュメント参照
・VirtualBoxとVagrantで開発
・Vueは今回はなし
・認証はひとまずなし(記事テーブルに外部キーのフィールドのみ持たせておく)完成イメージ
【実装した機能】
・記事の投稿 ・記事の描画 ・記事の削除 ・詳細ページの描画
・[追加]記事の編集所要時間:30分ほど
※すでにLaravelプロジェクトを構築した方に限る
※初回はいろいろインストール等に時間がかかりますLaravelプロジェクト構築
下記からさくっと環境構築してください
すでにされたことがある方なら10分くらいでできるはずです
Mac用の記事ですが、Windowsでも基本は同じです
https://qiita.com/7968/items/68b3566d92d2b007038e記事テーブル定義
postsテーブル
※テーブル名を任意に変更した場合、それ以降名前を変更してください
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| user_id | int(11) | NO | | NULL | |
| title | varchar(255) | NO | | NULL | |
| message | varchar(255) | NO | | NULL | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
+------------+------------------+------+-----+---------+----------------+手順レシピ
1.マイグレーションファイル生成〜編集〜マイグレート
マイグレーションファイル生成
$ php artisan make:migration create_posts_table
/database/migrations/xxxx_xx_xx_xxxxxx_create_posts_table.php// 中略 public function up() { Schema::create('posts', function (Blueprint $table) { $table->increments('id'); //追加したいデータ型とカラムを追加 $table->integer('user_id'); // 今回は使いませんが、リレーションするとき必要 $table->string('title'); $table->string('message'); $table->timestamps(); }); } // 中略マイグレート
$ php artisan migrate
2.モデル作成
$ php artisan make:model Post
※モデル名はキャメル記法の単数形/app/Post.php<?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model { // 初期設定を定義する protected $table = 'posts'; protected $guarded = array('id'); // 以下独自でいろいろ定義可能 // public function getData() // { // return $this->id. ": this is :" . $this->message; // } }「$guarded」に関してまとめられた記事です
https://qiita.com/kk_take/items/3e0639ed605f74c346193.コントローラー作成
$ php artisan make:controller PostController --resource
「--resource」をつけることでRESTfulなデータになります/Http/Controllers/PostController.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; // Eloquentを使うので必ず入れてください use App\Post; // Validatorを使うのに必要 use Validator; class PostController extends Controller { public function index() { $items = Post::all(); return view('post.index', ['items' => $items]); // ビューの描画 // return $items->toArray(); // JSONデータで描画 } // 描画はindexでしているので、不要 // public function create() // { // return view('post.create'); // } public function store(Request $request) { $post = new Post; $form = $request->all(); // 最低限なバリデーション処理です。ここでは特に説明はしません。 $rules = [ 'user_id' => 'integer|required', // 2項目以上条件がある場合は「 | 」を挟む 'title' => 'required', 'message' => 'required', ]; $message = [ 'user_id.integer' => 'System Error', 'user_id.message' => 'System Error', 'title.required'=> 'タイトルが入力されていません', 'message.required'=> 'メッセージが入力されていません' ]; $validator = Validator::make($form, $rules, $message); if($validator->fails()){ return redirect('/post') ->withErrors($validator) ->withInput(); }else{ // 本来は「$post->fill($form)->save();」で1行にまとめた方がスッキリします // なぜか上記書き方だとエラーになってしまいます // 分かる方、逆に教えていただけると幸いです unset($form['_token']); $post->user_id = $request->user_id; $post->title = $request->title; $post->message = $request->message; $post->save(); return redirect('/post'); } } public function show($id) { $item = Post::find($id); return view('post.show', ['item' => $item]); } // 描画はshowでしているので不要 // public function edit($id) // { // } // public function update(Request $request, $id) // { // UPDATE処理をビュー含めて下記に追加しました。 // } public function destroy($id) { $items = Post::find($id)->delete(); return redirect('/post'); } }RESTfulなチートシートはこちらを参照
https://qiita.com/fagai/items/a1bf55b6249aee03a6244.ルーティング設定
ルーティングを設定します。この1行で自動でCRUDに対応するルーティングを設定してくれます。
非常に便利でコードも見通しのいいものになります。/routes/web.php// RESTfulサービスのルーティング Route::resource('/post', 'PostController');5.ビューを作成する
まずはベースのBladeテンプレート
※一応Bootstrap入れておきます/views/layouts/postapp.blade.php<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>@yield('title')</title> <!-- <link href="{{ asset('css/app.css') }}" rel="stylesheet"> デフォルトCSS --> <!-- CDN Bootstrap --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <!-- /public/css/bootstrap.min.css --> <!-- <link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet"> --> <link href="{{ asset('css/post.css') }}" rel="stylesheet"> </head> <body> <div class="header"> <!-- header --> <h1>Laravel投稿アプリ</h1> </div> <div class="container"> <div class="content"> <h3>@yield('maincopy')</h3> @yield('content') </div> </div> <div class="footer"> <!-- footer --> </div> </body> </html>次にTopページ
/views/post/index.blade.php@extends('layouts.postapp') @section('title', '投稿アプリ') @section('content') @section('maincopy', '投稿してください') <!-- 投稿フォーム --> <form action="/post" method="post"> {{ csrf_field() }} <!-- value仮入れ(Userモデルとリレーションするのに必要) --> <input type="hidden" name="user_id" value="1"> @if($errors->has('title')) <div class="error_msg">{{ $errors->first('title') }}</div> @endif <input type="text" class="form" name="title" placeholder="タイトル" value="{{ old('title') }}"> @if($errors->has('message')) <div class="error_msg">{{ $errors->first('message') }}</div> @endif <div> <textarea class="form" name="message" placeholder="メッセージ">{{ old('message') }}</textarea> </div> <input type="submit" class="create" value="投 稿"> </form> <!-- 記事描画部分 --> @if(count($items) > 0) @foreach($items as $item) <div class="alert alert-primary" role="alert"> <a href="/post/{{ $item->id }}" class="alert-link">{{ $item->title }}</a> <form action="/post/{{ $item->id }}" method="POST"> {{ csrf_field() }} <input type="hidden" name="_method" value="DELETE"> <input type="submit" class="delete" value="削除"> </form> </div> @endforeach @else <div>投稿記事がありません</div> @endif @endsection最後に記事詳細ページ
/views/post/show.blade.php@extends('layouts.postapp') @section('title', '詳細記事') @section('content') @section('maincopy', '詳細記事') @if($item !== '') <div class="headcopy">Title</div><hr> <div class="text">{{ $item->title }}</div> <div class="headcopy">Message</div><hr> <div class="text">{{ $item->message }}</div> @endif <a href="/post"><img src="{{ asset('img/edit.svg') }}" class="add" alt="topへ"></a> @endsectionsrc="{{ asset('img/edit.svg') }}"の部分、
publicフォルダに「img」フォルダをつくり、そこにアイコン画像を入れてください
※UIはこちらのサイトから無料でダウンロードすることができます
https://www.ikonate.com/6.スタイルを調整する
/public/css/post.cssbody { width: 100%; background-color: #fff; } hr { margin: 0; padding: 0; } .header { color: #fff; text-align: center; background: #6495ed; margin: 0 0 20px 0; padding: 7vh; } .footer { font-size: 12px; color: #4169e1; text-align: center; margin: 50px 0 0 0; } h1 { color: #fff; font-size: 20px; font-weight: normal; } h3 { color: #4169e1; font-size: 16px; font-weight: normal; } .error_msg { color: #cd5c5c; font-size: 12px; margin: 10px 0 0 0; } .form { color: #4169e1; font-size: 12px; width: 100%; margin: 10px auto 10px; padding: 10px; border: none; outline: none; border-radius: 10px; box-sizing: border-box; box-shadow: 0 0 3px rgba(65,105,255,0.4); } .form:last-child { margin-bottom: 20px; } .form:focus { box-shadow: 0 0 7px #4169e1; } input[type=text] { height: 35px; } textarea { height: 50px; transition: 1s; } textarea:focus { height: 150px; } input[class=create] { width: 100%; font-size: 15px; font-weight: 100; color: #fff; margin: 0 auto 50px; padding: 5px 0 5px 0; background: #6495ed; border:1px solid #4169e1; border-radius: 5px; box-sizing: border-box; transition: 1s; } input[class=create]:hover { box-shadow: 0 0 7px #4169e1; opacity: .7; } input[class=delete] { font-size: 13px; font-weight: 100; color: #4169e1; margin: 5px 0 0 0; padding: 0; background: none; border: none; } img.add { width: 35px; background: #fff; padding: 5px; box-sizing: border-box; border-radius: 50%; position: absolute; top: 5px; right: 5px; transition: .5s; } img.add:hover { box-shadow: 0 0 7px #4169e1; opacity: .7; } .headcopy { color: #ccc; font-size: 15px; font-weight: bold; margin: 0 0 -6px 0; } .text { font-size: 15px; margin: 10px 0 20px 0; }CSSもシンプルにするため、モバイル版CSSのみにしています。
おのおので、良い感じのブレイクポイントのところでレスポンシブにしていただければと思います。
192.168.10.10/post
でアクセス機能追加
記事のUPDATE
/Http/Controllers/PostController.php// 中略 public function update(Request $request, $id) { $post = Post::find($id); $form = $request->all(); // バリデーションは省略。追加したい場合はcreateメソッドを参照してください。 unset($form['_token']); $post->user_id = $request->user_id; $post->title = $request->title; $post->message = $request->message; $post->save(); return redirect('/post'); } // 中略/views/post/show.blade.php<!--中略--> @if($item !== '') <div class="headcopy">Title</div><hr> <div class="text">{{ $item->title }}</div> <div class="headcopy">Message</div><hr> <div class="text">{{ $item->message }}</div> <!--ここから追加--> <form action="/post/{{$item->id}}" method="POST"> {{ csrf_field() }} <!-- value仮入れ(Userモデルとリレーションするのに必要) --> <input type="hidden" name="user_id" value="1"> <input type="text" class="form" name="title" placeholder="タイトル" value="{{ $item->title }}"> <div> <textarea class="form" name="message" placeholder="メッセージ">{{ $item->message }}</textarea> </div> <input type="hidden" name="_method" value="PUT"> <input type="submit" class="create" value="変 更"> </form> <!--ここまで追加--> @endif <!--中略-->あとがき
慣れればこの最低限の記事投稿機能を1時間もあれば実装できるかと思います。
この他にもUserモデルとのリレーション、画像投稿など出来次第、別ページを作成し、更新していきたいと思います。その際はこのページにURLリンクをつけますので、そちらからジャンプお願いします。もし、うまくいかない・分からない部分や、ここはこうした方が良いよと部分がございましたら、何なりとご意見お願いします。リレーション編はこちら
https://qiita.com/ProgramingDai/items/249acc8894079ee58268参考資料
参考書籍: PHPフレームワーク Laravel入門
https://blog.hiroyuki90.com/articles/laravel-books/
公式ドキュメント: https://readouble.com/laravel/
環境構築: https://qiita.com/7968/items/68b3566d92d2b007038e
RESTfulに関して: https://qiita.com/fagai/items/a1bf55b6249aee03a624
guardedに関して: https://qiita.com/kk_take/items/3e0639ed605f74c34619
UIアイコン提供サイト: https://www.ikonate.com/