2017-08-15 28 views
0

我有在控制器这样的代码:Laravel雄辩的活动 - 实现节省模式,如果更新

for($i=0; $i<$number_of_tourists; $i++) { 

$tourist = Tourist::updateOrCreate(['doc_number' => $request['doc_number'][$i]], 
$tourist_to_update); 

} 

如此,updateOrCreate方法可以1)更新记录,2)创建一个新的3)留下记录不变如果$ tourist_to_update等于数据库中已有的数据。

我想$ tourist_to_update保存到$ []数组只有在“旅游”表中的记录被更新(一个新的记录创建或没有什么变化不是当)。

据我所知,有口才很好事件https://laravel.com/docs/5.4/eloquent#events具有更新更新事件,这似乎符合我的需要。

问题是,我看着&读几个教程,仍然不知道如何使用它们。

我知道如何对注册在旅游模型雄辩事件:

protected static function boot() 
{ 
    parent::boot(); 

    static::updating(function ($model) { 

    }); 
} 

任何人都可以解释我怎么能achive我的目标与雄辩的事件?

预先感谢您。

+0

所以,你要创建一个新的阵列'$ array'其中只包含了哪些更新的记录? – TheFallen

+0

@ TheFallen是的:)完全! –

回答

1

这是一个比较复杂的方法,但如果你只想得到更新的记录,其数据发生了变化,这是行得通的。在你的控制器方法中添加:

app()->singleton('touristsCollector', function ($app) { 
    $collector = new \stdClass; 
    $collector->updated = []; 

    return $collector; 
}); 

for($i = 0; $i < $number_of_tourists; $i++) { 
    $tourist = Tourist::updateOrCreate(
     ['doc_number' => $request['doc_number'][$i]], 
     $tourist_to_update 
    ); 
} 

$collector = resolve('touristsCollector'); 
var_dump($collector->updated); // Only updated tourists which have data changed 

这将基本上添加到应用程序容器标准的PHP类,它会收集所有更新的游客从模型事件。在模型中添加此:

protected static function boot() 
{ 
    parent::boot(); 

    static::updated(function ($model) { 
     $collector = resolve('touristsCollector'); 
     $collector->updated[] = $model; 
    }); 
} 

这基本上将获得从应用程序容器的PHP类添加只有当它的一些特性已经被更新的旅游模式。

+0

哇,这就是我正在寻找 - 使用雄辩模型来完成这件事!:)你真的是主人!:)我有一些问题,但我看到没有区别,如果我改变'静态:更新'为'静态:更新'。那么有什么区别?:) –

+0

我在哪里可以阅读更多关于'app() - > singleton'和'\ stdClass'?:) –

+1

@SergejFomin,'updating'事件即使属性相同也会触发,'updated'只有在数据发生了一些变化时才会触发,所以你需要'updated'事件。 – TheFallen

0

如果模型已经建立物业wasRecentlyCreated将被设置为true,所以这是你如何检查,如果该模型是新的或更新:

$updated = []; 

for($i = 0; $i < $number_of_tourists; $i++) { 
    $currentTourist = ['doc_number' => $request['doc_number'][$i]]; 
    $tourist = Tourist::updateOrCreate($currentTourist, $tourist_to_update); 

    if ($tourist->wasRecentlyCreated) { 
     continue; // Go to next loop if this tourist was created now 
    } 

    $updated[] = $tourist; 
} 
+0

谢谢你,TheFallen。但我认为有一个问题。 'updateOrCreate',除了更新和创建之外,还有第三个行为: 3)如果$ tourist_to_update等于数据库中已有的内容,请保持记录不变。我认为你的代码将添加一个已经在db中并且不需要更新或创建的游客到$ updated []数组。我刚刚实现了你的代码。是的,它确实添加不变的游客阵列$更新...:( –

+1

@SergejFomin,你是正确的,只有更新的,你可以比较'updated_at'时间戳到当前时间或检查我的其他答案。 – TheFallen

0

如果您总是希望在旅游表中的某一行更新时执行特定的代码,我会建议您创建一个observer来收听updatedcreate来电。

<?php 

namespace App\Observers; 

use App\Tourist; 

class TouristObserver 
{ 
    /** 
    * Listen to the User created event. 
    * 
    * @param \App\User $user 
    * @return void 
    */ 
    public function created(Tourist $user) 
    { 
     // this will always trigger when you created a new entry 
    } 

    /** 
    * Listen to the User deleting event. 
    * 
    * @param \App\Tourist $user 
    * @return void 
    */ 
    public function updated(Tourist $user) 
    { 
     // this will always trigger when actually a row was updated 
    } 
} 

所有你需要做的就是在AppServiceProvider这样注册的观察者:

public function boot() 
{ 
    Tourist::observe(\App\Observer\TouristObserver::class); 
}