成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Laravel 中的模型事件與 Observer

Yuanf / 2833人閱讀

摘要:模型事件在的世界中你對大多數(shù)操作都會或多或少的觸發(fā)一些模型事件今天就來看一下模型事件的使用。事先已經(jīng)定義好了個模型事件以供我們使用它們分別是。和會在數(shù)據(jù)庫中的真值修改前后觸發(fā)。監(jiān)聽數(shù)據(jù)即將保存的事件。監(jiān)聽數(shù)據(jù)從軟刪除狀態(tài)恢復后的事件。

模型事件

Laravel 的世界中,你對 Eloquent 大多數(shù)操作都會或多或少的觸發(fā)一些模型事件,今天就來看一下模型事件的使用。

Laravel 事先已經(jīng)定義好了 10 個模型事件以供我們使用,它們分別是:

creating, created , updating, updated, saving, saved, deleting, deleted, restoring, restored。

事件名稱都很淺顯易懂,相信如果你是用腦子寫代碼的話都應該可以看明白,如果不明白的話可以左轉(zhuǎn)百度。

不過你可能對 updating, updated, saving, saved 這四個事件有所疑惑,所以我們來詳細分析一下。

打開 IlluminateDatabaseEloquentModel ,找到位于 517 行的 save 方法

筆者使用的是 Laravel 5.5 最新版本,如果你使用的是其他版本,請自行在官方文檔 版本差異 中對比你的版本

public function save(array $options = [])
{
    $query = $this->newQueryWithoutScopes();

    if ($this->fireModelEvent("saving") === false) {
        return false;
    }

    if ($this->exists) {
        $saved = $this->isDirty() ?
                    $this->performUpdate($query) : true;
    }

    else {
        $saved = $this->performInsert($query);

        if (! $this->getConnectionName() &&
            $connection = $query->getConnection()) {
            $this->setConnection($connection->getName());
        }
    }

    if ($saved) {
        $this->finishSave($options);
    }

    return $saved;
}

可以看到首先觸發(fā)的是 saving

$this->fireModelEvent("saving")

接著會判斷此 model 是不是新創(chuàng)建的。

如果是新創(chuàng)建的,那么則會進行 insert 操作,由于本例是分析修改操作,所以這里直接略過。

如果不是新創(chuàng)建的,那么會調(diào)用 isDirty 方法判斷此 model 是否進行了修改。

如果進行了修改,那么會調(diào)用 performUpdate 方法進行更新操作,如果沒有進行修改,則直接返回 true。

讓我們點開 performUpdate 方法。

protected function performUpdate(Builder $query)
{
    if ($this->fireModelEvent("updating") === false) {
        return false;
    }

    if ($this->usesTimestamps()) {
        $this->updateTimestamps();
    }

    $dirty = $this->getDirty();

    if (count($dirty) > 0) {
        $this->setKeysForSaveQuery($query)->update($dirty);

        $this->fireModelEvent("updated", false);

        $this->syncChanges();
    }

    return true;
}

可以看到這里會觸發(fā) updating

$this->fireModelEvent("updating")

如果返回的不是 false ,那么會接著往下走,判斷一下此模型是否使用了 Timestamp,如果使用了,那么則先更新自身的 Timestamp

if ($this->usesTimestamps()) {
    $this->updateTimestamps();
}

接著調(diào)用 getDirty,顧名思義,大概可以知道這個方法是獲取自身的臟值,讓我們點開看一下:

public function getDirty()
{
    $dirty = [];

    foreach ($this->getAttributes() as $key => $value) {
        if (! $this->originalIsEquivalent($key, $value)) {
            $dirty[$key] = $value;
        }
    }

    return $dirty;
}

意料之中,此方法內(nèi)會返回自身被修改后的臟值,如果你打印過 LaravelModel 實例,那么相信你會看到實例中有 originalattributes 兩個數(shù)組。

其中 original 保存的是最初始的實例屬性,無法被外部直接修改。

attributes 數(shù)組則是可以被自有修改,此方法即是由判斷兩個數(shù)組的差異而返回臟值,由于時間原因,這里不做過多詳解,有機會單開一個文章慢慢講。

繼續(xù)往下走,可以看到這里會判斷一下是否有臟值:

if (count($dirty) > 0)

只有在存在臟值的情況下才會進入 if 內(nèi)部,執(zhí)行 update 操作,繼而觸發(fā) updated 事件

update 結(jié)束后會執(zhí)行一下 syncChanges 同步一下自身的數(shù)據(jù)

OK, performUpdate 方法解析完畢,讓我們回到 save 方法,接著往下看,可以看到 Laravel 最后做了一個判斷:

if ($saved) {
    $this->finishSave($options);
}

只有在 update 成功的情況下,才會觸發(fā) finishSave() 方法,此方法會接收一個參數(shù) $options,即是修改的屬性。

讓我們點開此方法:

protected function finishSave(array $options)
{
    $this->fireModelEvent("saved", false);

    if ($this->isDirty() && ($options["touch"] ?? true)) {
        $this->touchOwners();
    }

    $this->syncOriginal();
}

可以看到在此方法內(nèi)會觸發(fā) saved 事件

分析完畢,大概可以做一個總結(jié)了。

當模型已存在,不是新建的時候,依次觸發(fā)的順序是:

saving -> updating -> updated -> saved

當模型不存在,需要新增的時候,依次觸發(fā)的順序則是

saving -> creating -> created -> saved

那么 saving,savedupdating,updated 到底有什么區(qū)別呢?

上面已經(jīng)講過,LaravelEloquent 會維護實例的兩個數(shù)組,分別是 originalattributes。

