カテゴリーアーカイブ Laravel

著者:杉浦

【Laravel】Laravel Mixにそこそこ複雑な仕事を任せる

 Laravel MixはLaravelプロジェクト組み込みのwebpackラッパーです。webpackの基本的な設定やコンパイル用のスクリプトを準備しておいてくれる点とLaravel用のバージョニングやら環境変数やらと結びついている点が利点になります。普通に使う分には以下の様なコンパイル対象を宣言するだけで問題ないです。これだけで十分便利です。

const mix = require('laravel-mix');

mix.sass('src/app.sass', 'dist')
   .js('src/app.js', 'dist');

 しかしフロントエンド側の開発環境を凝ろうとするとこれだけでは少々不便です。vuejs/vue-clifacebook/create-react-appの様なフロントエンドに注力する開発環境を別途用意しSPAを作るやり方についての記事もググればまあまあ出てきます。SPAを作る時はLaravelをAPIに注力させます。
 Laravel Mixは前述の二種ほどでないにせよ、いくらか複雑なこともできます。ドキュメントはLaravelそのものとは別にあります。Laravel Mix
Laravel Mix Extensions
 とりあえずで使える広範なカスタマイズはwebpack本来のconfigを注入する方法で以下のコードの通りです。

mix.webpackConfig({
    resolve: {
        modules: [
            'node_modules',
            path.resolve(__dirname, 'vendor/laravel/spark/resources/js')
        ]
    }
});

Quick Webpack Configuration | Laravel Mix Documentation
 webpackConfig関数の中身にはwebpack.config.jsでexportされるobject同様のモノを入れればOKです。その様にすればLaravel Mix側でうまい具合にマージしてくれます。
Configuration | webpack
 Laravel自身バックエンド用ということもあり任せられる仕事は程々です。それぐらいはできるので気持ち複雑程度の課題ならばわざわざフロントエンド開発用フレームワークを用いるのでなくLaravel Mixで済ませたいです。

  • この記事いいね! (0)
著者:杉浦

【Laravel】簡易なコントローラ単位のテストをする

 テストを書き、自動化できると何かと楽です。ライブラリのアップデートによって機能が壊されていないか確認するときなど全機能を総なめするので大変助かります。Laravelにおいて、あるアドレスにアクセスされた時にはあるコントローラのあるメソッドが動かされる様になっています。コントローラの各メソッドをテストすることができれば、各ページのPHPに関しての結合テストが完了します。もしAPIとして閉じているならば、これだけで全体のテストがほぼ完了します。
 コントローラのメソッドの起動と結果は大仰です。完璧なリクエストを生成するのも、モックのDB(データベース)を用意するのも手間です。この記事ではなるべく楽にまあまあの動きができるものを作ります。
 リクエストの作り方です。守るべきコード規約を一つ作ります。次の様にRequestクラスを記述し、リクエストのボディを参照するときはRequestインスタンスのプロパティから見る、というものです。

// HogeRequest.php
/**
 * @property string $id
 * @property string $name
 */
class HogeRequest extends FormRequest
{
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'id' => 'required|string',
            'name' => 'required|string',
        ];
    }
}
// FugaController.php

class FugaController extends Controller
{
    public function foo(HogeRequest $request)
    {
        $id = $request->id;            // こんな感じで取得する.get, post等のリクエスト形式を考慮しなくていいし値なしならnullが返ってくる
        $name = $request->get('name'); // この取り方をやめる
        $desc = $request->desc ?? '説明文'; // デフォルト値が欲しいならこんな感じ
    }
}

 こうするとテスト中では次のように記述するだけでテストで使うためのRequestインスタンスが出来、次のようにテストをささっと書けます。

    public function testFoo()
    {
        $request = new HogeRequest();
        $request->id = 'idの値';
        $request->name = 'nameの値';

        $response = $this->controller->foo($request);
        self::assert($expected, $response);
    }

 headerなどを見るならもう少し拡張する必要があります。
 リクエストを投げてどうこうされる処理にはDBを触るものもあります。DBの中身が変わると不都合な時もあり、テストの際にはDB中のデータを保護したいです。これを実現するのは割と簡単で全単体テスト共通の親クラスTestCaseを用意して次の様にトランザクションとロールバックを仕込むだけで完成です。ブラウザを介してDBを弄らない単体テストの範囲だからこそ簡単にできます。

<?php

namespace Tests;

use Exception;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Throwable;

/**
 * 基礎. DBの保護などの全テスト共通処理を記述する.
 * Class TestCase
 * @package Tests
 */
abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;

    /**
     * @throws BindingResolutionException
     * @throws Exception
     */
    public function setUp(): void
    {
        parent::setUp();
        $this->app->make('db')->beginTransaction();
    }

    /**
     * @throws BindingResolutionException
     * @throws Throwable
     */
    public function tearDown(): void
    {
        $this->app->make('db')->rollBack();
        parent::tearDown();
    }
}

 もちろんメールやらSlackやらLINEやら色々とこの記事のやり方に納まらないものもありますが結構な範囲をカバーできて便利です。

  • この記事いいね! (1)
著者:杉浦

【Laravel】Laravel6.0がリリース

 Laravelのメジャーバージョンアップである6.0が正式リリースされました。
Laravel 6 Is Now Released – Laravel News
Installation – Laravel – The PHP Framework For Web Artisans
 Laravel6.0は運用者に優しい作りになっています。まずLTSであり、2022/9/3までセキュリティ面のサポートが得られます。また、セマンティック バージョニングに則ります。セマンティック バージョニングのルールが守られる限り、バージョン6.0の機能はバージョン6.1や6.2で損なわれません。6.*,*の最新になる様アップデートを続けるだけで機能を損なわずサポートを得られ長期間の運用に耐えます。
セマンティック バージョニング 2.0.0 | Semantic Versioning
 既存プロジェクトの更新のためにはUpgrade Guide – Laravel – The PHP Framework For Web Artisansを、新機能のざっくばらんとした把握のためにはLaravel 6 Is Now Released – Laravel Newsを読むと楽です。
 フロントエンド側のフレームワークとしてVue.jsが備え付けられていましたが、6.0からはVue.jsとReactの選択式になりました。業界のシェア的にはReactの方が多いので今後はLaravelとReactのセットを使うライブラリやプロトタイプも増えそうです。
JavaScript & CSS Scaffolding – Laravel – The PHP Framework For Web Artisans

  • この記事いいね! (2)
著者:杉浦

【Laravel】バージョンごとの変更点をリファレンスリポジトリ中のファイル差分から見つける

 Laravelは週単位でとても細かくリリースされていますが、それとは別に5.7, 5.8, 6.0などと中くらいの単位、大きな単位でも更新されています。そういった大きな更新の際には、それまでにあった小さな多数の更新の内の注目すべき変更点をリファレンスに載せます。LaravelはリファレンスもGitHubで管理されており、これを扱うことでバージョンごとの違いを容易に比べることができます。
 laravel/docs
 特に有効なのはバージョンを示すブランチ間の比較でしょう。例えば、最新の5.8と9/2にリリースの決まった6.0のブランチの差分が次のリンクから読めます。プルダウンで任意のブランチを選ぶこともできます。
 Comparing 5.8…6.0 · laravel/docs
 これのFiles Changedから見ていって、例えば次のようにあります。

 6.0ではLaravelデフォルトの認証機能プロトタイプをプロジェクト内に設置するコマンドはphp artisan make:authからphp artisan ui vue –authに代わり、composerパッケージのlaravel/uiを入れておく必要もあるとわかります。同様に順々にファイル差分を読んでいくことで大きな変更点を見つけられます。
 ちなみにlaravel/uiはVue.jsで作るLaravelデフォルトの画面を扱うためのリポジトリの様です。
laravel/ui

  • この記事いいね! (1)
著者:杉浦

【Laravel】リポジトリlaravel/laravelとlaravel/frameworkの違い

 Laravelのソースコードリポジトリには全く同じ対象について記述されたリポジトリであるlaravel/laravelとlaravel/frameworkの二つがあります。

 laravel/laravel: A PHP framework for web artisans
 laravel/framework
この二つには安定した製品版と開発版の様なものです。もちろんlaravel/frameworkにもmasterブランチがあり、定期的にリリースをしていますがlaravel/laravelはそれ以上に安定です。この二つの最も違う点はcomposerでの呼び出し方でしょう。laravel/laravelは次の様に呼び出され、Laravelプロジェクトの初期状態を作ります。

composer create-project laravel/laravel

 laravel/frameworkは次のように呼び出され、vendor以下にLaravelフレームワークのコードを配置するのみです。

composer require laravel/framework

 GitHubから確認できるリリースの頻度もまるで違います。laravel/laravelが下の様に一気にバージョンアップしてるのに対し、

laravel/frameworkは週一で定期的にアップデートしています。

 最新の機能や残存するバグなどを見るにはlaravel/frameworkを追うのがやりやすいです。

  • この記事いいね! (1)
asaba 著者:asaba

ルーティング処理について

最近はバックエンド側も触れるようになりたいと思い、少ない時間を見つけて

自宅でlaravelをいじっております。

mvcの概念を頭に入れこむのに少し時間がかかりましたがおおよその流れだけは理解

できたのかなと感じています。とはいってもまだ覚える必要のあるものもたくさん

あるので忘れないように今回みたいにちょくちょく書いていきます。(でないと忘れるので)

 

という訳でルーティング処理の概念について少しおさらいします。

