- 投稿日:2021-03-21T21:25:04+09:00
駆け出しエンジニアがLaravelを理解するために意識したこと
はじめに
実務で PHP, Laravel を使用することになり、最低限の理解(土台つくる)をする上でやったこと・意識したことをまとめました。実務未経験の方や転職して間もないという方向けの記事になっております。
もちろん実務に入ってまだ約1ヶ月半なのでまだまだわからないことばかりですが、今まで学習してきた Ruby, Rails と違うけど大丈夫かなという不安はなくなってきましたので記事にまとめさせていただきました。
これから転職を考えている人もいるかと思います。個人の見解ですが、そのときに言語を特定のものに絞らなくても良いんじゃないかなあと思いましたので、迷われている方や実務で別の言語を触れるのか不安と思っている方の参考になったら幸いです。
実務にはいって
最初は今まで学習してきたものとの違いがあり、自分にできるかなあと思うこともありました。ただそれは振り返ってみれば、これからやっていけるかなあとか不安などから視野が狭くなっていたのが原因なのかなと思います。細かく具体的に見ていくとどの言語も別のものになってしまうと思いますが、少し抽象度を上げて考えるとこの部分は似ているなとか少し違うけどこれぐらいの差か、となったりします。
要はプログラミングをするということなのであまり大差はないはずです。(今までRuby, PHP, Pythonを扱っただけなので他の言語で全然違う意見があったらすみません。。)
「誰のどんな悩みを解決」するのか考え「成し遂げたいこと」、「実装したいこと」がありそれを「どのように実現」していくか、それを 言語化 して実装していくというフローは一緒です。
とはいえ全く一緒ということはないので抵抗は少しありましたし、それを埋めるためにググる時間があるかもしれませんが、それも慣れなのかなと思います。簡単な例を出すと PHP だと変数名の前に
$
をつけますが、 Ruby だと付けないみたいな感じです。まだ癖が抜けなくて$
を抜かしてしまうことがありますが、そのときはエラーが吐かれるのでデバッグをすれば解決です。大事だと思ったこと
- ブログ記事はたくさんありますが、補助程度に使用すること
- チュートリアルに沿って要点を抑える
- とにかく実践あるのみ、わからないことがあればとことん調べる
- 公式ドキュメントを読む、英語から逃げない
チュートリアル
丁寧にインストールするところからサンプルコードから体系的に学習することができます。開発の流れだったりメインの機能だったりが書かれているのでとても取り組みやすいです。
公式ドキュメント
公式ドキュメントの大切さは実務に入り身にしみて実感しました。今までも大切だということは理解していたのですが、記事をメインに公式ドキュメントを補助という使い方になっていた気がします。公式ドキュメントにしっかり書いてあるのに、色々な記事を彷徨ってしまう、、これ本当に時間の無駄ですよね。
ドキュメントをしっかり読むのには時間がかかります。だったらブログ記事を読んでサクッとデバッグしてけばいいじゃん!って思うかもしれません。それで解決できるならまだ良いですが、解決できなかったりブログに書いてあることが間違いだった場合にまた違う挙動が起きたりしてしまうなんてことになるかもしれません。
はじめは時間をかけてしまうかもしれませんが、しっかりと着実に理解していくほうが後々効いてくると思います。どこに重要なことが書いてあるんだろうとかそういったことも数をこなして慣れていったり、基本英語で書いてあることが多いけどわからないことは翻訳しながら読むようにしています。(少しずつ英語から読み取れるようになった気がします。)
いろいろ書きましたが言いたいことは、公式ドキュメントを読むことでエラー解決のスピードや実装のスピードが格段に上がったと思います。
エラーが起きたときにググり偶然同じエラーが起きた人がたまたまブログ記事などでまとめてくれていればラッキーですが、同じようなエラーが起きていないときはすぐに解決することができなくなってしまいます。
ブログ記事などは本当にわかりやすくまとめてくれていますが、あくまで補助的にしようするほうが良いと思います。とはいえ、公式ドキュメントやマニュアルでわからなかったり難しい表現を使ったりしていることも少なくないのでそういったところはブログ記事を参考にさせていただいております。
ディレクトリ構造や役割を知る、慣れる
どのファイルで何をしているのか、どのような役割をもっているのか知ることは重要だと思います。エラーの原因なども特定しやすいですし、何より流れが追えてくるのでプログラミングの楽しさも増してきます。
わかりやすく全体像をまとめてくださっている記事がありましたのでこちらに載せておきます。
Ruby、Railsとの違い・共通点を考える
新しい言語だからと 「1から学ぶ」 と時間をものすごく浪費してしまう気がします。今まで学習してきたものがあるのであればそれと照らし合わせてこの言語だったらこういうふうにするんだよなあとか考えながらやると定着が早まると思います。また、このような学習の仕方をしていれば今後別の言語を扱ったときも同じようにスムーズに扱うことができるのではと思いました。
まとめ
- 言語で選ぶのではなく「プログラミングとは」と少し抽象度を上げることによって見え方が変わる
- チュートリアルは体系的にまとまっていて初学者でも取り組みやすい
- 公式ドキュメントを読むことは実力をつけるプログラミングをしていく上では必須となる
- ブログ記事はたくさんありわかりやすくまとめてくれているが、最終的にはその情報があっているのか判断できるように一時ソースを読む
おわりに
少し駆け足になってしまいましたが、実務未経験から転職して間もないという方向けに記事を書かせていただきました。ただ経験をいくら積んでも大事な点というのは変わらないと思います。より良い考え方や方法をアップデートなどしていけたらしていきます(別記事で違う視点からまとめる可能性も)。
参考文献
- 投稿日:2021-03-21T16:54:40+09:00
デザインパターンの学習を始める前にクラス図を読めるようになろう
デザインパターンを学習していると説明にクラス図が用いられることが多いですよね。
みなさんはクラス図を見て、概要を理解してからコードを読んでいますか?
クラス図の読み方を理解しておくと概要の把握と理解が捗るので、デザインパターンを始める前にクラス図を読めるようにしておくことをお勧めしています。
実際に自分もそうすることでデザインパターンを理解するまでのコストを抑えられたように感じました。この記事では、クラス図を読む時に必要最低限の情報をまとめています。
よろしければ、参考になさってください。図の読み方
図からソースコードを想像してみる
上で確認した読み方を参考に下のクラス図はどのようなソースコードになるか想像してみましょう。
サンプルコードはPHPで書いています。クラス図
ソースコード
ClassA.php<?php declare(strict_types=1); abstract class ClassA { private $attribute1; public abstract function operation1(); public function operation2() { return true; } }ClassB.php<?php declare(strict_types=1); class ClassB extends ClassA { public function operation1() { // TODO: Implement operation1() method. } }InterfaceC.php<?php declare(strict_types=1); interface InterfaceC { public function operation3(ClassA $param); }ClassD.php<?php declare(strict_types=1); class ClassD implements InterfaceC { public function operation3(ClassA $param): int { // TODO: Implement operation3() method. $return_value = 0; return $return_value; } public static function operation4() { return new ClassE(); } }いかがでしたでしょうか?
クラス図の読み方をマスターして、デザインパターン学習の役に立てたら幸いです。
- 投稿日:2021-03-21T16:35:37+09:00
Dockerのphp:XX-apacheでpdo_mysqlを使用したい時は
よくあるPHPのLAMP環境をDockerで再現しようとした時
- Dockerfile
FROM php:7.2-apache WORKDIR /var/www/html/ RUN echo "<?php" > index.php && echo "phpinfo();" >> index.phpでDocker起動
docker build -t phptest . docker run -it -d --name phptest2021 -p 80:80 phptest:latestああ、sqliteしかないのか・・
MySQLやMariaDBを使用したいので、
https://www.php.net/manual/ja/ref.pdo-mysql.php
これが使いたいんですよね・・そんな時は
docker-php-ext-installを使う。
- Dockerfile 書き直す。
FROM php:7.2-apache RUN docker-php-ext-install pdo_mysql && docker-php-ext-enable pdo_mysql WORKDIR /var/www/html/ RUN echo "<?php" > index.php && echo "phpinfo();" >> index.phpでもう一度Docker起動
docker build -t phptest . docker run -it -d --name phptest2021 -p 80:80 phptest:latestPDOが使用で切ることを確認。
- おまけ
docker-php-ext-installこのコマンドを知らなかったときは
https://pentan.info/php/pdo_mysql_install.html
直接上記をやろうとして時間を浪費しました。
他にもdocker-php-ext-install mysqli mbstring gd iconv色々インストールできます。
- 投稿日:2021-03-21T16:29:36+09:00
mixhostにcomposerをインストールする
手順
sshでログインし、以下のコマンドを実行する
curl -sS https://getcomposer.org/installer | php
下記コマンドを実行し、composerのバージョンなどが表示されて入れば正常にインストールされている。
php composer.phar
- 投稿日:2021-03-21T14:07:13+09:00
laravel 姓 名が別カラムなので結合したり、キーワードが空白で区切られていても検索できるwhere節の作り方(全文検索を使わない)
laravelで、DBのカラムがfirst_nameとlast_nameに分かれている。
しかし検索キーワードはいろんなパターンに対応させるように検索させたい場合。
でも全文検索は使えない。そんな時に役立つかもしれない記事です。
DBの例
id last_name fist_name 1 山田 太郎 2 田中 花子 ユーザーからの検索クエリ
- 山田 太郎
- 山田太郎
- 山田
- 太郎
という感じで、どんなパターンでも検索をヒットさせたい。
でも全文検索は使わない場合は、このように書けば解決できます。解決コードのEuloquent Where節部分です
前提
usersには検索したいEuloquentモデルが入っているものとします。
keywordsには検索クエリが入っているものとします。$users->Where(function ($query) use ($keywords) { $splited_keywords = extractKeywords($keywords); foreach($splited_keywords as $keyword){ $query->orWhere('last_name', 'LIKE', "%{$keyword}%") ->orWhere('first_name', 'LIKE', "%{$keyword}%") ->orWhereRaw('CONCAT(last_name, "", first_name) LIKE ? ', '%' . $keyword . '%'); } });という感じで、送られてきたkeywordを空白文字列で分割しながら、各列を検索し、かつ、CONCATで結合したカラムを検索します。どれかにHITすればOK。
空白文字列が含まれる配列を分割するのはこちらの記事を参考にしました。
https://qiita.com/mpyw/items/a704cb900dfda0fc0331function extractKeywords(string $input, int $limit = -1): array { return array_values(array_unique(preg_split('/[\p{Z}\p{Cc}]++/u', $input, $limit, PREG_SPLIT_NO_EMPTY))); }この記事があなたの生産性を少しでも上げることができたならば
LGTMボタンお願いします!
- 投稿日:2021-03-21T13:18:05+09:00
【Laravel】migrateコマンド一覧
概要
データベースにテーブルを作成するための
マイグレーション
ですが、テーブルの構造を定義、更新、削除するためのコマンドがいくつもあります。
ここではmigrateコマンド
として一覧でまとめてみました。migrateコマンド一覧
- マイグレーションファイルを作成する
$ php artisan make:migration create_テーブル名_table
- マイグレーションファイルを実行する
$ php artisan migrate
- migrationsテーブルを作成する
$ php artisan migrate:install
- マイグレーションを再実行してテーブルを再構築する。テーブルとデータの初期化
$ php artisan migrate:refresh
- すべてのマイグレーション操作を元に戻す(全削除)
$ php artisan migrate:reset
- 1つ前のマイグレーション操作した情報に戻す
$ php artisan migrate:rollback
- マイグレーションファイルと実行状態を確認できる
$ php artisan migrate:status
- 投稿日:2021-03-21T09:18:45+09:00
tinkerを使ってみて勉強になった話
MySQLの接続がうまくいかなくて、「解決できたよ!」って記事ではないのですが
「こんな方法あるんだ!」と思ったことがあったので備忘録のため残します。tinker
artisan migrate
コマンドがうまくいかず、エラーメッセージ的に接続が拒否されている内容かなと思ったのでその理由を調べたくてググっていたところtinker
でデバッグを調べられることが分かりました。使い方は簡単でターミナルでコマンドを打つだけです。
Dockerの場合はコンテナに入った状態で行います。php artisan tinkerそうするとそのまま対話シェルが起動してコマンドを打てるようになります。
以下が実際に入力してみた内容です。
>>>
の後にそれぞれのコマンドを入力する事で設定内容が確認できます。>>> config('database.default'); => "mysql" >>> config('database.connections.mysql.port'); => "3306" >>> config('database.connections.mysql.database'); => "my_app" >>> config('database.connections.mysql.password'); => "pass" >>> config('database.connections.mysql.host'); => "127.0.0.1"私の場合は
config('database.connections.mysql.database');
が.envやdatabase.phpと違ったので「あれ?」となってエラー解決の原因究明に役立ちました!以上です。
- 投稿日:2021-03-21T09:07:57+09:00
SPAにおけるLaravelのCORS設定周辺でつまずいた
概要
筆者はエンジニア歴がまだ1年経っていないphpがメインのシステムエンジニアです。
普段の実務ではLaravelは使用しておりません。そのため、不備等がある場合は教えて頂けると幸いです。
今回は友人とSPA開発する際にCORSの設定周辺で苦労したので、今後の自分も含めて共有させていただきます。そもそもCORSとは
調べれば詳細が記載されている記事がたくさん見つかると思うので大枠で説明すると、
同一生成元ではないドメインへリクエストの安全性を保証する仕組みです。
CORSに基づいた方法で実装すれば、同一生成元ではないところでもJavaScriptでアクセスすることが可能になると言うことです。
認識違いがあれば指摘していただきたいです。環境
PHP 7.4.16
Laravel Framework 6.18.40発生したエラー
SPAで画像をアップロードする機能を実装したところ、下記のエラーが出力されました...。
Access to XMLHttpRequest at 'http://localhost:8000/api/upload' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.CORSの存在は知っていたのですが、まず自分自身
localhost
の部分が同じであればポート番号が違くても同一生成元だと思っていました...。
お恥ずかしい...。
その他のクロスドメインの判定としては、下記が挙げられます。
- プロトコルが異なる。 httpsとhttpの違い
- ホスト名が異なる。エラー解決までの過程
それでは上記のエラーを解決するのに、Laravel側でCORSの設定をしていきます。
自分はfruitcake/laravel-cors
を利用しました。詳細は下記のリンクからご確認ください。
https://github.com/fruitcake/laravel-cors# インストール $ composer require fruitcake/laravel-cors # メモリ周辺でエラーが発生する場合は下記のコマンドを実行。 $ COMPOSER_MEMORY_LIMIT=-1 composer require fruitcake/laravel-cors # configファイルを作成。 $ php artisan vendor:publish --tag="cors"configファイルは
/config/cors.php
に作成されます。
自分は下記のように各設定をしました。cors.php<?php return [ // CORSを設定するURI 'paths' => ['api/*', 'sanctum/csrf-cookie'], // 許可するリクエストメソッド 'allowed_methods' => ['*'], // 許可するリクエストオリジンの設定 'allowed_origins' => ['http://localhost:8080'], 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => [], 'max_age' => 0, // Access-Control-Allow-Credentialsヘッダーを設定する。 'supports_credentials' => true, ];そして、それらをグローバルミドルウェアに追加しました。
/app/Http/Kernel.phpprotected $middleware = [ \App\Http\Middleware\TrustProxies::class, \App\Http\Middleware\CheckForMaintenanceMode::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, \Fruitcake\Cors\HandleCors::class, // 追加 ];しかし、また別のエラーが出力されました...。
// コンソール POST http://localhost:8000/api/upload 419 (unknown status) // レスポンスメッセージ "message": "CSRF token mismatch.",どうしてー!自分の認識だと、
api.php
に定義したルートはCSRFの保護は無効になると思っていました。
色々原因を探ったところ、以前実装したsanctum認証
で設定したミドルウェアが原因だと判明しました。/app/Http/Kernel.php'api' => [ EnsureFrontendRequestsAreStateful::class, // ← これ 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class ],その中身を見ていると、下記の記述がありました。
だから、APIとして定義したルートでもCSRFのチェックがされていたのですね...。EnsureFrontendRequestsAreStateful.phppublic function handle($request, $next) { $this->configureSecureCookieSessions(); return (new Pipeline(app()))->send($request)->through(static::fromFrontend($request) ? [ function ($request, $next) { $request->attributes->set('sanctum', true); return $next($request); }, config('sanctum.middleware.encrypt_cookies', \Illuminate\Cookie\Middleware\EncryptCookies::class), \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, config('sanctum.middleware.verify_csrf_token', \Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::class), // ここでCSRFの保護が有効になってる!! ] : [])->then(function ($request) use ($next) { return $next($request); }); }簡単にまとめると、
1. sanctum認証で必要なミドルウェアをapi.phpのルート全てに反映されてしまっていた。
2. それによって、CSRFのチェックが不要なルートにもCSRFの保護が有効になっていた。
といった感じです。エラー対策
上記の原因が判明したとなるとあとは簡単でした。
認証がいらないルートの場合はCSRFの保護を無効にすればいいので、/app/Http/Middleware/VerifyCsrfToken.php
のexcept
箇所で無効にするURIを設定します。/app/Http/Middleware/VerifyCsrfToken.php<?php namespace App\Http\Middleware; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware; class VerifyCsrfToken extends Middleware { /** * Indicates whether the XSRF-TOKEN cookie should be set on the response. * * @var bool */ protected $addHttpCookie = true; /** * The URIs that should be excluded from CSRF verification. * * @var array */ protected $except = [ // ここに無効にするURIを追加する。 'api/login', 'api/upload', ]; }おわりに
今回SPAにおけるLaravel側のみのCORSの設定などを主に説明させていただきました。
また、筆者自身まだ未熟であるので説明不足であったり、理解不足などありましたらご指摘していただけると幸いです。
- 投稿日:2021-03-21T05:41:30+09:00
Atomで単語をダブルクリック時に$まで選択するようにする方法
- 投稿日:2021-03-21T02:19:16+09:00
【Laravel】Seedデータを作成する UserSeeder.php
Seedデータを作成する
$ dokcer-compose exec workspace php artisan make:seeder UserSeederlaradockを使用しているので、laradockディレクトリに移動してから上記のコマンドを実行する。
ここでは、UserSeeder
というファイルを作成して、Userに関するデータを登録する。database/seeds/UserSeeder.php<?php use Illuminate\Database\Seeder; class UserSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { } }すると、上記のようなファイルが作成される。
ここに登録したいデータに関する記述を加える。database/seeds/UserSeeder.php<?php use Illuminate\Database\Seeder; class UserSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { DB::table('users')->insert([ [ 'name' => 'Tanaka Taro', 'age' => 50 ], ]); } }DB::table('users')->insert([ [ 'name' => 'Tanaka Taro', 'age' => 50 ], ]);上記の記述で、Userテーブルにデータを登録できる。
あとは、Seederを実行するにはDatabaseSeederというクラスに作成したSeederクラスを登録する必要がある。database/seeds/DatabaseSeeder.php<?php use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { /** * Seed the application's database. * * @return void */ public function run() { $this->call(UserSeeder::class); } }これで準備完了。
あとは下記のコマンドを実行する。
$ docker-compose exec workspace php artisan db:seedこれでSeederに書いた情報がDBに登録される。
終わり
- 投稿日:2021-03-21T01:55:07+09:00
【Laravel】php artisan make:model ***で作成したマイグレーションファイルの中身
Laravelのmigrationファイルの中身
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateProductsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() //upメソッドでマイグレーション時にこの中身が実行される。 { Schema::create('products', function (Blueprint $table) { $table->bigIncrements('id'); $table->timestamps(); }); } //Schema::createでテーブルを作成するらしい。ここでは、productsテーブルが作成されるイメージ /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('products'); } }Laravelでは、テーブルの中身のカラムとそのデータ型は以下のように記述するらしい。
$table->bigIncrements('id'); $table->timestamps();これで、テーブル内のカラムとそのデータ型を指定してテーブルを作成する。
しかし、migrationファイルを作成した時点ではまだカラムの情報が不足している場合は、ここで追記が必要。