20211130のlaravelに関する記事は9件です。

Larastanで静的解析したエラーをreviewdogでプルリクにコメントさせるよ

はじめに アドベントカレンダー この記事ではGitHubへのプルリクエストに対して、Larastanを利用して静的解析して出たエラーをreviewdogがコメントしてくれる方法を紹介します。 LarastanはPHPの静的解析ツールであるPHPstanをLaravel用に最適化したラッパーのパッケージです。 https://github.com/nunomaduro/larastan reviewdogはlinterなどを使ってソースコードレビューを行ってくれる補助ツールです。 linterの実行結果を自動でGitHubのプルリクエストにコメントしたりしてくれます。 https://github.com/reviewdog/reviewdog 環境 Laravel 8.* Larastan 1.0 reviewdog 0.13.0 作成したソースコード https://github.com/ryofutebol/laravel_reviewdog Larastan設定 インストール composer require nunomaduro/larastan --dev LarastanはPHPが7.2以上、Laravelが6.0以上である必要があります。 phpstan.neonファイル設定 phpstan自体の設定はphpstan.neonファイルに記述します。 includes: - ./vendor/nunomaduro/larastan/extension.neon parameters: paths: - app level: 0 ignoreErrors: - '#Call to an undefined method .*badMethod\(\)#' 最初に2行でLarastanの設定を読み込んでいます。 parametersに必要な設定をしていきます。 pathsにどのパスを解析対象のディレクトリを指定 levelはPHPstanでどのくらい厳格に解析するかのレベルを指定 0~9まであるので今回は最も緩い解析である0を指定します。 ignoreErrorsで無視するエラーを指定 エラー分をそのまま指定してもいいですし、上記コードのように正規表現で指定することも可能です。 動作確認 実際に静的解析を行ってくれているのかをローカルで確認してみます。 Laravelをインストールした初期状態でUserContorllerのみを作成します。 そこに下記のようなわざとエラーが出るようなメソッドを記述します。 namespace App\Http\Controllers; use App\Models\User; class UserController extends Controller { public function getUserName(): string { $user = Admin::query()->findOrFail(1); return $user->name; } } 本来やりたいことはIDが1のユーザー名を取得することですが、わざと存在しないAdminモデルを指定したメソッドを用意しました。 この状態で静的解析を実行します。 ./vendor/bin/phpstan analyse Note: Using configuration file /laravel_reviewdog/phpstan.neon. 19/19 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100% ------ ------------------------------------------------------------------------------- Line Http/Controllers/UserController.php ------ ------------------------------------------------------------------------------- 15 Call to static method query() on an unknown class App\Http\Controllers\Admin. ? Learn more at https://phpstan.org/user-guide/discovering-symbols ------ ------------------------------------------------------------------------------- [ERROR] Found 1 error 存在しないクラスなのでしっかりエラーが出てくれました。 試しにignoreErrorsで上記エラーが出ないように正規表現で指定してみます。 ignoreErrors: - '#Call to static method .*\(\)#' Note: Using configuration file /laravel_reviewdog/phpstan.neon. 19/19 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100% [OK] No errors 今回はエラーが出ず正常に静的解析が実行されました。 reviewdog設定 reviewdogが静的解析のエラーをプルリクにコメントしてくれるようにGitHub Actionsの設定をしていきます。 .github/workflow/reviewdog.ymlを作成します。 name: reviewdog on: pull_request: branches: - master jobs: analyse: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: reviewdog/action-setup@v1 with: reviewdog_version: latest - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.0' tools: composer:v2 - name: Resolve dependencies run: composer install --no-progress --prefer-dist --optimize-autoloader - name: Run PHPstan env: REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./vendor/bin/phpstan analyse --error-format=raw --no-progress | reviewdog -reporter=github-pr-review -f=phpstan nameでワークフロー名を指定 onでワークフローファイルを自動的にトリガーするイベントを指定 今回だとmasterブランチにプルリクを上げたタイミングでこのワークフローが実行されます。 jobsの中にLarastanを実行してエラーが出た際にreviewdogがコメントしてくれるための実行ジョブを指定 中身を簡単に説明すると ①reviewdogを導入 ②PHPとComposerのセットアップ ③PHPstan実行して結果を出力 注意点としてはREVIEWDOG_GITHUB_API_TOKENにGitHubのトークンを設定していますが、Personal Access Tokensの権限スコープのworkflowにチェックが入っていないとうまく動いてくれません。 これでreviewdogの設定は終了です。 reviewdogにコメントしてもらう 試しに先程エラーが出たコードをプルリクにあげてみます。 そうすると先程ローカルで実行したときと同じエラーがコメントとして表示されます。 最後に 今回はLaravelで静的解析ツールを使いましたが、構文チェックしてくれるPHP_CodeSnifferでも同じことは可能です。 レビュワーからすると細かく構文などをチェックしている時間はないと思うので、こういった自動ツールを導入することで実装タスク以外のコストが削減できることはメリットかなと思います。 そもそもプルリク上げる前に構文エラーがあったら自動整形してくれるようなツールもあるみたいなので調べたいみたいですね。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelの.envに#を書いてハマった話