ルーティングというのは、各ページにて処理をあらかじめ決めておき、どのアドレスでどのような処理を

返すかを選定する決め事のようなものです。

書く場所としてはroutes/web.phpの中が適正です。つまり、このページを見ることで

処理をするページのアドレスと処理の内容(返す値)を一括で知ることが出来るので

いちいちページに行って確認する必要がなくなります。

ただ単純に文字列を返すだけだとこんな感じになります。


Route::get(&lt;span class="hljs-string"&gt;'posts/{id}'&lt;/span&gt;,

&lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;&nbsp; function&lt;/span&gt; &lt;span class="hljs-params"&gt;($id)&lt;/span&gt; &lt;/span&gt;{ &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-string"&gt;'あなたのidは&lt;/span&gt;&lt;span class="hljs-string"&gt;'&lt;/span&gt;$id.&lt;span class="hljs-string"&gt;'番です'&lt;/span&gt;; }

);

一つ目の引数にはアドレスの隣にページに渡す値を持たせています。保持することによって

このアドレスのページで受け取って使うことができます。

二つ目の引数は受け取った値で処理をした結果を持たせています。

ざっくり答えるとposts/{id}ページはidを教えてくれるページとなっており、受け取った

値によって結果を変える動的なファイルとなっています。

 

これだけでは実用性があるとまではいえないので、viewを返すルーティング処理を

書いていきます。

なんにもない普通のviewを返すコードです。


<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Laravel</title>
</head>
<body>
<form>
<h1>フォーム</h1>
<div>
<input type="text" placeholder="asaba"/>
</div>
<div>
<textarea placeholder="お問い合わせ"></textarea>
</div>
</form>
</body>
</html>

ディレクトリは「resources/views/sample.blade.php」です。

(ここではBladeというテンプレートエンジンを使っていますが自分でも

まだわかっていない部分があるので割愛させていただきます。)

 

お次はまたルーティングを書いていきます。


Route::get('/sample', function() {
return view('sample');
});

第一引数でパスを決めるとこまでは同じですが、returnの中ではviewそのもの

を返しているのが分かります。

 

これでhtmlひとかたまりを表示することはできました。後はこれとmvcを組み合わせてきれいな

コードを書きあげれば一歩踏み出したことになります。

今回はページをルーティングを使って値を返すだけの内容でしたが、いずれはmodelで

DBを操作したりcontorollerで非同期処理をしてみたりということも書けたらなと思っています。

 

  • この記事いいね! (0)
著者:杉浦

【Laravel】Laravel 6.0がリリース間近

 Laravel6.0はLaravelのメジャーアップデートであり新たなLTSバージョンです。リリースは8月中だとかなんだとか。


 メジャーアップデートですが予想されているアップデート所要時間は1時間程です(参考として5.5から5.6は10~30分、5.6から5.7が10~15分、5.7から5.8が1時間)。変更点は配列、文字列のヘルパ関数の置き換えやEloquent(laravelのデータベースと密結合したベースモデル)の一部と多用される部分にあるので多くのユーザが変更の影響を受けるでしょう。

 Upgrade Guide – Laravel – The PHP Framework For Web Artisans
 前回のメジャーアップデートである4.2から5.0へのアップデート方法には5.0のプロジェクトを新規作成して適宜ファイルを移動しろ、とあります。ユーザビリティの発展を感じますね。
 アップグレードガイド 5.0 Laravel

  • この記事いいね! (2)
著者:杉浦

【Laravel】データベースと無関係のEloquentっぽいモデルを作るためのFluentクラス

 LaravelはEloquentクラスにモデルをまとめています。Eloquentはデータベース中のテーブルに対応して扱われることを前提としたORMです。
Eloquent:利用の開始 5.8 Laravel
 webサービスにおいてモデルが欲しい時は大体、対応したテーブルを用意するのですが、時にはデータベースに関係なくモデルを作りたい時があります。具体的には別のサービスで吐き出されたファイルの中身を扱う時などです。そういった時に手製のクラスファイルを作成するのも一つの手ですが、何かしたいことが増える度に簡単なことでも一々コードを書く必要があります。何かしら継承なりuseしたいですがEloquentを継承するのは危険です。誤った呼び出し一つで存在しない場所を参照するSQLを投げるがPHP的には正しいコードが出来上がります。
 FluentはLaravelの\Illuminate\Support\Fluentに位置しているEloquentの様なプロパティ制御とjson、array扱いの要素(ArrayAccess, Arrayable, Jsonable, JsonSerializableのinterfaceを満たしている)を持った素朴なクラスです。Laravel内部で扱われているのが基本でドキュメントなしのクラスです(Laravel4とかの頃のモデルクラスっぽい?)。Fluentのコンストラクタは次の様になっており、適宜new Fluent(パラメータ配列)をすることでデータベースに関係ないEloquentライクなモデル実体を扱えます。

    /**
     * Create a new fluent instance.
     *
     * @param  array|object  $attributes
     * @return void
     */
    public function __construct($attributes = [])
    {
        foreach ($attributes as $key => $value) {
            $this->attributes[$key] = $value;
        }
    }

 継承して、そのクラスをnewしただけでインスタンスにさせたいこと、インスタンスから知りたいことの設定が完了します。クラスだけ作って何も中身がないのに自在に動く様はEloquentを彷彿とさせます。
 簡単にnewする対象を探索する処理を入れるとなお便利です。例えば次の様なstaticメソッドを生やすことでなお扱いやすくなります。

    /**
     * ファイル名で探す。
     * @param  string $filename
     * @return mixed
     */
    public static function find(string $filename)
    {
        $disk = Storage::disk('hoge_files');
        if(!$disk->exist($filename)){
            return null;
        }
        $meta_data = $disk->getMetadata($filename);
        $body_data = self::parse($disk->get($filename));
        
        return new self(array_merge($meta_data, $body_data);
    }

 バリデータを作ってコンストラクタ中で呼び出す様な仕組みを作るとプロパティに何があるのかきっちり決まり更に更に安全安心に使えます。

  • この記事いいね! (1)
著者:杉浦

【Laravel】Duskのテストケースを楽に作るChrome拡張Laravel TestToolsの紹介

 DuskはLaravelと密にかかわっている自動ブラウザテストツールです。実際にブラウザを開いて、あるページへ移動できるか、そのページである操作はできるか、操作の結果は想定した通りか、といったテストを自動で行ってくれます。ブラウザを用いる以上しょうがないかもしれませんが実行時間が長いのが玉に瑕です。
Laravel Dusk 5.8 Laravel
 テストコードは例えば次の様に書けます。

    public function testBasicExample()
    {
        $user = factory(User::class)->create([
            'email' => 'taylor@laravel.com',
        ]);

        $this->browse(function ($browser) use ($user) {
            $browser->visit('/login')
                    ->type('email', $user->email)
                    ->type('password', 'secret')
                    ->press('Login')
                    ->assertPathIs('/home');
        });
    }
    /**
     * <a href="https://readouble.com/laravel/5.8/ja/dusk.html">Laravel Dusk 5.8 Laravel</a>から引用
     */

 テストユーザを作成。/loginへ訪れて、name=”email”のinputタグにテストユーザのemailを入力、name=”password”のinputタグに’secret’と入力、Loginと書かれたボタンを押し、押した後のページのアドレスが/homeであることを確かめるコードです。簡単に記述するために相当暗黙知が入っています。慣れれば楽なのですが、慣れるまで具体的にどこの何が何であれば期待した通りに動作するのか、少し戸惑います。Laravel TestToolsは操作の記述を楽にしてくれます。
Laravel TestTools – Chrome ウェブストア
 具体的に何をするかというと操作の記録とコード起こしです。次のgifの様に録画ボタンを押すと動作を記録します。

 書き起こされたコードをコピペするだけで操作分の記述完成です。これでtype()やpress()を記述する際にそう悩む必要がありません。後はassertで確かめるだけです。

  • この記事いいね! (1)
著者:杉浦

【Laravel】一プロセス内限定のSQLのキャッシュを作る

 ORMは便利ですが、何度も重複するクエリを発行しがちです。複数のモデルオブジェクトeachしてリレーション先を参照する時は特に危険です。どれくらい重複してるかは
 barryvdh/laravel-debugbar: Laravel Debugbar (Integrates PHP Debug Bar)
 などで調べるのが楽です。duplicatedとuniqueに分けてくれます。

 やり方の方針はクエリが発行される度にそのクエリに対応するキャッシュはあるかチェック、あるならばキャッシュを結果として取得、なければ実際に発行して結果を取得してキャッシュに保存、です。
 一つのクエリに使う場合は次です。

        $key = __FILE__.' '.__FUNCTION__.' '.__LINE__ .' '.$id;
        app()->offsetExists($key) ?: app()->singleton($key, static function () use ($id){
            return Member::where('id',$id)->get();
        });

 コードの場所と引数に関して一意になるキーを設定。クエリの結果をシングルトンに登録することによって、同じ場所が同じ引数で繰り返し呼ばれる際、同じクエリを発行することなく、Laravel内にバインドされたシングルトンを呼ぶようになります。変数なのでプロセスが終わったら揮発します。
 作った後しばらくして気づきましたがarrayドライバ(array型の変数内にキャッシュを保存する機能)でキャッシュ使った方がシンプルですね。
 全体のクエリに使う場合はDBのselect等データ取得時のリスナーに同じ処理を入れます。updateした時のリスナーにキャッシュ消す処理忘れるとバグの元になります。

  • この記事いいね! (1)