只有在 saved 事件觸發(fā)之后,Laravel 才會對兩個數(shù)組執(zhí)行 syncOriginal 操作,這樣就很好理解了。

updatingupdated 會在數(shù)據(jù)庫中的真值修改前后觸發(fā)。

savingsaved 則會在 Eloquent 實例的 original 數(shù)組真值更改前后觸發(fā)。

這樣我們就可以根據(jù)業(yè)務(wù)場景來選擇更合適的觸發(fā)事件了~

Observer (觀察者)

如果你想在一個模型中監(jiān)聽多個事件,那么你可以把它寫成一個類,類中的方法名稱即是你想要監(jiān)聽的事件名稱

class UserObserver
{

    /**
     * 監(jiān)聽數(shù)據(jù)即將創(chuàng)建的事件。
     *
     * @param  User $user
     * @return void
     */
    public function creating(User $user)
    {

    }

    /**
     * 監(jiān)聽數(shù)據(jù)創(chuàng)建后的事件。
     *
     * @param  User $user
     * @return void
     */
    public function created(User $user)
    {

    }

    /**
     * 監(jiān)聽數(shù)據(jù)即將更新的事件。
     *
     * @param  User $user
     * @return void
     */
    public function updating(User $user)
    {

    }

    /**
     * 監(jiān)聽數(shù)據(jù)更新后的事件。
     *
     * @param  User $user
     * @return void
     */
    public function updated(User $user)
    {

    }

    /**
     * 監(jiān)聽數(shù)據(jù)即將保存的事件。
     *
     * @param  User $user
     * @return void
     */
    public function saving(User $user)
    {

    }

    /**
     * 監(jiān)聽數(shù)據(jù)保存后的事件。
     *
     * @param  User $user
     * @return void
     */
    public function saved(User $user)
    {

    }

    /**
     * 監(jiān)聽數(shù)據(jù)即將刪除的事件。
     *
     * @param  User $user
     * @return void
     */
    public function deleting(User $user)
    {

    }

    /**
     * 監(jiān)聽數(shù)據(jù)刪除后的事件。
     *
     * @param  User $user
     * @return void
     */
    public function deleted(User $user)
    {

    }

    /**
     * 監(jiān)聽數(shù)據(jù)即將從軟刪除狀態(tài)恢復的事件。
     *
     * @param  User $user
     * @return void
     */
    public function restoring(User $user)
    {

    }

    /**
     * 監(jiān)聽數(shù)據(jù)從軟刪除狀態(tài)恢復后的事件。
     *
     * @param  User $user
     * @return void
     */
    public function restored(User $user)
    {

    }
}

然后在 AppServiceProvider 中注冊此觀察者


然后你就可以在你注冊的 Observer 中觀測到各種事件啦~

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/26187.html

相關(guān)文章

  • Laravel學習筆記之Model Observer模型觀察者

    摘要:說明本文主要學習下的模型觀察者,把一點點經(jīng)驗分享出來希望對別人能有幫助。模型觀察者這個功能能做很多事情,比如模型更新時發(fā)個通知??偨Y(jié)本篇文章主要學了下的模型觀察者,發(fā)現(xiàn)這個功能也能使代碼結(jié)構(gòu)更清晰,覺得挺好的。 說明:本文主要學習下Laravel的Model Observer模型觀察者,把一點點經(jīng)驗分享出來希望對別人能有幫助。同時,作者會將開發(fā)過程中的一些截圖和代碼黏上去,提高閱讀效率...

    Crazy_Coder 評論0 收藏0
  • Laravel核心解讀--觀察者模式

    摘要:模式定義觀察者模式定義對象間的一種一對多依賴關(guān)系,使得每當一個對象狀態(tài)發(fā)生改變時,其相關(guān)依賴對象皆得到通知并被自動更新。 觀察者模式 Laravel的Event事件系統(tǒng)提供了一個簡單的觀察者模式實現(xiàn),能夠訂閱和監(jiān)聽應用中發(fā)生的各種事件,在PHP的標準庫(SPL)里甚至提供了三個接口SplSubject, SplObserver, SplObjectStorage來讓開發(fā)者更容易地實現(xiàn)觀...

    lei___ 評論0 收藏0
  • Laravel學習筆記之Redis保存頁面瀏覽量

    摘要:說明本文主要講述使用作為緩存加快頁面訪問速度。何不用來做緩存,等到該達到一定瀏覽頁面后再刷新下,效率也很高??勺骶彺嫦到y(tǒng)隊列系統(tǒng)。 說明:本文主要講述使用Redis作為緩存加快頁面訪問速度。同時,作者會將開發(fā)過程中的一些截圖和代碼黏上去,提高閱讀效率。 備注:作者最近在學習github上別人的源碼時,發(fā)現(xiàn)好多在計算一篇博客頁面訪問量view_count時都是這么做的:利用Laravel...

    z2xy 評論0 收藏0
  • 使用qq郵箱服務(wù)器來實現(xiàn)laravel的郵件發(fā)送

    摘要:本文來自原文鏈接歡迎作客我們的學習群在我們的底層核心技術(shù)實戰(zhàn)揭秘視頻中我們帶領(lǐng)大家使用了專業(yè)的郵件測試服務(wù)來體驗郵件發(fā)送的前前后后,下面給大家分享下利用郵箱服務(wù)器來實現(xiàn)的郵件發(fā)送。 本文來自pilishen.com----原文鏈接; 歡迎作客我們的php&Laravel學習群:109256050 在我們的Laravel底層核心技術(shù)實戰(zhàn)揭秘 視頻中,我們帶領(lǐng)大家使用了專業(yè)的郵件測試服務(wù)m...

    xumenger 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<