非常につまらないことで半日以上無駄にしたので、愚痴のつもりで書きます。 要約 .envに設定値を書くときは、""でクォートしておけ!特に記号が含まれる文字列は! ※おそらくPHPとRubyに適用される話だと思います。その他の環境についてはわかりません。 語り 他社さんにDBを構築してもらって、接続用のIDとパスワードを受け取りました。 今回、このパスワードに # が含まれていました。 DB_PASSWORD=hoge#fuga という設定を.env に記入して php artisan migrate を実行したところ、エラーが発生。 SQLSTATE[HY000] [1045] Access denied for user 'USERNAME'@'XXX.XXX.XXX.XXX' (using password: YES) (SQL: ...省略) おかしいなと思い mysql コマンドで接続を試みたところ、特に問題なし。設定ミスや伝達ミスの線は消えました。 .env の設定値を見直しても問題なし。この時点で何だこりゃ?となるわけです。 試しにconfig/database.php 内にパスワードを書いてみたところ、問題なく php artisan migrate が実行できました。こりゃ .env から読み込むところがおかしいんだろう、おそらく#以降がコメント扱いなっておるんじゃろうと推測しました。 で、.env の記述を DB_PASSWORD="hoge#fuga" としてやったら .env 側の設定だけで php artisan migrate が動いた、というわけです。 ここまでで半日経ってます。 ※まぁ、こればかりやってたわけじゃないですが .envってどう処理されてるの? Laravel は PHP dotenv というライブラリを使って .env を読み込んでいるようです。 https://github.com/vlucas/phpdotenv このページを見ただけでは、#の扱いがよくわかりません。 サンプルが良くないですよね.... 別のページでは#の前に空白があればコメントになるという記述も見かけました。 連続する文字列の中の#はコメントとして扱われない、ということですね。 結果的にはこの情報が間違っているわけですが、古い情報なので当時は正しかったのかもしれません。 リンクはしませんが.... PHP dotenv は Ruby dotenv の PHP版という立ち位置のようです。 https://github.com/bkeepers/dotenv こちらのページには、#を含む文字列はクォートすればいいんだな、と判断できるサンプルが書かれています。 説明はこのように行うように心がけたいものです。 また、Laravel 添付の .env.example にも課題があるのではないかと思います。 設定値を "" でクォートしているものは .env内で定義した設定値を参照している箇所のみなので、 ここから .env に入った人は「設定値はベタ書きでいいんだ」と思うことでしょう。 かく言う自分も他の人が書いた .env を環境に合わせて設定していただけなので、今回のハマりを招いてしまったわけです。これが "" で囲まれているパスワードを置き換えるのであれば、なんの問題もなかったわけです。 ※私自身の知識にはなんの増加もないことになりますが、そんなことより早く仕事を終わらせたいときだってありますよね ※そこは今回の自分の仕事の範囲じゃないんじゃよ... ここから導かれる対策は2つ ・設定値に#を含めないようにせよ ・設定値はとにかく "" でクォートしておけ 前者の対応は論外なので、後者を推奨。 もちろん、何でもかんでもクォートしていると面倒だし、不要なところは省略していいと思うんですが、自分のようにうっかり # を書き込む羽目になってしまったような人のために、fool proof な書き方になっている方が良いですよね、って話です。 お付き合いありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client (SQL: select * from information_schema.tables where table_schema = hogehoge and table_name = migrations and table_type = 'BASE TABLE')

