BeginnerEngineerBlog
中の人
中の人

laravelで保存前にmodelの値を変更したい

公開: 2021-09-26 21:52
更新: 2023-04-06 14:59
4105
laravel6.x eloquent boot observer
laravelでmodelを保存する前に、modelのパラメータを操作して保存する方法を紹介したいと思います。

こんにちは!

laravelで、modelを保存前に値を操作したいときってありますよね?
(ここで言う操作とは、controllerとかの処理の中でという意味ではなく、データベースにinsert、またはupdateされる直前に、という意味です。)

ないですか?

ないかー(*≧∀≦*)< フツウネーヨ!!

私はありました!(*≧∀≦*)< アッタンカイ!!

ということで、laravelでmodelをcreateやupdateした際に処理を介入させて、modelの値を操作する方法を紹介したいと思います!
(ちなみにここで使用するlaravelプロジェクトは勝手にlaravelチュートリアルで作成したTutorialアプリケーションを利用しています。)

observer


まずはobserverを紹介します。

参考リンクでは、create後、update後の処理の介入が紹介されてますが、create,update前にmodelの値を変更してsaveするという処理もできます。

それでは紹介していきます!

まず、ターミナルで
php artisan make:observer TestObserver --model=Article

と適当なファイル名で、値を操作したいmodelを指定してobserverクラスを作成しましょう!

📁 App/Observers/TestObserver.php

<?php

namespace App\Observers;

use App\Article;

class TestObserver
{
    /**
     * Handle the article "created" event.
     *
     * @param  \App\Article  $article
     * @return void
     */
    public function created(Article $article)
    {
        //
    }

    /**
     * Handle the article "updated" event.
     *
     * @param  \App\Article  $article
     * @return void
     */
    public function updated(Article $article)
    {
        //
    }

    /**
     * Handle the article "deleted" event.
     *
     * @param  \App\Article  $article
     * @return void
     */
    public function deleted(Article $article)
    {
        //
    }

    /**
     * Handle the article "restored" event.
     *
     * @param  \App\Article  $article
     * @return void
     */
    public function restored(Article $article)
    {
        //
    }

    /**
     * Handle the article "force deleted" event.
     *
     * @param  \App\Article  $article
     * @return void
     */
    public function forceDeleted(Article $article)
    {
        //
    }
}

するとこんなファイルが作成されます。

で、今回は保存する前に値を操作したいので、ここで定義されているアクションを全て削除して、代わりに以下のようにアクションを定義してください。

//~~省略
use App\Article;
//~~省略
public function creating(Article $article)
{
    //
}

public function updating(Article $article)
{
    //
}

creating,updatingは、保存、または更新される直前に呼び出されるアクションになります。

そしたら、AppServiceProvider.phpを以下のように編集します。

📁 App/Providers/AppServicePrivider.php

//~省略
use App\Article;
//~省略

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    //↓追加
    Article::observe(\App\Observers\TestObserver::class);
}

bootアクションに作成したobserverを追加します。

これでobserverを使う準備が整いました。

では、一旦このmodelが保存される処理を実行してみましょう。


はい、適当にArticle作成のアクションを実行してみます。


ちゃんと入力された通り保存されてますね。

では、保存する直前にtitleを入力された値と違う値を保存するように実装してみます。
TestObserver.phpを以下のように編集してください。

public function creating(Article $article)
{
    $article->title = 'creating!';
}

一旦、新規保存時にタイトルを上記のように"creating!"として保存したいと思います。

そしたら、再度適当に記事を保存してみます。


では保存してみます。


titleがcreating!になってますね!

では、次に更新をしてみます。

TestObserverを以下のように編集します。

//~~省略

public function updating(Article $article)
{
    $article->title = 'updating!';
}

次はupdatingを上記のように編集します。

そしたら記事を編集してみます。


これは先ほど作成した記事になります。

そしたら登録してみます。



はい、先ほど登録した記事のタイトルがupdating!になってますね!

observerでmodelの値を操作する紹介は以上になります。


次に、modelで値を操作するやり方を紹介します。

boot関数


では、保存前に値を操作したいmodelへ以下の関数を追記してください。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
    //~~省略

    public static function boot()
    {
        parent::boot();
    }
}

ちなみにparent::boot();はよくわかりません。よくわかりませんが、まぁ親クラスのboot関数を上書きしているということなので、親クラスのboot関数を先に実行する的な感じだと思います。これを書いておかないとエラーになります。

そしたら、新規登録時に値を操作する処理を記載します。

public static function boot()
{
    parent::boot();
    self::creating(function (self $article) {
        $article->title = 'model_creating';
    });
}

observerで定義したように、こちらも"creating"を指定します。

では、適当にmodelを登録してみましょう。


で、登録してみます。


ちゃんとtitleの値が変わってますね!

では、更新もやってみます。
modelを以下のように編集してください。

public static function boot()
{
    parent::boot();
    self::creating(function (self $article) {
        $article->title = 'model_creating';
    });
    self::updating(function (self $article) {
        $article->title = 'model_updating';
    });
}

updatingを追加します。
では、先ほど作成したArticleを編集してみます。


適当に値をいれて更新してみます。



ちゃんとtitleがmodel_updatingになってますね!

ということで以上でmodelの値を操作する紹介を終わります!

ここで紹介した方法の他にもやり方ありそうなので、気になった方は調べていろいろ試してみましょう!
個人的には、modelに定義する方がわかりやすいのかなーと感じていますが、みなさんのやりやすい方法で実装しましょう!


終わりに


今回記事にした理由は、observerや、modelでboot関数使っていろんな処理をする記事が色々ありましたが、紹介させていただいた記事のように、

  • modelを作成、または更新した後に、通知をする
  • modelを作成、または更新した後に、ログに出力する

的な記事が多かったので、model自体の値も操作することもできたので記事にしてみました。

ですが、正直なところ、今回紹介した内容は、ほぼほぼ実装する機会がないじゃないかなとも思っています。

が、私は冒頭で説明した通り、ありました!

というのも、

  • データベースのフィールドはnot null
  • 対応するフォームのvalidationはnullable

という仕様があったからです!
なので、保存する際、対象の値がnullの場合、空文字を保存する必要があったのです。
コントローラなどで値を操作するのもスマートではない気がしたので、今回実装することになりました。

データベース設計がおかしいという指摘は受け付けていません!(☝︎ ՞ਊ ՞)☝︎< ダマッテロ!!

ということで、皆さんもこのような実装が必要な時は参考にしてみてください!

ちなみに今回の実装はTutorial - modelの値を直前で変更 ブランチにプッシュしていますので合わせて参考にしてください!
0
0
0
0
通信エラーが発生しました。
似たような記事