- 投稿日:2019-03-24T17:27:57+09:00
LaravelのSQL動作確認(Laravel学習メモ#3-2)
- 投稿日:2019-03-24T17:27:57+09:00
LaravelのSQL動作確認方法(Laravel学習メモ#3-2)
◆実行されるSQL文確認
User::where('name', '山田')->toSql();◆実行されたSQLを一気に確認
DB::enableQueryLog();//SQL保存有効 $userList = User::where('name', '山田')->get(); $foodList = Food::where('name', 'ラーメン')->get(); dd(DB::getQueryLog());//DB::enableQueryLog();以降に実行されたクエリ確認 DB::disableQueryLog();//SQL保存無効実行された処理を保存したい場合などもDB::getQueryLog()は活躍しそう
- 投稿日:2019-03-24T16:59:49+09:00
laravel Eloquentと少しModelについて個人的メモ(Laravel学習メモ#3-1)
◆Modelクラス
$guarded = ['id', 'created_at']; 編集不可のものを指定する
◆findメソッド
findでデータがない場合を考慮している処理を入れている場合はいいが、それが考慮されていない場合はfindOrFailを使う
try{ findOrFail }catch(ModelNotFoundException $e){}◆where
汎用的なメソッドを作成するときにwhere('カラム名', 値)を使うが、それ以外は
whereカラム名(値)で検索したほうが可読性が上がるかもしれない
例:whereName('山田')◆create・save・insert
https://qiita.com/katsunory/items/87a73297f44a65f1474f
◆物理削除
delete()もしくはdestory() destoryはidで指定する
◆論理削除
マイグレーションファイルに
$table->softDeletes();テーブルにdeleted_atが追加される。そのマイグレーションファイルのテーブルに対応したModelクラスに
use SoftDeletes;を追加しておく。
こうしておくとdelete()・destroy()を使用した際に、自動的にdeleted_atカラムに
削除時間が登録されて、データを取得する際に、自動で含まれなくなる。
例 User::get();取得方法User::withTrashed()->get; 削除済みを含むすべてのデータ User::onlyTrashed()->get();削除済みのみのデータ◆リレーション
1対1 hasOne・belongsTo
hasOne
つなげる元のModelクラスに
hasOne(つなげ先のModel, 内部キー, 外部キー);belongsTo
つなげられるModelクラスに
belongsTo(つなげ元のModel, 内部キー, 外部キー);内部キーと外部キーは省略することも可能で、省略時
内部キーは「モデル名_id」、外部キーは「id」が適用される。一対多 hasMany
hasManyは基本的にhasOneと指定方法は同じでデータの在り方が1対1なのか1対多の違いだけで、引数も同じ
- 投稿日:2019-03-24T16:18:13+09:00
Laravel5.4以上でGD Library extension not available with this PHP installation.のエラーが出た時の対処法
環境
PHP:v7.0.31
Laravel:v5.5
IDE:cloud9エラー内容
composer require intervention/imageも実行した。
config/app.php//provider 'Intervention\Image\ImageServiceProvider', //aliases 'Image' => 'Intervention\Image\Facades\Image',この2つも追加した。
いざアップロードすると
Driver.phpGD Library extension not available with this PHP installation.このエラーが出る。
なんと
実は、「Intervention/image」はPHP5.4以上で画像処理ライブラリのGDまたはImageMagickがインストールされている必要があるそうです。てことでGDをインストールします。
sudo apt-get update sudo apt-get install php7.0-gd以上2つのコマンドをターミナルでうち、apache再起動すれば動くと思います。
- 投稿日:2019-03-24T16:18:13+09:00
LaravelでGD Library extension not available with this PHP installation.のエラーが出た時の対処法
環境
PHP:v7.0.31
Laravel:v5.5
IDE:cloud9エラー内容
composer require intervention/imageも実行した。
config/app.php//provider Intervention\Image\ImageServiceProvider::class, //aliases 'Image' => Intervention\Image\Facades\Image::class,この2つも追加した。
app/http/Controllers/PhotosController.phpuse Image;も対象のコントローラのトップに追加してある。
しかしながら、以下Driver.phpGD Library extension not available with this PHP installation.このエラーが出る。
なんと
実は、「Intervention/image」はPHP5.4以上で画像処理ライブラリのGDまたはImageMagickがインストールされている必要があるそうです。てことでGDをインストールします。
sudo apt-get update sudo apt-get install php7.0-gd以上2つのコマンドをターミナルでうち、apache再起動すれば動くと思います。
- 投稿日:2019-03-24T13:20:35+09:00
リレーションはメソッドで定義したはずが、プロパティアクセスで動作する謎を解明する(Laravel)
前提
Bookというモデルには、detail()というメソッドが定義してあるとする。この定義によりBookモデルとBookdetailモデルが、「bookdetail_idとid」を通して、1対1に結合(hasOne)していることになる。
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Book extends Model { public function detail(){ return $this->hasOne('\App\Bookdetail','id','bookdetail_id'); } }下記は、Bookモデルからid=1であるもののbookdetail_idを通して、Bookdetailモデルからisbnを出力するコードである。
class TestController extends Controller { public function test(){ $book = \App\Book::find(1); echo $book->detail->isbn; } }疑問点
先ほどのBookモデルでは、detail()とメソッドとして定義したはずだ。しかし、このコードでは、->detailとプロパティアクセスの形になっている。どこにもメソッドとして実行する記述はない。いったい何が起こっているのだろう?
Laravelのコアファイルを深掘りする
それでは、Laravelのコアファイルを一つずつ辿っていきたい。
本記事の動作前提となるファイルは下記に用意してあるので、自分でサンプルデータを作るのが面倒な方は、適宜利用いただきたい。
https://github.com/3tomcha/qiita->detailとはつまり何をしているのか
まずはアクセスされる側の$bookの型を調べて見よう。dd()を使って出力するとBook型とわかる。(これは大方の予想通りであろう)
つまり->detailの正体を知るには、\App\Bookを調べるのが良さそうだと検討がつく。<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class TestController extends Controller { public function test(){ $book = \App\Book::find(1); dd($book); echo $book->detail->isbn; } }さてApp\Bookをみてみると、直接関係ありそうな記述はない。よって、Illuminate\Database\Eloquent\Modelを辿ってみる。
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Book extends Model { public function detail(){ return $this->hasOne('\App\Bookdetail','id','bookdetail_id'); } }Illuminate\Database\Eloquent\Model をみると、気になる記述が見つかる。__getはマジックメソッドと呼ばれるもので、アクセスできないプロパティにアクセスした時に呼ばれるものだ。これが働いているのではと検討がつく。実際にdump()を使ってみると、__getは2回行われており、1回目はBookdetailオブジェクト、2回目は結果のisbnである"3333333333333"を返している。
/** * Dynamically retrieve attributes on the model. * * @param string $key * @return mixed */ public function __get($key) { return $this->getAttribute($key); }次に__getで行われている getAttribute()を辿って見よう。
Illuminate\Database\Eloquent\Concerns\HasAttrubute.php に定義されている。
今回は、hasOneというリレーションを定義しているため、最後の return $this->getRelationValue($key); が動いていそうだと検討を付けて、さらに進む。/** * Get an attribute from the model. * * @param string $key * @return mixed */ public function getAttribute($key) { if (! $key) { return; } // If the attribute exists in the attribute array or has a "get" mutator we will // get the attribute's value. Otherwise, we will proceed as if the developers // are asking for a relationship's value. This covers both types of values. if (array_key_exists($key, $this->attributes) || $this->hasGetMutator($key)) { return $this->getAttributeValue($key); } // Here we will determine if the model base class itself contains this given key // since we don't want to treat any of those methods as relationships because // they are all intended as helper methods and none of these are relations. if (method_exists(self::class, $key)) { return; } return $this->getRelationValue($key); }getRelationValueは同じく Illuminate\Database\Eloquent\Concerns\HasAttrubute.php に定義されている。最下部にあるgetRelationshipFromMethod を辿って見よう。
/** * Get a relationship. * * @param string $key * @return mixed */ public function getRelationValue($key) { // If the key already exists in the relationships array, it just means the // relationship has already been loaded, so we'll just return it out of // here because there is no need to query within the relations twice. if ($this->relationLoaded($key)) { return $this->relations[$key]; } // If the "attribute" exists as a method on the model, we will just assume // it is a relationship and will load and return results from the query // and hydrate the relationship's value on the "relationships" array. if (method_exists($this, $key)) { return $this->getRelationshipFromMethod($key); } }getRelationshipFromMethodは同じく Illuminate\Database\Eloquent\Concerns\HasAttrubute.php に定義されている。
ここで、今まで辿ってきたことに確信が持てるはずだ。$relation = $this->$method(); の記述によって、なぜ->detailとアクセスしたのに、detail()が動いているのだろうという疑問が解決された。/** * Get a relationship value from a method. * * @param string $method * @return mixed * * @throws \LogicException */ protected function getRelationshipFromMethod($method) { $relation = $this->$method(); if (! $relation instanceof Relation) { throw new LogicException(sprintf( '%s::%s must return a relationship instance.', static::class, $method )); } return tap($relation->getResults(), function ($results) use ($method) { $this->setRelation($method, $results); }); }$methodと$relation をそれぞれdumpしてみると、予想通り$methodはdetailであり、$relationにはBookモデルのdetail()が行われた結果であるHasOneオブジェクトが入っていることがわかった。
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Book extends Model { public function detail(){ return $this->hasOne('\App\Bookdetail','id','bookdetail_id'); } }結論
プロパティアクセスの形でしか書いていないのに、モデルのメソッドが動く理由は、コアの処理の途中で$method()として実行しているため。
修正ご意見お待ちしています
- 投稿日:2019-03-24T02:58:17+09:00
laradock で『laradock_mysql_1 docker-entrypoint.sh mysqld Exit 2』となる問題を解決
環境
OS:macOS Mojave 10.14.3
Docker:18.09.2
docker-compose:1.23.2
docker-machine:0.16.1
php:7.1.23
Laravel Framework:5.8.7
mysql:Ver 14.14 Distrib 5.7.25, for Linux (x86_64) using EditLine wrapper事象
laradockで構築したmysqlを起動すると
$ docker-compose up -d php-fpm nginx mysql Recreating laradock_mysql_1 ... done Starting laradock_docker-in-docker_1 ... done Starting laradock_workspace_1 ... done Starting laradock_php-fpm_1 ... done Starting laradock_nginx_1 ... done $ docker-compose ps Name Command State Ports ----------------------------------------------------------------------------------------------------------------- laradock_docker-in-docker_1 dockerd-entrypoint.sh Up 2375/tcp laradock_mysql_1 docker-entrypoint.sh mysqld Exit 2 laradock_nginx_1 /bin/bash /opt/startup.sh Up 0.0.0.0:443->443/tcp, 0.0.0.0:8080->80/tcp laradock_php-fpm_1 docker-php-entrypoint php-fpm Up 9000/tcp laradock_workspace_1 /sbin/my_init Up 0.0.0.0:2222->22/tcpとなり起動にコケてしまう事象が発生しました。
解決方法
一旦dockerを止めます。
docker-compose stop以下のファイルを変更します。
.env### MYSQL ################################################# MYSQL_VERSION=latest #latestのまま - MYSQL_DATABASE=default + MYSQL_DATABASE=laradock - MYSQL_USER=root + MYSQL_USER=laradock - MYSQL_PASSWORD=root + MYSQL_PASSWORD=secret MYSQL_PORT=3306 MYSQL_ROOT_PASSWORD=root MYSQL_ENTRYPOINT_INITDB=./mysql/docker-entrypoint-initdb.dさらに、以下のディレクトリ配下のファイルをすべて削除します。
/Users/{USER NAME}/.laradock/data/mysql/終わり
以上、対応後にdockerを起動すると
$ docker-compose up -d php-fpm nginx mysql Starting laradock_docker-in-docker_1 ... done Recreating laradock_mysql_1 ... done Starting laradock_workspace_1 ... done Starting laradock_php-fpm_1 ... done Starting laradock_nginx_1 ... done $ docker-compose ps Name Command State Ports ---------------------------------------------------------------------------------------------------------------- laradock_docker-in-docker_1 dockerd-entrypoint.sh Up 2375/tcp laradock_mysql_1 docker-entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp, 33060/tcp laradock_nginx_1 /bin/bash /opt/startup.sh Up 0.0.0.0:443->443/tcp, 0.0.0.0:8080->80/tcp laradock_php-fpm_1 docker-php-entrypoint php-fpm Up 9000/tcp laradock_workspace_1 /sbin/my_init Up 0.0.0.0:2222->22/tcpmysqlのプロセスが確認できれば完了です。お疲れ様でした^^
- 投稿日:2019-03-24T00:12:47+09:00
Laravel での「php artisan migrate」ができないとき、解決法
環境
ローカル環境にlravel環境を作っている
PHP 7.3.2 mysql 8.0.15 osx10.12 Laravel Framework 5.8.5やろうとしたこと
users,password_resetsのテーブルを
マイグレーションしようとしたらエラーが出ました。users,password_resetsテーブルは、laravel newしたときに、作られています。
2014_10_12_00000000_create_users_table.rb<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('users'); } }2014_10_12_00000000_create_password_resets_table..rb<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreatePasswordResetsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('password_resets', function (Blueprint $table) { $table->string('email')->index(); $table->string('token'); $table->timestamp('created_at')->nullable(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('password_resets'); } }エラーの内容
$ php artisan migrate Illuminate\Database\QueryException : SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client (SQL: select * from information_schema.tables where table_schema = forge and table_name = migrations)エラーの結論
結局laravelとmysqlの接続ができてないこと
具体的に言うと
laravelが指定したmysqlデータベース名、user名が
自分のmysqlにないことです解決法
データベースを作る
ここではmysqlでデータベースを作ります。
手順としては以下の通りです。
- mysql8.0以降では、mysql5.6と少し違うので、注意してください
①mysqlインストールする
②mysqlでユーザー名、rootで入り、同時にpassword設定する
③ユーザーrootの中で
ユーザー名forgeを作る(同時にパスワードを作る)
④ユーザーrootの中で
ユーザー名forgeにデータベースを作る権限を与える。
⑤ユーザー名rootを抜ける
⑥ユーザー名forgeで入り、データベースforgeを作る。
⑦mysqlのユーザー承認方式を変えるmysqlについて知らない方は以下を参考してください
https://blog.codecamp.jp/what_is_mysql①mysqlインストールする
mysqlインストール $brew install mysql mysqlを起動 $mysql.server start②mysqlでユーザー名、rootで入り、同時にpassword設定する
$ mysql -uroot -p(パスワード設定するためにパスワードを書く) 例 したいパスワード abcd1234 $ mysql -uroot -pabacd1234③ユーザーrootの中でユーザー名forgeを作る(同時にパスワードを作る)
rootユーザーは、なんでもできる権限のため、別にユーザーを作ります。
ユーザー名 forge
パスワード Mt@rvy5ii3mysql> create user 'forge' identified by 'Mt@rvy5ii3'; Query OK, 0 rows affected (0.01 sec) 上が出た成功*パスワードの注意
LOW ポリシーは、パスワードの長さのみテストします。
パスワードは少なくとも 8 文字の長さでなければなりません。MEDIUM ポリシーは、パスワードが最低 1 つの数値文字を含み、1 つの小文字および
大文字を含み、1 つの特殊文字 (英数字以外) を含む必要があるという条件を追加します。STRONG ポリシーは、パスワードの 4 文字以上の部分文字列が、(辞書ファイルが指定された場合に)
辞書ファイル内の単語と一致してはならないという条件を追加します。④ユーザーrootの中で
ユーザー名forgeにデータベースを作る権限を与える。
grant all on forge. * to 'forge';⑤ユーザー名rootを抜ける
qiita.rb> exit;⑥ユーザー名forgeで入り、データベースforgeを作る。
ターミナルからユーザーforgeに入る $mysql -uforge -pMt@rvy5ii3; mysql -uユーザー名 -pパスワード データベースforgeを作る。 $create database forge;⑦mysqlのユーザー承認方式を変える
LaravelがMySQLに接続するために、
MySQL上のユーザ認証に指定された方式に変える。alter user 'forge' identified with mysql_native_password by 'pMt@rvy5ii3';
laravelの設定
mysqlのユーザー名、パスワード、データベースの名前をlaravelに教える。
ディレクトリ直下にある.envファイルを開く
DB_DATABASE,DB_USERNAME,DB_PASSWORDを以下のように変える。
プロジェクト名/.envDB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=forge(自分のデータベース) DB_USERNAME=forge(自分のユーザ名) DB_PASSWORD=pMt@rvy5ii3(自分のパスワード)最後に
以下のようにmigrateできた完成
$ php artisan migrate Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table参考文献
エラー解決のやり方
https://teratail.com/questions/154105mysql8.0の変更点
https://www.sejuku.net/blog/82303#imysqlインストールした方
https://qiita.com/hkusu/items/cda3e8461e7a46ecf25dmysqlのパスワードルール
https://qiita.com/hermannsw/items/b4da81201d69cefb080bmysql8のmigrationのエラーについて
https://takakisan.com/laravel-mysql-8-migration-error-fix/