前提 ・Mac m1チップ ・Laravel8系 ・MySQL8系 ・PHP7系 ・envファイルに正しくDB情報を書いた。 ← ここまでちゃんと切り分けしましたか? 補足:.envに正しく書いたらしいことを確認する方法 ・ターミナルで下記を打って、パスワードをちゃんと入力して入れますか? mysql -u 書いたユーザー名 -p show databases; ・下記コマンドを打って、対象DBをちゃんと用意したことを確認しましたか? show databases;  → 結果に対象のDB名が出て来れば良い。 ・接続先がDockerのMySQLコンテナである場合、別途調べてください。 注意 ・タイトルのhogehogeを接続先となるDB名に置き換えて、もし手元のエラーと等しくないならやらない方が良いかもしれません。DBなので。(とは言っても、やってしまっても大丈夫なよう新規ユーザーを作成するような形にしてます。) 解決方法 ・利用しているユーザーのパスワードを「mysql_native_password」で変更してやる。 ・自分としては、新しくユーザーを作成してから試してみることをお勧めします。 // ユーザー作成 create user fuga@localhost identified by 'fugafuga'; // 権限付与(とりあえず全て。ここは必要に応じてドキュメント読みながら調整。) grant all privileges on *.* to fuga@localhost; flush privileges; // パスワードをmysql_native_passwordを利用して変更する alter user fuga@localhost identified with mysql_native_password 'fugafuga'; 解決するまでに読んだ記事 ・https://trialanderror.jp/mysql-8x-laravel-migrate/ ・https://blog.janjan.net/2018/11/01/mysql8-request-authentication-method-unknown-to-the-client/ ・https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-caching-sha2-password ・https://www.digitalocean.com/community/tutorials/how-to-create-a-new-user-and-grant-permissions-in-mysql-ja ・https://www.dbonline.jp/mysql/user/index6.html
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laravelでJWT(Json Web Token)を使いたい

JWT(Json Web Token)を勉強していく上で参考になったサイトを紹介していきます laravel8でとりあえずJWTを実装してみる ほぼコピペで動きました JWT+SNSアカウント でOAuthの認証機能をつくる コードを参考にしました
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel 8 VueでLaravel標準の認証機能を実装

手順 1. laravel/uiをインストール composer require laravel/ui 2.ログイン機能追加 php artisan ui vue --auth 3.マイグレーション(DBに接続する設定は省きます) php artisan migrate 4.vue-loaderのバージョンを変更 (2021-11-30現在は、変更しないとエラーになるため必須) package.json "vue-loader": "^15.9.7", ↓ "vue-loader": "^15.9.8", 5.Packageをインストール npm install 6.buildする(laravel mix) npm run dev 7.php artisan serve(必須ではない) (手っ取り早く確認するなら) php artisan serve 確認 http://127.0.0.1:8000/login または、welcomeページからLoginリンクから遷移 環境 Laravel Framework 8.73.2
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel Duskでブラウザ自動テスト化導入まで

Laravel Duskを使うことになったのでメモ程度に残します。 Dsukでできる事 Laravel Duskは、表現力豊かで使いやすいブラウザ自動化およびテストAPIを提供します。 手順 1.laravelをインストール composer create-project laravel/laravel laravel_dusk 2.Duskをインストール composer require --dev laravel/dusk php artisan dusk:install 3.アプリケーションの環境変数を設定する ※「php artisan serve」で動かす時 APP_URL=http://127.0.0.1:8000/ 4.サーバー起動 ※「php artisan serve」で動かす時 php artisan serve 5.テスト生成 php artisan dusk:make LoginTest ↓作成される tests\Browser\LoginTest.php <?php namespace Tests\Browser; use Illuminate\Foundation\Testing\DatabaseMigrations; use Laravel\Dusk\Browser; use Tests\DuskTestCase; class LoginTest extends DuskTestCase { /** * A Dusk test example. * * @return void */ public function testExample() { $this->browse(function (Browser $browser) { $browser->visit('/') ->assertSee('Laravel'); }); } } ※Duskのテストを生成するには、dusk:make Artisanコマンドを使います。生成されたテストは、tests/Browserディレクトリへ設置されます。 6.テストの実行 php artisan dusk OKになって入れば成功です。 環境 Laravel Framework 8.73.2
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laravel8 画像をBase64の文字列にエンコード・デコードするアプリを作る

