我正在使用Laravel 4,并且有2个型号:
class Asset extends \Eloquent {
public function products() {
return $this->belongsToMany('Product');
}
}
class Product extends \Eloquent {
public function assets() {
return $this->belongsToMany('Asset');
}
}
Product
上有标准时间戳(created_at
,updated_at
),我想更新updated_at
的{{1}}字段。附加/分离Product
。
我在Asset
型号上尝试了这个:
Asset
......但这根本没有做任何事情(显然)。 修改:显然这是为了更新数据透视表上的时间戳,而不是在关系表上更新它们(即更新class Asset extends \Eloquent {
public function products() {
return $this->belongsToMany('Product')->withTimestamps();
}
}
,而不是assets_products.updated_at
)。
然后我在products.updated_at
模型上尝试了这个:
Asset
...哪个有效,但随后打破了调用class Asset extends \Eloquent {
protected $touches = [ 'products' ];
public function products() {
return $this->belongsToMany('Product');
}
}
的种子,因为显然Laravel尝试在关系上调用Asset::create([ ... ]);
而不检查它是否为->touchOwners()
:
PHP致命错误:在第1583行的/projectdir/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php中调用未定义的方法Illuminate \ Database \ Eloquent \ Collection :: touchOwners()
我用来添加/删除null
的代码是:
Asset
我哪里错了?
答案 0 :(得分:3)
您可以使用touch
方法手动执行此操作:
$product = Product::find($validId);
$product->assets()->attach($anotherValidId);
$product->touch();
但是,如果您不希望每次都以这种方式在Product
模型中简化此创建方法时手动执行此操作:
public function attachAsset($id)
{
$this->assets()->attach($id);
$this->touch();
}
现在你可以这样使用它:
Product::find($validId)->attachAsset($anotherValidId);
你当然可以为分离行动做同样的事。
我注意到你有一个关系belongsToMany
而另一个hasMany
- 两者之间应该是belongsToMany
,因为它有多对多关系
修改强>
如果您想在许多模型中使用它,您可以使用以下方法创建特征或创建另一个扩展Eloquent的基类:
public function attach($id, $relationship = null)
{
$relationship = $relationship ?: $this->relationship;
$this->{$relationship}()->attach($id);
$this->touch();
}
现在,如果您需要此功能,您只需要从另一个基类扩展(或使用特征),现在您可以向Product
类添加一个额外属性:
private $relationship = 'assets';
现在你可以使用:
Product::find($validId)->attach($anotherValidId);
或
Product::find($validId)->attach($anotherValidId, 'assets');
如果您需要附加更新updated_at
字段的数据。当然,你需要重复分离。
答案 1 :(得分:1)
在code source中,您需要在创建相关模型的新实例时将$touch
设置为false:
Asset::create(array(),array(),false);
或使用:
$asset = new Asset;
// ...
$asset->setTouchedRelations([]);
$asset->save();
答案 2 :(得分:1)
创建一个扩展Eloquent的BaseModel
,对create
方法进行简单调整:
<强> BaseModel.php 强>:
class BaseModel extends Eloquent {
/**
* Save a new model and return the instance, passing along the
* $options array to specify the behavior of 'timestamps' and 'touch'
*
* @param array $attributes
* @param array $options
* @return static
*/
public static function create(array $attributes, array $options = array())
{
$model = new static($attributes);
$model->save($options);
return $model;
}
}
让您的Asset
和Product
模型(以及其他模型,如果需要)扩展BaseModel
而不是Eloquent
,并设置$touches
属性:
Asset.php (以及其他型号):
class Asset extends BaseModel {
protected $touches = [ 'products' ];
...
在您的播种机中,将create
的第二个参数设置为指定'touch'
为false
的数组:
Asset::create([...],['touch' => false])
Eloquent的save()
method接受一个(可选的)选项数组,您可以在其中指定两个标记:'timestamps'
和'touch'
。如果touch
设置为false
,则无论您在模型上指定了哪些$touches
属性,Eloquent都不会触及相关模型。这是Eloquent的save()
方法的所有内置行为。
问题在于,Eloquent的create()
method不接受传递给save()
的任何选项。通过扩展Eloquent(使用BaseModel
)接受$options
数组作为第二个属性,并将其传递给save()
,您现在可以在调用{{1}时使用这两个选项在所有扩展create()
的模型上。
请注意,BaseModel
数组是可选的,因此这样做不会破坏您在代码中对$options
的任何其他调用。