- 投稿日:2019-12-22T22:07:58+09:00
【開発環境】Operation not permittedでphp artisan migrateできないときは権限周りを確認!
どうも、たかふみです。
現在携わっているシステムの開発が終わり、「さぁそろそろステージング環境の準備をしようかなぁ」と思い、テーブルを作成するコマンド
php aritisan migrate
を実行しようとしたそのとき。Operation not permitted「migrateができない!」
今日の記事は、AWSのEC2を使って用意したステージング環境でmigrateができない問題を解決します!
解決策
自分が所有ユーザーになる&所有グループに書き込み権限を与える
やったこと
1. まずエラーメッセージを読む。
UnexpectedValueException : The stream or file "/var/www/mcfhfs/storage/logs/laravel-2019-11-20.log" could not be opened: failed to open stream: Permission denied at /var/www/mcfhfs/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php:111 107| restore_error_handler(); 108| if (!is_resource($this->stream)) { 109| $this->stream = null; 110| > 111| throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: '.$this->errorMessage, $this->url)); 112| } 113| } 114| 115| if ($this->useLocking) { Exception trace: 1 Monolog\Handler\StreamHandler::write() /var/www/mcfhfs/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php:120 2 Monolog\Handler\RotatingFileHandler::write() /var/www/mcfhfs/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php:42 Please use the argument -v to see more details.エラーメッセージを見てみると「ログファイルへの書き込み権限がありません。」となっていました。どうやらログファイルへの書き込み権限が無いようです。
2. ログファイルの権限を確認&変更
ls -la
で権限を確認すると、rw- - r -- - r --
となっていました。この場合「所有ユーザ(読/書) - 所有グループ(読) - その他のユーザ(読)」であり、
僕は所有ユーザーではなく、所有グループに属するので読み取り権限しかありません。「そしたら、所有グループの権限に書き込み権限(w)を追加すれば良いのでは?」
ということで
chmod 664 laravel-2019-11-20.log
を実行。
結果、Operation not permitted
が表示されました。調べてみると、ファイルの権限はファイル所有者でないと変更できないようです。
(参考:https://marunouchi-tech.i-studio.co.jp/3341)3. ファイルを作り直す
「そしたら、自分がファイルの所有ユーザーになればいいのでは?」
該当のログファイルを一旦削除して再度作成。
ファイル所有者が自分になっていることを確認した後、再度migrateを実行。php artisan migrate:fresh Dropped all tables successfully. Migration table created successfully.「成功!」
4. webサーバーからも書き込みができるように権限を変更
これで解決だと思い、ブラウザからステージング環境に接続してページを表示しようとしたところ、再び「ログファイルに書き込み権限がありません」との表示がされました。
どうやらwebサーバーからの書き込み権限を与える必要があるようです。chmod 664 laravel-2019-11-20.log ls -la -rw-rw-r--これで所有ユーザー、所有グループに書き込み権限を付与できたので再度サイトへアクセス。無事に表示されていました!
■まとめ
・権限はファイル所有者でないと変更できない。
・webサーバーからの書き込み権限付与を忘れずに!
・「Operation not permitted」「Permission denied」のときには権限を確認!今まで権限でエラーが起きたことがなかったので、これを機に知ることができて良かったです。これでPermission deniedが出ても安心ですね。それでは!
- 投稿日:2019-12-22T21:53:26+09:00
【Laravel】migrateができないのは環境設定が間違っているからかも!あるあるエラーを.envと共に振り返る。
どうも、たかふみです。
Laravelで開発を行っていると、必ず使うであろう
php artisan migrate
コマンド。僕も何度もお世話になったコマンドです。今回は
php artisan migrate
を実行したときに出会ったエラーと共に解決策を書きたいと思います。あるあるエラー1:Connection refused
エラーメッセージ
Illuminate\Database\QueryException : SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = sample and table_name = migrations and table_type = 'BASE TABLE') at /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:665 661| // If an exception occurs when attempting to run a query, we'll format the error 662| // message to include the bindings with SQL, which will make this exception a 663| // lot more helpful to the developer instead of just the database's errors. 664| catch (Exception $e) { > 665| throw new QueryException( 666| $query, $this->prepareBindings($bindings), $e 667| ); 668| } 669| Exception trace: 1 PDOException::("SQLSTATE[HY000] [2002] Connection refused") /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70 2 PDO::__construct("mysql:host=127.0.0.1;port=3306;dbname=sample", "root", "password", []) /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70 Please use the argument -v to see more details. Whoops\Exception\ErrorException : Module 'zip' already loaded at Unknown:0 1| Exception trace: 1 {main}() /var/www/html/artisan:0解決策:DB_HOSTの設定を見直す。
.envファイルにあるDB_HOSTの値を確認したところ、
DB_HOST=127.0.0.1
となっていました。調べると、dockerの場合はコンテナ名に設定する必要があるとのことです。【修正後】 DB_HOST=mysqlこれで解決しました。
エラー2:Connection refused
Illuminate\Database\QueryException : SQLSTATE[HY000] [1049] Unknown database 'sample' (SQL: select * from information_schema.tables where table_schema = sample and table_name = migrations and table_type = 'BASE TABLE') at /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:665 661| // If an exception occurs when attempting to run a query, we'll format the error 662| // message to include the bindings with SQL, which will make this exception a 663| // lot more helpful to the developer instead of just the database's errors. 664| catch (Exception $e) { > 665| throw new QueryException( 666| $query, $this->prepareBindings($bindings), $e 667| ); 668| } 669| Exception trace: 1 PDOException::("SQLSTATE[HY000] [1049] Unknown database 'sample'") /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70 2 PDO::__construct("mysql:host=mysql;port=3306;dbname=sample", "root", "password", []) /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70 Please use the argument -v to see more details.解決策:DB_DATABASEの値を確認
エラーメッセージから「'sample'というDBは存在しません。」ということが分かります。
この場合は、接続しようとしているDBの名前を見直す必要があります。僕の場合はDB「bookmark」に接続をしたかったので、.envファイルの該当箇所を下記のように修正しました。
【修正後】 DB_DATABASE=bookmarkこれで接続できました。
エラー3:修正しても接続できない。
解決策:envファイルが複数存在していないか確認
このエラー(?)が起きたときに一番ハマりました。笑
修正してもキャッシュを削除してもエラーが起きるため、もう一度ファイルを確認しようとファイル名で検索したところ、「.env」が2つあることに気づきました。不要なenvファイルを削除したら上手くいったのでこれが原因だったようです。
migrateに成功すれば晴れて下記の状態になるはずです。
このババババッと実行される感じが気持ちいいんですよね。root@592de04c5bde:/var/www/html/web# php artisan migrate Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.03 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.01 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.01 seconds)まとめ:エラーメッセージを読んでenvファイルを見直そう。
こうするとmigrateが上手くいかないのは.envファイルの値、つまり環境設定が間違っていることが多かったように感じます。DBが無いと開発に着手できないので、ここはスムーズに乗り越えたいですね。それでは!
- 投稿日:2019-12-22T21:53:26+09:00
【Laravel】migrateができないのは環境変数が間違っているからかも!あるあるエラーを.envと共に振り返る。
どうも、たかふみです。
Laravelで開発を行っていると、必ず使うであろう
php artisan migrate
コマンド。僕も何度もお世話になったコマンドです。今回は
php artisan migrate
を実行したときに出会ったエラーと共に解決策を書きたいと思います。あるあるエラー1:Connection refused(Dockerの場合)
エラーメッセージ
Illuminate\Database\QueryException : SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = sample and table_name = migrations and table_type = 'BASE TABLE') at /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:665 661| // If an exception occurs when attempting to run a query, we'll format the error 662| // message to include the bindings with SQL, which will make this exception a 663| // lot more helpful to the developer instead of just the database's errors. 664| catch (Exception $e) { > 665| throw new QueryException( 666| $query, $this->prepareBindings($bindings), $e 667| ); 668| } 669| Exception trace: 1 PDOException::("SQLSTATE[HY000] [2002] Connection refused") /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70 2 PDO::__construct("mysql:host=127.0.0.1;port=3306;dbname=sample", "root", "password", []) /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70 Please use the argument -v to see more details. Whoops\Exception\ErrorException : Module 'zip' already loaded at Unknown:0 1| Exception trace: 1 {main}() /var/www/html/artisan:0解決策:DB_HOSTの設定を見直す。
.envファイルにあるDB_HOSTの値を確認したところ、
DB_HOST=127.0.0.1
となっていました。調べると、dockerの場合はDBのコンテナ名に設定する必要があるとのことです。【修正後】 DB_HOST=mysqlこれで解決しました。
エラー2:Connection refused
Illuminate\Database\QueryException : SQLSTATE[HY000] [1049] Unknown database 'sample' (SQL: select * from information_schema.tables where table_schema = sample and table_name = migrations and table_type = 'BASE TABLE') at /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:665 661| // If an exception occurs when attempting to run a query, we'll format the error 662| // message to include the bindings with SQL, which will make this exception a 663| // lot more helpful to the developer instead of just the database's errors. 664| catch (Exception $e) { > 665| throw new QueryException( 666| $query, $this->prepareBindings($bindings), $e 667| ); 668| } 669| Exception trace: 1 PDOException::("SQLSTATE[HY000] [1049] Unknown database 'sample'") /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70 2 PDO::__construct("mysql:host=mysql;port=3306;dbname=sample", "root", "password", []) /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70 Please use the argument -v to see more details.解決策:DB_DATABASEの値を確認
エラーメッセージから「'sample'というDBは存在しません。」ということが分かります。
この場合は、接続しようとしているDBの名前を見直す必要があります。僕の場合はDB「bookmark」に接続をしたかったので、.envファイルの該当箇所を下記のように修正しました。
【修正後】 DB_DATABASE=bookmarkこれで接続できました。
エラー3:修正しても接続できない。
解決策:envファイルが複数存在していないか確認
このエラー(?)が起きたときに一番ハマりました。笑 修正してもキャッシュを削除してもエラーが起きるため、もう一度ファイルを確認しようとファイル名で検索したところ、「.env」が2つあることに気づきました。
不要なenvファイルを削除したら上手くいったのでこれが原因だったようです。
migrateに成功すれば晴れて下記の状態になるはずです。このババババッと実行される感じが気持ちいいんですよね。
root@592de04c5bde:/var/www/html/web# php artisan migrate Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.03 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.01 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.01 seconds)まとめ:エラーメッセージを読んでenvファイルを見直そう。
こうするとmigrateが上手くいかないのは.envファイルの値、つまり環境変数が間違っていることが多かったように感じます。DBが無いと開発に着手できないので、ここはスムーズに乗り越えたいですね。それでは!
- 投稿日:2019-12-22T18:14:13+09:00
【Laravel】boolean型へのキャスト
boolean型(理論型)とは
phpのマニュアルによれば、「boolean は、真偽の値を表します。 この値は、TRUE または FALSE のどちらかになります。」とのこと。
つまりboolean型には「TRUE」と「FALSE」の2種類の値にしかならない。
型をキャスト(変換)すると
boolean型へのキャストを行うと次の値は「FALSE」と判定される。
・boolean の FALSE
・integerの0
・floatの0.0
・空の文字列、および文字列の "0"
・要素の数がゼロである配列
・NULL
・空のタグから作成された SimpleXML オブジェクトvar_dump((bool) "false"); // bool(false) var_dump((bool) 0); // bool(false) var_dump((bool) 0.0); // bool(false) var_dump((bool) ""); // bool(false) var_dump((bool) "0"); // bool(false) var_dump((bool) []); // bool(false) var_dump((bool) NULL); // bool(false)これら以外の値はTRUEとなる
判定処理への利用
DBテーブル内にその値があるかどうかの判定
例)指定したIDのユーザが存在するかどうかUser.phpreturn (boolean) $this->where("id",$user->id)->first();first()で取り出したデータはオブジェクト型のデータとなるが、存在しない場合NULL値となるためFALSEを返す。
これだったらis_null()やempty()でいいかも。
- 投稿日:2019-12-22T17:51:31+09:00
Using left join and name column in Model at Laravel Eloquent.
Environment
Laravel Framework 6.5.2Example
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\DB; // for giving alias to base table class TableA extends Model { protected $table='table_a'; public static function getList() { return DB::table('table_a as a') ->leftJoin('table_b as b', 'b.id', '=', 'a.b_id') ->get([ 'a.id', 'b.id as b_id', 'a.created_at as created_at' ]); } }Note
If each table have created_at and you don't narrow one created_at explicitly, you'll face an error like below
SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'created_at' in order clause is ambiguous
- 投稿日:2019-12-22T17:20:58+09:00
Vue.jsのtemplateの中でURLとかの文字列をフィルタで置き換えする方法
タイトルからすごく直感的に分かりづらいタイトル!
【本記事の目的】
vue.jsの中で、文字列の中の一部をフィルターで変更したい!
(phpでいうところのstr_replace)【前置き】(長いので飛ばしてもokです)
laravelでは画像データを投稿すると、デフォルトでpublicに保管されます。
それを実際に表示させるには画像をシンボリックリンクでstorage側で表示させる事を推奨されています。
参考:https://qiita.com/koru1893/items/1d2f522e20744b03e3adでもそれをlaravel経由のvue.jsで表示させようとするとうまくいかず。
vue.jsの中でimgタグの参照urlをpublic→storage に置き換える
という作業にハマったのでメモです。**publicだと読み込めず、storageだと読み込める状態です。
なお、php(view)でそのデータを読み込むだけなら
str_replaceで画像のurlを変数にして置き換えて、imgタグの読み込み先として指定すれば行けます。//$image_urlがdbから持ってきたurl情報。urlの一部を置き換えるということ。 $image_url = str_replace('public/', 'storage/', $image_url);phpのview内でやる方法で完了しているじゃん!て思うんですが、
vue.jsとか使って非同期でdb上のURL文字列を取ってくる場合、img参照用のURLをjsファイル内で(今回の場合vue.jsん中で)差し替える必要があります。
やっと本題
カスタムフィルタを作りました!
(※vue.jsのフィルタ機能は今は自作しないとダメぽい。vue.1系はフィルタのメソッドあったぽいです。なんで削除されたんだろう?)filtersの中に、
「public」という文字列を「..storage」に置き換える
「replace」という処理を作りました。
(置き換え前、置き換え先のコードはもちろん任意です。)vue.js<script> export default { props:['hoge'], data:function(){ return{ (略) } }, mounted(){ (略) }, filters:{ //カスタムフィルタ。こんな感じ! replace:function(val){ return val.replace("public", "../storage"); } }, } } </script>replaceのフィルタは準備できました。
あとはtemplateの中で、フィルタします!
(※vue.jsの中では {{ フィルタしたいデータ|フィルタの処理名 }} という書き方でフィルタリングできます。マスタッシュ!)vue.js<template> (略) <img :src="image_url | replace('public','../storage')" alt=""> (略) </template>これで、urlのなかの一部を置き換えられます。
公開サイト側でソースをみると、下記のようになります。フィルタなしの結果
<img src="public/post_images/hoge.jpg">フィルタありの結果
<img src="../storage/post_images/hoge.jpg">これできちんと画像が公開サイトで読み込めました。やった!
参考:https://www.itsolutionstuff.com/post/how-to-replace-string-in-vue-jsexample.html
- 投稿日:2019-12-22T17:20:58+09:00
【Laravel】 Vue.jsのtemplateの中で文字列置き換えする方法【フィルタ】
タイトルからすごく直感的に分かりづらいタイトル!
【前置き】
まず、larabelでは投稿した画像はpublicに保管されてしまうんですが
それを実際に表示させるには画像をシンボリックリンクでstorage側で表示させないといけません。
参考:https://qiita.com/koru1893/items/1d2f522e20744b03e3ad
で、本記事でやりたいことは
vue.jsの中でimgタグの参照urlをpublic→storage に置き換える
という作業。php(view)でそのデータを読み込むだけなら
str_replaceで画像のurlを変数にして置き換えて、imgタグの読み込み先として指定すれば行けます。//$image_urlがdbから持ってきたurl情報。urlの一部を置き換えるということ。 $image_url = str_replace('public/', 'storage/', $image_url);
本題
長くなりましたが本題。
vue.jsで文字列置き換え、前述のreplace的なことをやろうとして「フィルタが良さそう!」
となったんですが、いい感じのreplace処理がない!
参考情報調べても少しややこいreplaceばかり出てきたけど、簡単そうな方法がありました。
参考:https://www.itsolutionstuff.com/post/how-to-replace-string-in-vue-jsexample.html調べるのに少し時間かかったので、備忘録を兼ねて。
やろうとしたこと
- コントローラーでDBから取得したデータを
- view に持ってきて、そこからvue.jsに受け渡す。
- vue.js内で受け取ったデータのimage出力するときに、url情報を一部書き換えたい(書き換えたい理由は[前提]参照)
1.2は割愛。この辺りが参考になるかもです!
3でやった方法。
カスタムフィルタで特定のコードをreplaceしたい!
※vue.jsのフィルタ機能は今は自作しないとダメぽい(vue.1系はフィルタのメソッドあったぽいです。なんで削除されたんだろう)filtersの中に、
「public」という文字列を「..storage」に置き換える
「replace」というフィルタを作りました。vue.js<script> export default { props:['hoge'], data:function(){ return{ (略) } }, mounted(){ (略) }, filters:{ //カスタムフィルタ。こんな感じ! replace:function(val){ return val.replace("public", "../storage"); } }, } } </script>replaceのフィルタは準備できました。
あとはtemplateの中で、フィルタします!
vue.jsの中では
{{ フィルタしたいデータ|フィルタの処理名 }}
という書き方でフィルタリングできますvue.js<template> (略) <img :src="image_url | replace('public','../storage')" alt=""> (略) </template>これで、urlのなかの一部を置き換えられます。
公開サイト側でソースをみると、下記のようになります。フィルタなしの結果
<img src="public/post_images/hoge.jpg">フィルタありの結果
<img src="../storage/post_images/hoge.jpg">これできちんと読み込めました。やった!
参考:https://www.itsolutionstuff.com/post/how-to-replace-string-in-vue-jsexample.html
- 投稿日:2019-12-22T17:20:58+09:00
【Laravel】 Vue.jsのtemplateの中でURLとかの文字列置き換えする方法【フィルタ/非同期】
タイトルからすごく直感的に分かりづらいタイトル!
【前置き】
まず、larabelでは投稿した画像はpublicに保管されてしまうんですが
それを実際に表示させるには画像をシンボリックリンクでstorage側で表示させないといけません。
参考:https://qiita.com/koru1893/items/1d2f522e20744b03e3ad
で、本記事でやりたいことは
vue.jsの中でimgタグの参照urlをpublic→storage に置き換える
という作業。php(view)でそのデータを読み込むだけなら
str_replaceで画像のurlを変数にして置き換えて、imgタグの読み込み先として指定すれば行けます。//$image_urlがdbから持ってきたurl情報。urlの一部を置き換えるということ。 $image_url = str_replace('public/', 'storage/', $image_url);phpのview内でやる方法で完了しているじゃん!て思うんですが、
vue.jsで非同期でも取ってくるのをやるのも試そうとして、img参照用のURLを差し替える方法を探すのに時間がかかったのです。
本題
長くなりましたが本題。
vue.jsで文字列置き換え、前述のreplace的なことをやろうとして「フィルタが良さそう!」
となったんですが、いい感じのreplace処理をやるのに簡単そうな方法がありました。
参考:https://www.itsolutionstuff.com/post/how-to-replace-string-in-vue-jsexample.htmlもう少し細かく全体の流れをかくと
- コントローラーでDBから取得したデータを
- view に持ってきて、そこからvue.jsに受け渡す。
- vue.js内で受け取ったデータのimage出力するときに、url情報を一部書き換えたい(書き換えたい理由は[前提]参照)
1.2は割愛。この辺りが参考になるかもです!
で、3でやった方法。
カスタムフィルタで特定のコードをreplaceしました!
(※vue.jsのフィルタ機能は今は自作しないとダメぽい。vue.1系はフィルタのメソッドあったぽいです。なんで削除されたんだろう?)filtersの中に、
「public」という文字列を「..storage」に置き換える
「replace」という処理を作りました。
(置き換え前、置き換え先のコードはもちろん任意です。)vue.js<script> export default { props:['hoge'], data:function(){ return{ (略) } }, mounted(){ (略) }, filters:{ //カスタムフィルタ。こんな感じ! replace:function(val){ return val.replace("public", "../storage"); } }, } } </script>replaceのフィルタは準備できました。
あとはtemplateの中で、フィルタします!
(※vue.jsの中では {{ フィルタしたいデータ|フィルタの処理名 }} という書き方でフィルタリングできます。マスタッシュ)vue.js<template> (略) <img :src="image_url | replace('public','../storage')" alt=""> (略) </template>これで、urlのなかの一部を置き換えられます。
公開サイト側でソースをみると、下記のようになります。フィルタなしの結果
<img src="public/post_images/hoge.jpg">フィルタありの結果
<img src="../storage/post_images/hoge.jpg">これできちんと画像が公開サイトで読み込めました。やった!
参考:https://www.itsolutionstuff.com/post/how-to-replace-string-in-vue-jsexample.html
- 投稿日:2019-12-22T16:15:50+09:00
laradockでXdebugを使おうとしたらエラーと戦うことになった話
どうもやまうちです。
PhpStormとLaradockを使ってXdebugの導入をしようと思っていたところエラーとの戦いになりました。
docker-compose up --build nginx mysql workspace
これをしたらめっちゃエラー出ました(;´Д`)
エラー出ると冷静になります。
間違えました、放心状態になります。
かっこよく言うと茫然自失です(今調べました)。とはいえXdebugの導入がスタートラインなので立ち止まるわけには行きません。
結果としては無事導入できました。
ということで今回の記事は解決記録です。この記事を書くまでの話
※いきなり本編の裏話的な話なので次まで飛ばしても1ミリの支障もございません
「今週はデバッグの記事書くぞ~!」
と意気込む午後10時。
Qiitaを開き導入文を書き始める。
ちょっと知識を得て調子に乗っているボクは、デバッグをまだ使っていない後輩たちを煽るために奮い立たせるために、手を止めることなく導入文を書き終えた。
叩くキーボードの音に心地良ささえ感じていた。その余韻に浸かっているさなか、ボクは気づいた。
「そういや職場のPCにはデバッグ環境あるけど、自宅PCにはねえな」
「軽く導入でもするか---」
ナッパがあいさつがわりに「クン」と東の都を消したときのように、
ボクもXdebugの導入を「クン」した。その「クン」が戦いの合図になるとも知らずに・・・。
環境
- Winddows10 pro
- Docker for windows
- Laradock
- PhpStorm
PhpstormにXdebugを導入
何も見ずに導入できるハズもなくググりました。
そこでたどり着いたこの記事を参考に導入を進めました。参考記事:Laradock+PhpStormでXdebug - けけずんセルフハッキング
- xdebug.iniを編集
- .envを編集
docker-compose up --build nginx mysql workspace
を実施- エラー出る
- (;・∀・)
docker-compose up --build nginx mysql workspace
こいつでエラーか。
ちっ、しゃーねーなぁ。workspaceのエラー
こんなエラーが出ました。
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing? ERROR: Service 'workspace' failed to build: The command '/bin/sh -c if [ ${INSTALL_XDEBUG} = true ]; then apt-get install -y php${LARADOCK_PHP_VERSION}-xdebug && sed -i 's/^;//g' /etc/php/${LARADOCK_PHP_VERSION}/cli/conf.d/2 0-xdebug.ini && echo "alias phpunit='php -dzend_extension=xdebug.so /var/www/vendor/bin/phpunit'" >> ~/.bashrc ;fi' returned a non-zero code: 100これから分かることは
1. workspace関連のエラー
以上!!
要するになんもわからん!!!!wwwwwwwwwwwwww
いや草も生えねえよ、こんなエラー。とりあえずググってこのページにたどり着く。
Php 7.2 XDebug install error · Issue #1847 · laradock/laradock · GitHub英語アレルギーの症状が出ているがそんなこと言っている場合でもなく、冷静にボタンを押す。
このページを翻訳しますか? [翻訳] ポチ
読めるっ!読めるぞおおおお!!!!!laradock/workspace/Dockerfileを編集する
なんかこんなことが書いてあった。
edit file laradock/workspace/Dockerfile line 261
apt-get install -y php\${LARADOCK_PHP_VERSION}-xdebug && \
to
apt-get update && apt-get install -y php\${LARADOCK_PHP_VERSION}-xdebug && \
then run docker-compose build workspace何を言ってるのかはわからないが()、なんかそれっぽいのでDockerfileの該当箇所を編集してみた。
そしてdocker-compose up --build nginx mysql workspace
お!挙動が変わった!うまくいっ・・・ん?
php-fpmのエラー
またエラー。
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing? ERROR: Service 'php-fpm' failed to build: The command '/bin/sh -c if [ ${INSTALL_IMAGEMAGICK} = true ]; then apt-get install -y libmagickwand-dev imagemagick && pecl install imagick && docker-php-ext-enable imagick ;fi' returned a non-zero code: 100上の方にもっと色々出てたけど、とりあえずこちら↑のみ掲載。
例のごとく何言ってるのかわからないので、ググる。
そしてQiitaの記事にたどり着く。
laradock(Docker)+PhpStorm環境のxdebug導入でphp-fpmのエラーが起きる - Qiitalaradock/php-fpm/Dockerfileを編集
laradock/php-fpm/Dockerfile
のImageMagickのこれ↓をRUN if [ ${INSTALL_IMAGEMAGICK} = true ]; then \ apt-get install -y libmagickwand-dev imagemagick && \ pecl install imagick && \ docker-php-ext-enable imagick \ ;fiこう↓しろって書いてあったからする
RUN if [ ${INSTALL_IMAGEMAGICK} = true ]; then \ rm -rf /var/lib/apt/lists/* && \ apt-get update && \ apt-get install -y libmagickwand-dev imagemagick && \ pecl install imagick && \ docker-php-ext-enable imagick \ ;fiんで
docker-compose up --build nginx mysql workspace
よし!いい感じ!今度こそうまk・・・おいいいぃぃぃ!!nginxのエラー
今度はこんなエラー
adduser: group 'www-data' in use ERROR: Service 'nginx' failed to build: The command '/bin/sh -c apk update && apk upgrade && apk --update add logrotate && apk add --no-cache openssl && apk add --no-cache bash && adduser -D -H -u 1000 -s /bin/ba sh www-data' returned a non-zero code: 1まあ似たような内容のエラー。
workspaceのエラーとphp-fpmのエラーの経験を活かして頑張ろうとしたけど、1ミリもわからずにググった。
Laradockコンテナのビルドで ”adduser: group 'www-data' in use” が発生したときの対応【メモ】 - I am a software engineerlaradock/nginx/Dockerfileを編集
記事にはこう書いてた。
RUN apk update \ && apk upgrade \ && apk add --no-cache openssl \ - && apk add --no-cache bash \ - && adduser -D -H -u 1000 -s /bin/bash www-data + && apk add --no-cache bash + +RUN set -x ; \ + addgroup -g 82 -S www-data ; \ + adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1 ARG PHP_UPSTREAM_CONTAINER=php-fpm ARG PHP_UPSTREAM_PORT=9000昔の自分ならよくわからん書き方だが、今なら分かるっ!
ということでlaradock/nginx/Dockerfile
のこれ↓をRUN apk update \ && apk upgrade \ && apk --update add logrotate \ && apk add --no-cache openssl \ && apk add --no-cache bash \ && adduser -D -H -u 1000 -s /bin/bash www-dataこう↓した
RUN apk update \ && apk upgrade \ && apk --update add logrotate \ && apk add --no-cache openssl \ && apk add --no-cache bash RUN set -x ; \ addgroup -g 82 -S www-data ; \ adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1んで、
docker-compose up --build nginx mysql workspace
うまく行きました!!!あとは進むだけ
Laradock+PhpStormでXdebug - けけずんセルフハッキング
あとはこの↑記事通り進んで無事にデバッグできるようになりました。
ということでデバッグに関する記事はまた後日・・・。エラーとの戦い
とりあえず無事にXdebugの導入という目標は達成したわけですが、
エラーに関しては裏側で何が起きてて、Dockerfileを編集したことどう変わったのかはわかりません!!!(;・∀・)
それはおいおい知識を付けていきますm(_ _)mエラーが発生したらググる!
ボクがやっているレベルくらいの話であれば、たいていこれで解決できるはずです。
解決しないときはググり力が足りていないんだと思います。どういうワードで検索したら良いかわからないことはよくあると思います。
とりあえずそれっぽいワードなんでもいいので調べましょう。
そしたらそれっぽいワードを拾えたりするので、それをまたググる。
そんなことをしてたら答えに近づいていけます!先輩が教えてくれた記事を共有しますので、読んでみてください。
Vue.js未経験のベテランプログラマーに作業依頼したところ難なくこなしてしまうのですが、隠れて努力してるのでしょうか?それとも経験により新しいフレームワークにも対応できてしまうのでしょうか?に対する阿部 誠 (Makoto Abe)さんの回答 - Quoraエラーに負けずに戦おう!
- 投稿日:2019-12-22T15:53:56+09:00
Laravel-Excelでセル結合した複数シートを出力する
この記事は、Fusic その2 Advent Calendar 2019 22日目の記事です。
はじめに
LaravelでExcel出力するなら Laravel-Excel を使っている方が多いかと思います。
ただこのライブラリ、PHPSpreadSheet の完全なラッパーではありません。
それ故に少々詰まったので、書き残しておきます。環境
PHP 7.4.1
Laravel 6.9.0
Laravel-Excel 3.1クラス構成
Userモデルを介して取得した全データを、
UsersExportクラスにDIし、各ユーザごとにUsersSheetクラスを作成します。├── app │ ├── Exports │ │ ├── UsersExport.php │ │ └── UsersSheet.php │ └── User.php最終的には各ユーザごとにレイアウトが変動する複雑なExcelファイルの出力が必要だったのですが、
今回はその前段階として、結合セルのある複数シートの出力を目指します。
セル結合
Laravel-Excel では、PHPSpreadsheet の
mergeCells()
がラッパーされていません。
即ちセル結合をする際は、ライフサイクルの中でPHPOffice\PHPSpreadSheet\WorkSheet\WorkSheet
インスタンスを取得する必要があります。Laravel-Excelのライフサイクル
以下4つのイベントが順に発火します。
- BeforeExport
- BeforeSheet
- AfterSheet
- BeforeWriting
公式ドキュメントの記述によると、
PHPOffice\PHPSpreadSheet\WorkSheet\WorkSheet
が生成されるのはBeforeSheetイベントの直前です。
しかし、肝心の取得方法は記載されていません。
PHPOffice\PHPSpreadSheet\WorkSheet\WorkSheet
の取得以下のようにして、BeforeSheetイベント内で取得できました。
あとはPHPSpreadSheetのドキュメントに従うだけです。
$event->getSheet()で取得されるのがMaatwebsite\Excel\Sheet
なのはややこしいですね。namespace App\Exports; use Maatwebsite\Excel\Concerns\WithEvents; use Maatwebsite\Excel\Events\BeforeSheet; class UsersExport implements WithEvents { /** * @return array */ public function registerEvents(): array { return [ BeforeSheet::class => function (BeforeSheet $event) { $sheet = $event->getSheet()->getDelegate(); // セル結合 $sheet->mergeCells('A2:D2'); }, ]; } }複数シートの出力
続いて、複数シートの出力を行います。
失敗例
Laravel-Excel # Multiple Sheets を参考に、
先ほどのコードにWithMultipleSheets
とsheets()
メソッドを追加してみました。namespace App\Exports; use Maatwebsite\Excel\Concerns\WithEvents; use Maatwebsite\Excel\Events\BeforeSheet; class UsersExport implements WithEvents, WithMultipleSheets { protected $users; public function __construct($users) { $this->users = $users; } /** * @return array */ public function registerEvents(): array { return [ BeforeSheet::class => function (BeforeSheet $event) { $user = $event->getSheet()->user; $sheet = $event->getSheet()->getDelegate(); // セル結合 $sheet->mergeCells('A2:D2'); $sheet->setCellValue('A2', $user->name); }, ]; } /** * @return array */ public function sheets(): array { $sheets = []; foreach ($this->users as $user) { $sheets[] = new UsersSheet($user); } return $sheets; } }<?php namespace App\Exports; use App\User; class UsersSheet { public $user; public function __construct(User $user) { $this->user = $user; } }これを実行すると…
まっさら!!!
ライフサイクルの確認
各イベントが発火しているのか確認します。
<?php namespace App\Exports; use App\User; use Maatwebsite\Excel\Concerns\FromCollection; use Maatwebsite\Excel\Concerns\WithEvents; use Maatwebsite\Excel\Concerns\WithMultipleSheets; use Maatwebsite\Excel\Events\BeforeExport; use Maatwebsite\Excel\Events\BeforeWriting; use Maatwebsite\Excel\Events\BeforeSheet; use Maatwebsite\Excel\Events\AfterSheet; class UsersExport implements WithEvents, WithMultipleSheets { protected $users; public function __construct($users) { $this->users = $users; } /** * @return array */ public function registerEvents(): array { return [ BeforeExport::class => function (BeforeExport $event) { \Log::debug('==========================================='); \Log::debug('BeforeExport'); \Log::debug('==========================================='); }, BeforeSheet::class => function (BeforeSheet $event) { \Log::debug('==========================================='); \Log::debug('BeforeSheet'); \Log::debug('==========================================='); }, AfterSheet::class => function (AfterSheet $event) { \Log::debug('==========================================='); \Log::debug('AfterSheet'); \Log::debug('==========================================='); }, BeforeWriting::class => function (BeforeWriting $event) { \Log::debug('==========================================='); \Log::debug('BeforeWriting'); \Log::debug('==========================================='); }, ]; } /** * @return array */ public function sheets(): array { $sheets = []; foreach ($this->users as $user) { $sheets[] = new UsersSheet($user); } return $sheets; } }[2019-12-22 03:42:15] local.DEBUG: =========================================== [2019-12-22 03:42:15] local.DEBUG: BeforeExport [2019-12-22 03:42:15] local.DEBUG: =========================================== [2019-12-22 03:42:15] local.DEBUG: =========================================== [2019-12-22 03:42:15] local.DEBUG: BeforeWriting [2019-12-22 03:42:15] local.DEBUG: ===========================================
BeforeSheet
,AfterSheet
イベントが発火していませんね。
UsersSheet
のほうにもデバッグコードを追加してみます。class UsersSheet implements WithEvents { /** * @return array */ public function registerEvents(): array { return [ BeforeExport::class => function (BeforeExport $event) { \Log::debug('==========================================='); \Log::debug('BeforeExport -- Sheet'); \Log::debug('==========================================='); }, BeforeSheet::class => function (BeforeSheet $event) { \Log::debug('==========================================='); \Log::debug('BeforeSheet -- Sheet'); \Log::debug('==========================================='); }, AfterSheet::class => function (AfterSheet $event) { \Log::debug('==========================================='); \Log::debug('AfterSheet -- Sheet'); \Log::debug('==========================================='); }, BeforeWriting::class => function (BeforeWriting $event) { \Log::debug('==========================================='); \Log::debug('BeforeWriting -- Sheet'); \Log::debug('==========================================='); }, ]; } }[2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: BeforeExport [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: BeforeSheet -- Sheet [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: AfterSheet -- Sheet [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: BeforeSheet -- Sheet [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: AfterSheet -- Sheet [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: BeforeSheet -- Sheet [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: AfterSheet -- Sheet [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: BeforeSheet -- Sheet [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: AfterSheet -- Sheet [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: =========================================== [2019-12-22 04:03:45] local.DEBUG: BeforeWriting [2019-12-22 04:03:45] local.DEBUG: ===========================================
BeforeSheet
,AfterSheet
はどちらもUsersSheet
内での発火になっています。
Sheetイベントなので、確かに各Sheetクラスに委任するのが自然ですね。最終コード
以下のコードで、望んでいたExcelが出力できました。
<?php namespace App\Exports; use App\User; use Maatwebsite\Excel\Concerns\FromCollection; use Maatwebsite\Excel\Concerns\WithMultipleSheets; class UsersExport implements WithMultipleSheets { protected $users; public function __construct($users) { $this->users = $users; } /** * @return array */ public function sheets(): array { $sheets = []; foreach ($this->users as $user) { $sheets[] = new UsersSheet($user); } return $sheets; } }<?php namespace App\Exports; use App\User; use Maatwebsite\Excel\Concerns\WithTitle; use Maatwebsite\Excel\Concerns\WithEvents; use Maatwebsite\Excel\Concerns\WithMultipleSheets; use Maatwebsite\Excel\Events\BeforeSheet; class UsersSheet implements WithEvents, WithTitle { private $user; /** * @param User $user */ public function __construct(User $user) { $this->user = $user; } /** * @return array */ public function registerEvents(): array { return [ BeforeSheet::class => function (BeforeSheet $event) { $sheet = $event->getSheet()->getDelegate(); $sheet->mergeCells('A2:D2'); $sheet->setCellValue('A2', $this->user->name); }, ]; } public function title(): string { return $this->user->name; } }まとめ
今回はセル結合のみを行いましたが、
PHPOffice\PHPSpreadSheet\WorkSheet\WorkSheet
インスタンスの取得方法がわかったので、ほかにもいろいろできそうです。
BeforeSheet以外のイベントも上手く使っていきたいと思います。
- 投稿日:2019-12-22T14:46:41+09:00
【入門】Laravel×Vue.js②〜実装編〜
はじめに
PHPのフレームワークであるLaravelで作成したアプリケーションに
JavaScriptのフレームワークであるVue.jsを連携させる方法について説明します。
簡単な機能を実装します。自分のコンポーネントを登録する方法について説明します
実装する機能
メッセージを表示して、ボタンを押すと、メッセージを反転するコンポーネントの作成
まず、
resources/js/components/
内にHelloComponent.vue
を作成してください
そして、内容を以下のようにしてくださいresources/js/components/HelloComponent.vue<template> <div id="app"> <p>{{ message }}</p> <button v-on:click="reverseMessage">Reverse Message</button> </div> </template> <script> export default { data:function(){ return { message: 'Hello Vue!', }; }, methods: { reverseMessage: function () { this.message = this.message.split('').reverse().join('') } } } </script>コンポーネントの登録
上で作成したコンポーネントを登録しましょう
resource/js/app.jsrequire('./bootstrap'); window.Vue = require('vue'); Vue.component('example-component', require('./components/ExampleComponent.vue').default); Vue.component('hello-component', require('./components/HelloComponent.vue').default);ビューファイルへの組み込み
ビューファイルの追加したい時に下記を記述してください
hello/index.blade.php<div id="app"> <hello-component></hello-component> </div>以上で実装完了です。
疑問、気になるところがございましたら、質問、コメントよろしくお願いします!!!
- 投稿日:2019-12-22T10:36:17+09:00
【IT専門学生の就活】僕がこれからやること
自己紹介
僕はIT系の専門学生1年で、現在はWeb系の企業を目指して学習を進めています。今回この記事を書こうと思った理由は、就活が迫ってきたのですが学校にはWeb系企業の求人がなく、ポートフォリオを作成し、技術を証明する必要があると考えたからです。
今までやったこと
僕がWeb開発を始めたのは大学受験に落ちた日からです。もちろん最初は Progateさんから始めました:)
そしていつの間にかIT系の専門学校に
独学
- ポートフォリオページ作成(HTML&CSS)
- Ruby
- Ruby on Rails
- AWS(EC2)
- adobeXD
- PaizaスキルチェックBランク(Java,Ruby)
学校
- MySQL
- CentOS
- GUI電卓作成(JavaFX)
- GUIポーカー作成(JavaFX)
- シューティングゲーム作成(JavaFX)
- 基本情報技術者試験合格
- 成績全てA(1年前期)
書き途中に気付いたのですが、自主学習時間の割に形になっているものが少ないなと思ったので、作成物や資格合格を目標として取り組むことにします。
これからやること
自分でやることで何をすればよいかを整理するために書くので、学校のみで勉強するものは省いています。
就活までにやること(専門1年)
先頭の番号は優先順位です
- Webアプリ作成(Rails&HTML&CSS&BT) [独学]
- PaizaスキルチェックAランク(Python) [独学]
- ポートフォリオサイト作成(HTML&CSS&BS) [独学]
- 成績全てA [自宅+学校]
- 応用情報技術者試験合格 [自宅+学校]
プラスしてやること(専門2年)
まだ具体的に定まっていないため優先順位はつけられないのでつけません。
- Webアプリ作成(Laravel)
- Webアプリ作成(Java Spring Framework)
- TOEIC600点?(受けたことないからわからない)
ここからは趣味でやりたいことかもしれません。余裕があればやります
- 高校数学復習+大学数学
- 機械学習・人工知能
- Pythonでいろんな分野で遊ぶ
タスクに分解
やることを明確にするため、目標をタスクに分解していきます。
1.Webアプリ作成(Rails)
- Ruby
- Rails
- HTML・CSS
- Git
主役はRailsですがもちろん基礎文法としてRuby、デザインとしてHTML・CSS、バージョン管理としてGitをやる必要があります。デプロイはHerokuで行います(デプロイについてはRailsチュートリアルで学習できます↓)
タスク
【Ruby】
・[完了]Progate Rubyコース
・[完了]Paiza Rubyコース
・[完了]プロを目指す人のためのRuby【Rails】
・[完了]Progate Railsコース
・Railsチュートリアル【HTML・CSS】
・[完了]Progate HTML&CSS【Git】
・Udemy Git:はじめてのGitとGitHub2.PaizaスキルチェックAランク
- Python
- アルゴリズム
Pythonは応用情報と組み合わさった良い講座があったのでそれを見ることにします。アルゴリズムは演習もやりながらできるものがQiitaにたくさんあったのでそれをやることにします。
タスク
【Python】
・基本情報技術者試験+応用情報技術者試験+Python+SQL【アルゴリズム】
・AtCoder に登録したら次にやること 過去問精選10問
・AtCoder 版!蟻本 (初級編)3.ポートフォリオサイト作成(HTML&CSS&BS)
サーバーサイドを見せるためのポートフォリオ程度のHTML・CSSで新たに学習することはないので適当に調べながらやることにします。
4.成績全てA
テスト範囲が発表されてから考えます
5.応用情報技術者試験合格
基本情報で基本的なことは覚えたのでやるべきことは過去問演習だけです
タスク
・過去問演習
おわりに
応用情報合格したいな...?