目的 laravelを用いて画像をBase64の文字列にエンコード・デコードする簡単なアプリを作ってみる 環境 ハードウェア環境 項目 情報 OS macOS Big Sur(11.6) ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) プロセッサ 2 GHz クアッドコアIntel Core i5 メモリ 32 GB 3733 MHz LPDDR4 グラフィックス Intel Iris Plus Graphics 1536 MB ソフトウェア環境 項目 情報 備考 PHP バージョン 7.4.11 Homebrewを用いてこちらの方法で導入→Mac HomebrewでPHPをインストールする Laravel バージョン 8.X commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う MySQLバージョン 8.0.21 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする 概要 Macに直接作成したlaravelのローカル開発環境にて今回のアプリを作成する。 下記機能を持つlaravel8のアプリを作ってみる。 画像 → Base64文字列(エンコード) Base64文字列 → 画像(デコード) 文字列のBase64エンコード・デコードは今回実装しない。 今回のソース https://github.com/miriwo0104/laravel8_base64 方法 下記コマンドを実行してlaravel8のアプリを作成する。 $ composer create-project "laravel/laravel=8.*" laravel8_base64 -vvv 上記コマンドをで作成されたlaravel8_base64ディレクトリに移動して下記コマンドを実行してローカルサーバーを起動する。 $ php artisan serve 下記にアクセスし、正常にローカルサーバーが起動していることを確認する。 http://127.0.0.1:8000/ laravel8_base64ディレクトリで下記コマンドを実行してフォームリクエストクラスのファイルを作成する。 $ php artisan make:request EncodeRequest laravel8_base64/pp/Http/Requests/EncodeRequest.phpを開き下記の様に修正する。 laravel8_base64/pp/Http/Requests/EncodeRequest.php <?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class EncodeRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'file' => 'required' ]; } } 下記コマンドを実行してフォームリクエストクラスのファイルを作成する。 $ php artisan make:request DecodeRequest laravel8_base64/pp/Http/Requests/DecodeRequest.phpを開き下記の様に修正する。 laravel8_base64/pp/Http/Requests/DecodeRequest.php <?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class DecodeRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'base64_str' => 'required', ]; } } ルーティングファイルに下記の内容を記載する。 laravel8_base64/routes/web.php <?php use App\Http\Controllers\ConvertController; use Illuminate\Support\Facades\Route; /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::get('/', function () { return view('welcome'); }); Route::get('index', [ConvertController::class, 'index'])->name('index'); Route::post('encode', [ConvertController::class, 'encode'])->name('encode'); Route::post('decode', [ConvertController::class, 'decode'])->name('decode'); 下記コマンドを実行してコントローラークラスのファイルを作成する。 $ php artisan make:controller ConvertController 作成されたlaravel8_base64/app/Http/Controllers/ConvertController.phpを開き下記の様に記載する。 laravel8_base64/app/Http/Controllers/ConvertController.php <?php namespace App\Http\Controllers; use App\Http\Requests\EncodeRequest; use App\Http\Requests\DecodeRequest; use Illuminate\Support\Facades\Storage; use Illuminate\Http\Request; class ConvertController extends Controller { public function index() { return view('index'); } public function encode(EncodeRequest $request) { $postData = $request->validated(); // ファイルを文字列とする $file = file_get_contents($postData['file']); // ファイルをbase64でエンコード $encodedBase64Str = base64_encode($file); // view表示用データの整形 $viewData = [ 'encodedBase64Str' => $encodedBase64Str, ]; return view('index', ['viewData' => $viewData]); } public function decode(DecodeRequest $request) { $postData = $request->validated(); // base64文字列のData-URL宣言の削除 $base64Str = str_replace(' ', '+', preg_replace('/^data:image.*base64,/', '', $postData['decodeBase64Str'])); // ファイルのデコード $decodeFile = base64_decode($base64Str); // mimeの取得 $mime = finfo_buffer(finfo_open(FILEINFO_MIME_TYPE), $decodeFile); // view表示用データの整形 $viewData = [ 'decodeBase64Str' => $base64Str, 'mime' => $mime, ]; return view('index', ['viewData' => $viewData]); } } index.blade.phpを作成して下記の内容を記載する。 laravel8_base64/resources/views/index.blade.php <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Covert</title> </head> <body> <header></header> <main> <div class="encode"> <h1>ファイル → Base64 へエンコード</h1> @error('file') {{ $message }} @enderror @if ( empty($viewData['encodedBase64Str']) ) <form action="{{ route('encode') }}" method="post" enctype="multipart/form-data"> @csrf <input type="file" name="file" id="input-file"> <input type="submit" value="変換"> </form> @else <textarea name="" id="" cols="180" rows="10">{{ $viewData['encodedBase64Str'] }}</textarea> @endif </div> <div class="decode"> <h1>Base64 → ファイル デコード</h1> @error('decodeBase64Str') {{ $message }} @enderror @if ( empty($viewData['decodeBase64Str']) ) <form action="{{ route('decode') }}" method="post"> @csrf <input type="text" name="decodeBase64Str" id="input-base64_str"> <input type="submit" value="変換"> </form> @else <img src="data: {{ $viewData['mime'] }};base64, {{ $viewData['decodeBase64Str'] }}"> @endif </div> <div class="clear"> <a href="{{ route('index') }}"> <button>内容クリア</button> </a> </div> </main> <footer></footer> </body> </html> 確認 ローカルサーバーを起動して下記にアクセスする。 http://127.0.0.1:8000/decode 「ファイルを選択」をクリックして何かしらの画像ファイルを選択し「変換」をクリックする。 Base64文字列が表示されるのですべてコピーする。 「Base64 → ファイルデコード」のinput boxにコピーしたBase64文字列を入力して「変換」をクリックする。 画像に変換されて表示される。 参考文献 https://codelikes.com/php-base64-encode/ https://qiita.com/taniko/items/c76c04576c8eb38191ad https://qiita.com/bashi4/items/611ac85056f735d1cd54
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laravel8 超絶簡単なCRUD処理を作る

