有条件地将属性附加到 Laravel 中的模型

Moh*_*ini 5 php orm append laravel eloquent

每当调用模型范围时是否可以将属性附加到我的模型?

例如,在我的控制器中,我想调用一个作用域来附加这些动态属性,例如:

$Media_query = OutDoorMedia::query();
$Media_query->orderby('created_at', 'desc');
$Media_query->PreviouslyOrdered();
$Media = $Media_query->get();
Run Code Online (Sandbox Code Playgroud)

在我的模型中我想做类似的事情:

class OutDoorMedia extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'id',
        'user_id',
        'address',
        'location',
        'media_type',
    ];
}

class scopePreviouslyOrdered extends OutDoorMedia
{
public $appends = ['previously_ordered'];

public function getPreviouslyOrderedAttribute()
{
    if ($this->hasMany('App\Models\OutDoorMediaOrders', 'odm_id', 'id')->Where(function ($query) {
        $query->where('status', MEDIA_ORDER_CHECKOUT_STATUS)
            ->orWhere('status', STATUS_TO_PAY);
    })->exists()) {
        return true;
    } else {
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

}

但它不起作用,我知道这是错误的,如何实现这一目标?

Moh*_*ini 6

我在@apokryfos 的帮助下解决了这个问题,但做了一些调整。希望这能减少浪费别人的时间。

我没有在模型上附加属性,而是通过雄辩的魔术方法将所述属性附加到我的模型中:

$Media_query = OutDoorMedia::query();
$Media_query->orderby('created_at', 'desc');
$Media = $Media_query->get()->each(function ($items) {
          $items->append('previously_ordered');//add this attribute to all records which has the condition
         });    
Run Code Online (Sandbox Code Playgroud)

在模型中,正如 apokryfos 所说,我放置了这两种方法:

  public function PreviousOrders() {
      return $this->hasMany('App\Models\OutDoorMediaOrders', 'odm_id', 'id');
  }

  public function getPreviouslyOrderedAttribute() {
      return $this->PreviousOrders()->exists();
  }
Run Code Online (Sandbox Code Playgroud)

但我不需要这个方法,我必须将其从模型中删除,因为如果它存在于模型中,它会自动附加到模型中:

public $appends = [ 'previously_ordered' ];
Run Code Online (Sandbox Code Playgroud)


apo*_*fos 4

我认为对于范围应该如何工作存在误解。范围基本上就像模型的快捷查询。您正在使用它来测试关系的存在,但有更好的方法可以使用whereHas

以下是如何使用关系来实现这一目标:

class OutDoorMedia extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'id',
        'user_id',
        'address',
        'location',
        'media_type',
    ];

    public function previousOrders() {
         return $this->hasMany('App\Models\OutDoorMediaOrders', 'odm_id', 'id');
    }
    public function getPreviouslyOrderedAttribute() {
        return $this->previousOrders()->exists(); 
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你只需执行以下操作:

$Media_query = OutDoorMedia::whereHas('previousOrders')
                ->orderby('created_at', 'desc');
Run Code Online (Sandbox Code Playgroud)

如果您自动在模型上附加动态属性,则只需将以下内容添加到模型中即可:

 public $appends = [ 'previously_ordered' ];
Run Code Online (Sandbox Code Playgroud)

我想如果你想两全其美,你可以这样做:

class OutdoorMediaWithPreviouslyOrdered extends OutDoorMedia {
     public $appends = [ 'previously_ordered' ];         
 }
Run Code Online (Sandbox Code Playgroud)

然后,当您需要附加模型时,您可以使用:

 $Media_query = OutdoorMediaWithPreviouslyOrdered ::orderby('created_at', 'desc');
Run Code Online (Sandbox Code Playgroud)