Home  >  Q&A  >  body text

Function is not triggered when updated inside model

<p>我有一个像这样的模型:</p> <pre class="brush:php;toolbar:false;">class Equipment extends Model { use HasFactory,softDeletes; protected $table = 'equipments'; protected $fillable = ['station_id', 'parent_id', 'code', 'name', 'description', 'creator_id','deletor_id','updator_id']; protected $softDelete = true; protected $dates = ['deleted_at']; public static function boot() { parent::boot(); //it doesn't called at all! static::updated(function (Model $model) { Log::error('calling refreshTree'); $model->refreshTree(); }); static::created(function (Model $model) { $model->refreshTree(); }); static::deleted(function (Model $model) { $model->refreshTree(); }); } public function refreshTree(){ Log::error('refreshTree'); $equipment = DB::table('equipments')->get(); $treeData = $this->generateTree($equipment); $jsonData = json_encode($treeData); Redis::set(config('redis.EquipmentTree'),$jsonData); } private function generateTree($data, $parentId = 0) { $tree = []; foreach ($data as $item) { if ($item->parent_id == $parentId) { $children = $this->generateTree($data, $item->id); $node = [ 'id' => $item->id, 'text' => $item->name, 'editURL'=>route('dashboard.basic-info.equipments.edit',['id'=>$item->id]), 'children' => $children ]; if(count($children) <= 0) unset($node['children']); array_push($tree, $node); } } return $tree; } }</pre> <p>当我创建模型时,创建函数被触发,但当我更新模型时,更新函数没有被触发</p> <pre class="brush:php;toolbar:false;">//Equipment::where('id',$id)->update(['parent_id'=>$recordTarget['id']]); //它没有生效 //我也尝试了这个: $equipment = Equipment::find($id); $equipment->parent_id = $recordTarget['id']; $equipment->save();</pre> <p><br /></p>
P粉752826008P粉752826008461 days ago477

reply all(1)I'll reply

  • P粉165522886

    P粉1655228862023-08-09 09:30:12

    When using a query builder instance or batch update, the event listener will not fire even if you only operate on one row

    Equipment::where('id',$id) //right here you get a Builder instance
        ->update([]); //will not trigger the event listener as it is a mass update

    To trigger it, you need to use a model instance

    Equipment::where('id',$id)->first() //This returns a model instance
        ->update([]); //will trigger the event listener as it is a single instance update

    This is also equivalent to

    $equipment = Equipment::find($id);
    $equipment->parent_id = ..;
    $equipment->save();

    And you can see that calling update() on the model is different from calling update() on the query builder.

    When you consider that to trigger these events, the code needs an instance of the model to work with, like static::updated(function (Model $model) {. If your query is different, for example Equipment: :where('id','>',$id), in order to handle all events, it needs to query all affected rows, generate model instances for them, and then call the event using these models.

    This Will reduce performance

    But if there is no other way, you can do it explicitly

    $equipments = Equipment::where('id','>',$id)->get();
    foreach ($equipments as $equipment) {
        $equipment->update(['parent_id'=>$recordTarget['id']]);
    }

    reply
    0
  • Cancelreply