目的 laravel8にて超絶簡単なCRUD処理を含んだWebアプリを作る方法をまとめる 環境 ハードウェア環境 項目 情報 OS macOS Big Sur(11.6) ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) プロセッサ 2 GHz クアッドコアIntel Core i5 メモリ 32 GB 3733 MHz LPDDR4 グラフィックス Intel Iris Plus Graphics 1536 MB ソフトウェア環境 項目 情報 備考 PHP バージョン 7.4.11 Homebrewを用いてこちらの方法で導入→Mac HomebrewでPHPをインストールする Laravel バージョン 8.X commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う MySQLバージョン 8.0.21 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする 概要 投稿型SNSの超絶簡易版的なものを作ってWebアプリの基礎であるCRUDを学ぶ。 認証機能無し 画像アップロード無し とにかく文字だけ投稿できるようにする。 ただ、依存注入、サービスクラス、リポジトリクラスなどを用いて実装を行う。 そのため作り的には超絶簡単ではあるが、もしかすると初心者向けじゃないかもしれません。 他にももっと良い実装方法があるはずなので、参考の一部としていただきたい。 Macに直接laravel・MySQLローカル環境を構築してアプリを作成した。 本laravel8アプリのソース https://github.com/miriwo0104/laravel8_easy_crud 方法 アプリの作成 任意のディレクトリで下記コマンドを実行してlaravel8のプロジェクトを作成する。 $ composer create-project "laravel/laravel=8.*" laravel8_easy_crud -vvv MySQLにてテーブルの作成と.envの紹介 MySQLにてlaravel8_easy_crudテーブルを作成する。 下記のように.envファイルに記載する。(MySQLの情報の部分は皆さんの環境に合っている情報を記載してください。) laravel8_easy_curd/.env APP_NAME=Laravel8_easy_crud APP_ENV=local APP_KEY=base64:JAeeSV6U8967eYtwwcKLjS/kXjEKBZECcfXVPLXG834= APP_DEBUG=true APP_URL=http://localhost LOG_CHANNEL=stack LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=laravel8_easy_crud DB_USERNAME=皆さんのMySQLの読み書き権限のあるユーザー名 DB_PASSWORD=皆さんのMySQLの読み書き権限のあるユーザーのパスワード BROADCAST_DRIVER=log CACHE_DRIVER=file FILESYSTEM_DRIVER=local QUEUE_CONNECTION=sync SESSION_DRIVER=file SESSION_LIFETIME=120 MEMCACHED_HOST=127.0.0.1 REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 MAIL_MAILER=smtp MAIL_HOST=mailhog MAIL_PORT=1025 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS=null MAIL_FROM_NAME="${APP_NAME}" AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=us-east-1 AWS_BUCKET= AWS_USE_PATH_STYLE_ENDPOINT=false PUSHER_APP_ID= PUSHER_APP_KEY= PUSHER_APP_SECRET= PUSHER_APP_CLUSTER=mt1 MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" ルーティングの記入 ルーティング情報を下記のように記載する。 laravel8_easy_crud/routes/web.php <?php use App\Http\Controllers\ContentController; use Illuminate\Support\Facades\Route; /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::get('/', function () { return view('welcome'); }); Route::prefix('contents')->group(function() { Route::get('/list', [ContentController::class, 'list'])->name('contents.list'); Route::get('/create', [ContentController::class, 'create'])->name('contents.create'); Route::get('/update/{content_id}', [ContentController::class, 'update'])->name('contents.update'); Route::get('/delete/{content_id}', [ContentController::class, 'delete'])->name('contents.delete'); Route::post('/save', [ContentController::class, 'save'])->name('contents.save'); }); コントローラーの記載 ContentController.phpを作成して下記のように記載する。 laravel8_easy_crud/app/Http/Controllers/ContentController.php <?php namespace App\Http\Controllers; use App\Services\ContentService; use Facade\FlareClient\View; use Illuminate\Http\Request; use App\Http\Requests\ContentRequest; class ContentController extends Controller { public function __construct( ContentService $contentService ) { $this->contentService = $contentService; } /** * 投稿一覧ページの表示 * * @return view */ public function list() { $content_infos = $this->contentService->getAllContentList(); return view('contents.list', ['content_infos' => $content_infos]); } /** * 新規投稿作成 * * @return view */ public function create() { return view('contents.create'); } /** * 投稿編集 * * @param integer $content_id * @return view */ public function update(int $content_id) { $content_info = $this->contentService->getContentInfoByContentId($content_id); return view('contents.update', ['content_info' => $content_info]); } /** * 投稿削除 * * @param integer $content_id * @return view */ public function delete(int $content_id) { $this->contentService->delete($content_id); return redirect(route('contents.list')); } /** * 新規作成・投稿編集の情報保存 * * @param ContentRequest $post_data * @return view */ public function save(ContentRequest $post_data) { $this->contentService->save($post_data); return redirect(route('contents.list')); } } サービスクラスの記載 ContentService.phpを作成して下記のように記載する。 laravel8_easy_crud/app/Services/ContentService.php <?php namespace App\Services; use App\Repositories\ContentRepositoryInterface as ContentRepository; use Illuminate\Database\Eloquent\Model; class ContentService { public function __construct( ContentRepository $contentRepository ) { $this->contentRepository = $contentRepository; } /** * 投稿内容の取得 * * @return Model */ public function getAllContentList() { return $this->contentRepository->getAllContentList(); } /** * 投稿内容IDに紐づく投稿内容の取得 * * @param integer $content_id * @return Model */ public function getContentInfoByContentId(int $content_id) { return $this->contentRepository->getContentInfoByContentId($content_id); } /** * 投稿内容の保存 * * @param Request $post_data * @return Model */ public function save($post_data) { return $this->contentRepository->save($post_data); } /** * 投稿削除 * * @param integer $content_id * @return Model */ public function delete(int $content_id) { return $this->contentRepository->delete($content_id); } } リポジトリクラスの記載 ContentRepositoryInterface.phpを作成して下記のように記載する。 laravel8_easy_crud/app/Repositories/ContentRepositoryInterface.php <?php namespace App\Repositories; use Illuminate\Database\Eloquent\Model; interface ContentRepositoryInterface { /** * 投稿内容の取得 * * @return Model */ public function getAllContentList(); /** * 投稿内容IDに紐づく投稿内容の取得 * * @param integer $content_id * @return Model */ public function getContentInfoByContentId(int $content_id); /** * 投稿内容の保存 * * @param Request $post_data * @return Model */ public function save($post_data); /** * 投稿削除 * * @param integer $content_id * @return Model */ public function delete(int $content_id); } ContentRepository.phpを作成して下記のように記載する。 laravel8_easy_crud/app/Repositories/ContentRepository.php <?php namespace App\Repositories; use App\Models\Content; use Illuminate\Database\Eloquent\Model; class ContentRepository implements ContentRepositoryInterface { public function __construct(Content $content) { $this->content = $content; } /** * 投稿内容の取得 * * @return Model */ public function getAllContentList() { return $this->content ->select('*') ->where('deleted_flag', config('const.content.deleted_flag.false')) ->get(); } /** * 投稿内容IDに紐づく投稿内容の取得 * * @param integer $content_id * @return Model */ public function getContentInfoByContentId(int $content_id) { return $this->content->find($content_id); } /** * 投稿内容の保存 * * @param Request $post_data * @return Model */ public function save($post_data) { return $this->content->updateOrCreate( ['id' => $post_data->id], ['content' => $post_data->content], ); } /** * 投稿削除 * * @param integer $content_id * @return Model */ public function delete(int $content_id) { $content_info = $this->content->find($content_id); $content_info->deleted_flag = config('const.content.deleted_flag.true'); return $content_info->save(); } } ビューの記載 contentsディレクトリをlaravel8_easy_crud/resources/views直下に作成する。 create.blade.phpを作成して下記のように記載する。 laravel8_easy_crud/resource/views/contents/create.blade.php <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>新規投稿</title> </head> <body> <header></header> <main> <h1>新規投稿</h1> <form action="{{ route('contents.save') }}" method="post"> @csrf @error('content') {{ $message }} <br> @enderror <textarea name="content" cols="30" rows="10"></textarea> <input type="submit" value="投稿"> </form> </main> <footer></footer> </body> </html> list.blade.phpを作成して下記のように記載する。 laravel8_easy_crud/resource/views/contents/list.blade.php <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>投稿一覧</title> </head> <body> <header></header> <main> <h1>投稿内容</h1> <ul> <li><a href="{{ route('contents.create') }}">新規投稿</a></li> </ul> @foreach ($content_infos as $content_info) <div>{{ $content_info->content }}</div> <div>{{ $content_info->updated_at }}</div> <a href="{{ route('contents.update', ['content_id' => $content_info->id]) }}">編集</a> <a href="{{ route('contents.delete', ['content_id' => $content_info->id]) }}">削除</a> <br> <br> @endforeach </main> <footer></footer> </body> </html> update.blade.phpを作成して下記のように記載する。 laravel8_easy_crud/resource/views/contents/update.blade.php <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>編集</title> </head> <body> <header></header> <main> <h1>編集</h1> <form action="{{ route('contents.save') }}" method="post"> @csrf @error('content') {{ $message }} <br> @enderror <input type="hidden" name="id" value="{{ $content_info->id }}"> <textarea name="content" cols="30" rows="10">{{ $content_info->content }}</textarea> <input type="submit" value="保存"> </form> </main> <footer></footer> </body> </html> リクエストの記載 ContentRequest.phpを作成して下記のように記載する。 laravel8_easy_crud/app/Http/Requests/ContentRequest.php <?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class ContentRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'content' => ['required'], ]; } } マイグレーションファイルの記載 contentsテーブルを作成するためのマイグレーションファイルを用意する。 下記のように記載する。 laravel8_easy_crud/database/migrations/YYYY_MM_DD_XXXXXX_create_contents_table.php <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateContentsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('contents', function (Blueprint $table) { $table->id(); $table->text('content')->comment('投稿内容'); $table->unsignedTinyInteger('deleted_flag')->default(0)->comment('削除フラグ デフォルト:0 削除:1'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('contents'); } } 下記コマンドをlaravel8_easy_crudディレクトリで実行してマイグレーションを実行する。 $ php artisan migrate シーダーの記載 ContentSeeder.phpを作成して下記のように記載する。 laravel8_easy_crud/database/seeders/ContentSeeder.php <?php namespace Database\Seeders; use Carbon\Carbon; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\DB; class ContentSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { $contents = [ 'テスト投稿_1', 'テスト投稿_2', 'テスト投稿_3', 'テスト投稿_4', 'テスト投稿_5', 'テスト投稿_6', 'テスト投稿_7', 'テスト投稿_8', ]; $now = Carbon::now(); foreach ($contents as $content) { $info = [ 'content' => $content, 'deleted_flag' => 0, 'created_at' => $now, 'updated_at' => $now, ]; DB::table('contents')->insert($info); } } } DatabaseSeeder.phpを開いて下記のように記載する。 laravel8_easy_crud/database/seeders/DatabaseSeeder.php <?php namespace Database\Seeders; use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { /** * Seed the application's database. * * @return void */ public function run() { // \App\Models\User::factory(10)->create(); $this->call(ContentSeeder::class); } } 下記コマンドをlaravel8_easy_crudディレクトリで実行してシーダーを作動させる。 $ php artisan db:seed 確認 $ php artisan serveコマンドにてローカルサーバーを起動する。 http://127.0.0.1:8000/contents/listにアクセスする 。 下記の様に表示されることを確認する。 「新規投稿」 をクリックする。 テキストエリアになにか入力して「投稿」をクリックする。 投稿一覧ページの最下部に今投稿した内容が追加される。 任意の投稿の「編集」をクリックする。 テキストエリアにすでに投稿されている内容が初期値として格納されている。何かしらの編集をして「保存」をクリックする。 投稿一覧ページで確認すると編集内容が反映されている。 「削除」をクリックすると当該の投稿が投稿一覧ページに表示されなくなる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

