Homestead をリロードしようとしたらエラーになる
What?
- カフェに行ってPCを開いて、起動しっぱなしのHomesteadサーバにアクセスしたらエラー
- vagrantからリロードしても以下のエラーが出て立ち上がらない
$ vagrant reload ==> homestead-7: Attempting graceful shutdown of VM... ==> homestead-7: Checking if box 'laravel/homestead' is up to date... ==> homestead-7: Clearing any previously set forwarded ports... ==> homestead-7: Clearing any previously set network interfaces... The specified host network collides with a non-hostonly network! This will cause your specified IP to be inaccessible. Please change the IP or name of your host only network so that it no longer matches that of a bridged or non-hostonly network.
Why?
英語を読もう(雑訳)
- ホストオンリーではないネットワークで、特定のホストネットワークが衝突してます
- これは、あなたが設定したIPにアクセス出来ないということです
- そのホストはブリッジされているもしくはホストオンリーではないネットワークにおいて、もうマッチしていないので、あなたのホストオンリーネットワークのIPか名前を変えてください。
つまりは、外で作業を初めて、今のIP(homesteadのデフォルトIP: 192.168.10.10)が他の人と被ったから
Solution
.homestead/Homestead.yaml
ip: "192.168.10.10"
を
ip: "192.168.10.11"
とかに変更する。
- /etc/hosts も変更することを忘れずに
Laravel 5.4: Model, Controller, Viewワークフロー
Why?
- Articleの一覧、詳細を作ることで、一通りのModel, Controller, Viewワークフローを流す
How to
Articleの一覧を作る
app/Http/routes.php
にRoutingを追加
Route::get('articles', 'ArticlesController@index');
- Controllerを追加 (laravel 5.2から
–plain
オプションはデフォルトになったので不要)app/Http/Controllers/ArticlesController.php
が追加される
$ php artisan make:controller ArticlesController
app/Http/Controllers/ArticlesController.php
にindexメソッドを追加 (まずはviewに渡さずにプレーンに表示)
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Article; class ArticlesController extends Controller { public function index() { $articles = Article::all(); return $articles; } }
- プレーンなレスポンスが帰ってくる
[ { id: 1 title: "My Update First Article" body: "Lorem ipsum" ... } ]
app/Http/Controllers/ArticlesController.phpView
からViewに渡す
public function index() { $articles = Article::all(); return view('articles.index', compact('articles')); }
- View
resources/views/articles/index.blade.php
を追加
@extends('app') @section('content') <h1>Articles</h1> <hr /> @foreach ($articles as $article) <article> <h2>{{ $article->title }}</h2> <div class="body">{{ $article->body }}</div> </article> @endforeach @stop
Articleの詳細を作る
app/Http/routes.php
にRoutingを追加
Route::get('articles/{id}', 'ArticlesController@show');
app/Http/Controllers/ArticlesController.php
にshowメソッドを追加
public function show($id) { $article = Article::findOrFail($id); return view('articles.show', compact('article')); }
- View
resources/views/articles/show.blade.php
を追加
@extends('app') @section('content') <h1>{{ $article->title }}</h1> <article> <div class="body">{{ $article->body }}</div> </article> @stop
一覧と詳細ページを繋げる
resources/views/articles/show.blade.php
にリンク追加
@extends('app') @section('content') <h1>{{ $article->title }}</h1> <article> <div class="body">{{ $article->body }}</div> </article> <a href="/articles/">< Back to list</a> @stop
resources/views/articles/index.blade.php
にリンク追加
@extends('app') @section('content') <h1>Articles</h1> <hr /> @foreach ($articles as $article) <article> <h2><a href="/articles/{{ $article->id }}">{{ $article->title }}</h2></a> <div class="body">{{ $article->body }}</div> </article> @endforeach @stop
参考
Laravel 5.4: Eloquent ORMを使ってみる
What?
- Eloquent ORM: Laravel5にデフォルトで組み込まれているORマッパー
- RailsのActive Recodeみたいに使える
How to
DBにモデルを保存
- モデルを作る ->
app/Article.php
ができている
$ php artisan make:model Article $ cat app/Article.php <?php namespace App; use Illuminate\Database\Eloquent\Model; class Article extends Model { // }
- モデルができているかtinkerで確認
$ php artisan tinker >>> $article = new App\Article; => App\Article {#668}
- モデルを使う (オブジェクトを作って、値を入れる)
>>> $article = new App\Article; => App\Article {#673} >>> $article->title = 'My First Article'; => "My First Article" >>> $article->body = 'Lorem ipsum'; => "Lorem ipsum" >>> $article->published_at = Carbon\Carbon::now(); => Carbon\Carbon {#682 +"date": "2017-03-04 11:53:09.134952", +"timezone_type": 3, +"timezone": "UTC", } >>> $article; => App\Article {#673 title: "My First Article", body: "Lorem ipsum", published_at: Carbon\Carbon {#682 +"date": "2017-03-04 11:53:09.134952", +"timezone_type": 3, +"timezone": "UTC", }, }
- 作ったオブジェクトをセーブする
>>> App\Article::all()->toArray(); => [] >>> $article->save(); => true >>> App\Article::all()->toArray(); => [ [ "id" => 1, "title" => "My First Article", "body" => "Lorem ipsum", "created_at" => "2017-03-04 11:53:44", "updated_at" => "2017-03-04 11:53:44", "published_at" => "2017-03-04 11:53:09", ], ]
- MySQL上でも確認
$ mysql --user=homestead --password=secret homestead mysql> select * from articles\G; *************************** 1. row *************************** id: 1 title: My First Article body: Lorem ipsum created_at: 2017-03-04 11:53:44 updated_at: 2017-03-04 11:53:44 published_at: 2017-03-04 11:53:09 1 row in set (0.00 sec)
DBからモデルを読み込みアップデートしてみる
- tinker でDBから情報を1行読み込んで、更新後、セーブする
>>> $article = App\Article::all()->first(); => App\Article {#689 id: 1, title: "My First Article", body: "Lorem ipsum", created_at: "2017-03-04 11:53:44", updated_at: "2017-03-04 11:53:44", published_at: "2017-03-04 11:53:09", } >>> $article->title = 'My First Article Updated'; => "My First Article Updated" >>> $article->save(); => true
- DBを確認
mysql> select * from articles\G; *************************** 1. row *************************** id: 1 title: My First Article Updated body: Lorem ipsum created_at: 2017-03-04 11:53:44 updated_at: 2017-03-04 12:09:32 published_at: 2017-03-04 11:53:09 1 row in set (0.00 sec)
色々な方法でデータを検索する
>>> App\Article::find(1); => App\Article {#684 id: 1, title: "My First Article Updated", body: "Lorem ipsum", created_at: "2017-03-04 11:53:44", updated_at: "2017-03-04 12:09:32", published_at: "2017-03-04 11:53:09", } >>> App\Article::where('body', 'Lorem ipsum')->get(); => Illuminate\Database\Eloquent\Collection {#656 all: [ App\Article {#692 id: 1, title: "My First Article Updated", body: "Lorem ipsum", created_at: "2017-03-04 11:53:44", updated_at: "2017-03-04 12:09:32", published_at: "2017-03-04 11:53:09", }, ], } >>> App\Article::where('body', 'Lorem ipsum')->first(); => App\Article {#693 id: 1, title: "My First Article Updated", body: "Lorem ipsum", created_at: "2017-03-04 11:53:44", updated_at: "2017-03-04 12:09:32", published_at: "2017-03-04 11:53:09", }
createメソッドを使ってみる
createメソッドはまとめて値を入力できるので便利
App\Article::create()
でまとめて作ろうとするとMassAssignmentExceptionエラーが出る
>>> $article = App\Article::create(['title' => 'New Article', 'body' => 'Lorem ipsum', 'published_at' => Carbon\Carbon::now()]); Illuminate\Database\Eloquent\MassAssignmentException with message 'title'
app/Article.php
モデルを修正する
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Article extends Model { protected $fillable = [ // 'title', 'body', 'published_at' ]; }
- ん?まだ、MassAssignmentExceptionエラーが出る
>>> $article = App\Article::create(['title' => 'New Article', 'body' => 'Lorem ipsum', 'published_at' => Carbon\Carbon::now()]); Illuminate\Database\Eloquent\MassAssignmentException with message 'title'
- tinkerを立ち上げなおしてリトライ。できた。
>>> $article = App\Article::create(['title' => 'New Article', 'body' => 'Lorem ipsum', 'published_at' => Carbon\Carbon::now()]); => App\Article {#670 title: "New Article", body: "Lorem ipsum", published_at: Carbon\Carbon {#661 +"date": "2017-03-04 12:17:28.029855", +"timezone_type": 3, +"timezone": "UTC", }, updated_at: "2017-03-04 12:17:28", created_at: "2017-03-04 12:17:28", id: 2, }
参考
php artisan tinker の使い方
Why?
- Laravel チュートリアルやってて、突然出現した
- pryっぽいけど、なにができるのか疑問
What?
- https://github.com/laravel/tinker
- REPL (Read-Eval-Print Loop) 。対話的シェル。
- コンソールにどういう状況のものが表示されるのか?
- ラッパー
- 2016〜: tinkerコマンドはPsyPH( http://psysh.org/ )のラッパー(tinkerのcomposer.json参照)
- Oct 23, 2015で開発が止まってる: tinkerコマンドは Boris ( https://github.com/borisrepl/boris )を使っていた
How to use?
- プロジェクトディレクトリ内で
$ php artisan tinker
すると立ち上がる。
$ php artisan tinker Psy Shell v0.8.1 (PHP 7.1.1-1+deb.sury.org~xenial+1 — cli) by Justin Hileman New version is available (current: v0.8.1, latest: v0.8.2) >>>
- phpコマンドを逐次実行できる (
hoge
は標準出力、=> null
は返り値)
>>> echo "hoge"; hoge⏎ => null
- tinderコマンドは色々ある
>>> help help Show a list of commands. Type `help [foo]` for information about [foo]. Aliases: ? ls List local, instance or class variables, methods and constants. Aliases: list, dir dump Dump an object or primitive. doc Read the documentation for an object, class, constant, method or property. Aliases: rtfm, man show Show the code for an object, class, constant, method or property. wtf Show the backtrace of the most recent exception. Aliases: last-exception, wtf? whereami Show where you are in the code. throw-up Throw an exception out of the Psy Shell. trace Show the current call stack. buffer Show (or clear) the contents of the code input buffer. Aliases: buf clear Clear the Psy Shell screen. history Show the Psy Shell history. Aliases: hist exit End the current session and return to caller. Aliases: quit, q clear-compiled Remove the compiled class file down Put the application into maintenance mode env Display the current framework environment migrate Run the database migrations optimize Optimize the framework for better performance up Bring the application out of maintenance mode inspire Display an inspiring quote
- tinkerコマンド例: グローバル変数一覧表示させる
>>> ls -gl Global Variables: $app Illuminate\Foundation\Application {#3 …15} $argc 2 $argv [ …2] $GLOBALS [ …13] $input Symfony\Component\Console\Input\ArgvInput {#20} $kernel App\Console\Kernel {#22} $_COOKIE [] $_FILES [] $_GET [] $_POST [] $_REQUEST [] $_SERVER [ …35] $__composer_autoload_files [ …8]
参照
Laravel 5.4: DBマイグレーション
What?
- LaravelでのDBマイグレーションの仕方
Why?
- そもそもなぜDBマイグレーションが必要なのか?
Migration
- 保存場所
database/migrations/
$ php artisan migrate Migration table created successfully. Migrated: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_100000_create_password_resets_table
$ mysql --user=homestead --password=secret homestead mysql> show tables; +---------------------+ | Tables_in_homestead | +---------------------+ | migrations | | password_resets | | users | +---------------------+ 3 rows in set (0.00 sec) mysql> desc migrations; +-----------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | migration | varchar(255) | NO | | NULL | | | batch | int(11) | NO | | NULL | | +-----------+------------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec) mysql> desc users; +----------------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | varchar(255) | NO | | NULL | | | email | varchar(255) | NO | UNI | NULL | | | password | varchar(255) | NO | | NULL | | | remember_token | varchar(100) | YES | | NULL | | | created_at | timestamp | YES | | NULL | | | updated_at | timestamp | YES | | NULL | | +----------------+------------------+------+-----+---------+----------------+ 7 rows in set (0.00 sec) mysql> desc password_resets; +------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+-------+ | email | varchar(255) | NO | MUL | NULL | | | token | varchar(255) | NO | MUL | NULL | | | created_at | timestamp | YES | | NULL | | +------------+--------------+------+-----+---------+-------+ 3 rows in set (0.00 sec)
Rollback
$ php artisan migrate:status +------+------------------------------------------------+ | Ran? | Migration | +------+------------------------------------------------+ | Y | 2014_10_12_000000_create_users_table | | Y | 2014_10_12_100000_create_password_resets_table | +------+------------------------------------------------+ $ php artisan migrate:rollback Rolled back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_000000_create_users_table $ php artisan migrate:status +------+------------------------------------------------+ | Ran? | Migration | +------+------------------------------------------------+ | N | 2014_10_12_000000_create_users_table | | N | 2014_10_12_100000_create_password_resets_table | +------+------------------------------------------------+
Make migration
$ php artisan make:migration create_articles_table --create="articles" Created Migration: 2017_02_14_184315_create_articles_table $ less database/migrations/2017_02_14_184315_create_articles_table.php <?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateArticlesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('articles', function (Blueprint $table) { // ここから $table->increments('id'); $table->string('title'); $table->text('body'); $table->timestamps(); $table->timestamp('published_at')->useCurrent(); // ここまで追加 }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('articles'); } }
Edit migration
php artisan migrate
mysql> desc articles; +--------------+------------------+------+-----+-------------------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+------------------+------+-----+-------------------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | title | varchar(255) | NO | | NULL | | | body | text | NO | | NULL | | | created_at | timestamp | YES | | NULL | | | updated_at | timestamp | YES | | NULL | | | published_at | timestamp | NO | | CURRENT_TIMESTAMP | | | exceprt | text | NO | | NULL | | +--------------+------------------+------+-----+-------------------+----------------+ 7 rows in set (0.00 sec)
参考
Laravel 5.4: DBマイグレーションでエラーになる
What?
このバージョンで
laravel vagrant master %$ php artisan --version Laravel Framework 5.4.10 laravel vagrant master %$ mysql --version mysql Ver 14.14 Distrib 5.7.17, for Linux (x86_64) using EditLine wrapper laravel vagrant master %$ php -v PHP 7.1.1-1+deb.sury.org~xenial+1 (cli) (built: Jan 20 2017 09:20:20) ( NTS ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies with Zend OPcache v7.1.1-1+deb.sury.org~xenial+1, Copyright (c) 1999-2017, by Zend Technologies with blackfire v1.14.3~linux-x64-non_zts71, https://blackfire.io, by Blackfireio Inc.
このmigrationファイルを
/** * Run the migrations. * * @return void */ public function up() { Schema::create('articles', function (Blueprint $table) { // ここから $table->increments('id'); $table->string('title'); $table->text('body'); $table->timestamps(); $table->timestamp('published_at'); // ここまで追加 }); }
migrateすると、エラーになる
$ php artisan migrate [Illuminate\Database\QueryException] SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'published_at' (SQL: create table `articles` (`id ` int unsigned not null auto_increment primary key, `title` varchar(255) not null, `body` text not null, `created_at` timestamp nul l, `updated_at` timestamp null, `published_at` timestamp not null) default character set utf8mb4 collate utf8mb4_unicode_ci) [PDOException] SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'published_at'
Solution
このmigrationファイルをちょっと書き換え、
/** * Run the migrations. * * @return void */ public function up() { Schema::create('articles', function (Blueprint $table) { // ここから $table->increments('id'); $table->string('title'); $table->text('body'); $table->timestamps(); $table->timestamp('published_at')->useCurrent(); // ここ追加 // ここまで追加 }); }
こうする
$ php artisan migrate:refresh --seed Rolled back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_100000_create_password_resets_table Migrated: 2017_02_14_184315_create_articles_table Migrated: 2017_02_23_172823_add_excerpt_to_articles_table
Why?
- マイグレーションを全部ロールバックし、再度実行する力技コマンド
php artisan migrate:refresh --seed
を使って、強制帳消し published_at
がnot null
なのに値が入ってなかったので、useCurrent()
を使って突っ込んだ
失敗例
published_at
だけ触ればいいのに、その前のtimestampも色々いじってしまった結果。
laravel vagrant master %$ php artisan migrate [Symfony\Component\Debug\Exception\FatalThrowableError] Call to a member function useCurrent() on null laravel vagrant master *%$ php artisan migrate [Symfony\Component\Debug\Exception\FatalThrowableError] Call to a member function default() on null laravel vagrant master *%$ php artisan migrate [Symfony\Component\Debug\Exception\FatalThrowableError] Call to a member function nullable() on null
config/database.phpの確認したけど、ちゃんとstrictになってた
'strict' => true,