サクッとLaradockでLaravel8 (&PHP8 &Nginx)

こんにちわ!今年もアドベントカレンダーの季節がやってきましたー!ヽ(=´▽`=)ノ 今年も弊社ではせめて年に1記事はなんんかアウトプットを残そう!と言うスローガンで記事を上げて行きたいと思っていますm(_ _)m なのでカレンダーが埋まっていなくてもご容赦下さい(;´Д`) さて!今年も色々新技術やらせて貰ったのですがその中から最も苦戦した(w)Laravel8 の話を書かせて貰おうと思います。 ※言い訳をすると、最近はPHPでは無い案件の方が多くなってきていて浦島状態でした・・・_(´ཀ`」 ∠)_ Laradock はLaravel 開発環境を Docker コンテナとしてローカルに即座に立ち上げが出来る画期的なOSSです。 Docker の習得には時間が掛かりますので上辺でサクッとやりたい私にとても向いていました(おい Laradock でサックリ PHP8 Laravel8 な環境を作るレシピのご紹介 今回の記事のターゲットの方は Laradock を使って簡単に Nginx PHP8 Laravel8 な環境をサックリ作りたい方を対象にしています。 (※何よりも自分が困ったので・・・) 手順は以下です。 Github でリポジトリを作成 Laradock をsubmoduleとしてリポジトリに追加 Laradock を使ってローカルにサックリ Laravel8 環境を構築して Github にPush 手順は答を知ってしまうと割と簡単でこんな感じです。 順番に説明していきます。 先ずは通常通りプロジェクト用のリポジトリを用意します。 Github上でリポジトリを作ったら、ローカルにクローンします。 ※私は~/workspaceと言うディレクトリの下にクローンしましたがお好きな場所で良いと思います。 自分のリポジトリの配下に Laradock も持ってきます。 この時、サブモジュールとして自身のリポジトリに追加するのが簡単だと思います。 git submodule add https://github.com/laradock/laradock.git laradock とコマンドで実行すれば追加されます。 操作しやすいようにAtomエディタでプロジェクトを開いておくと便利です。 Laradockの為にDocker Desktopをインストールします。 https://www.docker.com/products/docker-desktop コチラからMac版、Windows版環境に合う方をダウンロードしてインストールして下さい。 ※説明を割愛しますが、手順通りにインストールすればOKです。 言われるがままにサンプルまで実行するとこんな感じの画面になり、インストールが終了します。 Laradock を起動したらローカルの Laravel8 開発環境がもう出来てしまいます。 larabelsample/laradock/.env.example をコピーして larabelsample/laradock/.env を作ります。 .envの中の PHP_VERSION=7.4を8.0に変更します。 ※ローカルはPHP8でなくて構わないと言う場合はいじらなくて良いです。 cd laradock docker-compose up -d nginx mysql workspace phpmyadmin としてLaradockを起動させます。 コマンド実行直後に Laravel 用の Dockerコンテナ の作成が始まりますので暫く待ちます。 程なくDockerが起動しました! しかし起動しただけだとまだ404 Not Foundです。 理由は簡単で、Dockerが起動しただけでアプリケーションの中身が空っぽだからです。 なのでアプリケーションの雛形もサクッと作成して行きます。 Laradock で作成した workspace から composer を使ってプロジェクトを作成します。 docker-compose exec workspace bashとして、workspaceコンテナにログインします。 workspaceでは既に composer が実行出来る状態が整っていますので composer create-project laravel/laravel sample としてプロジェクトの作成を行います。 この時、最後の引数で指定する名前はプロジェクトの名前を指定しましょう。 ※この名前でディレクトリが作成されます。 暫くするとプロジェクトが作成されます。 終わると以下のような構成になるかと思います。 プロジェクトの作成が完了したら、一度コンテナからexitして抜けます。 もう一度 larabelsample/laradock/.env を編集します。 APP_CODE_PATH_HOST=../ を作成したプロジェクトのディレクトリに変更します。 ローカルの.envのファイルの場所から見たパスを指定するので APP_CODE_PATH_HOST=../sample とすればOKです。 ※この手順は敢えてプロジェクト作成の後からやる必要がある事に注意が必要です。 また、作成したプロジェクトの.envファイルの設定も変更します。 larabelsample/sample/.envが作成されているハズです。 larabelsample/sample/.envの DB_HOST=127.0.0.1 を DB_HOST=mysql に変更して下さい。 作成した Docker コンテナのmysqlを向いてくれるようになります。 最後に Nginx を再起動して localhost にアクセスしてみましょう! cd laradock docker-compose up -d nginx 上記コマンドで再設定したenvに沿ってコンテナが再構築されますので暫く待ちましょう。 再構築が完了し、無事起動したらいよいよ http://localhost にアクセスしてみましょう! 無事完了していれば Nginx Laravel8 PHP8 と言う環境でスタートページが表示されると思います。 PHPMyAdmin にもアクセスが出来るようになっているハズです。 http://localhost:8081/ にアクセスしてみましょう。 ※デフォルトの接続設定は以下です サーバー: mysql ユーザー名: root パスワード: root 無事アクセス出来れば設定は無事完了しています。 このままGitにPushしてしまって、もうOKです。 直ぐにチーム開発が始められると思います。 個人的には larabelsample/sample/.env はバージョン管理に入れてしまって良いと思います。 ※標準では larabelsample/sample/.gitignore で ignore されています。 .envをバージョン管理に置くことでチームメイトはGitリポジトリをCloneするだけで開発が始められるようになります。 ※但し、.envにはDBのパスワードを記述しているのでプライベートリポジトリの場合のみのオススメになります。 以上長くなりましたが Laradock でサックリ PHP8 Laravel8 な環境を作るレシピのご紹介でした。 参考になれば幸いです! 最後まで読んで頂き有難う御座いました!それでは!!m(_ _)m
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む