雄辩的morphOne关系并不限于一种关系

时间:2014-07-11 09:42:36

标签: laravel laravel-4 eloquent polymorphism

我遇到了Eloquent morphOne关系的问题,它正在创建新条目,而不是更新已存在的条目。

基本上我有一些模型(例如,我们说PersonBuilding)都需要一个位置,所以我创建了一个Location模型:

class Location extends Eloquent {

    public function locationable()
    {
        return $this->morphTo();
    }

}

然后在我的其他模特中我有这个:

class Person extends Eloquent {

    // ...

    /**
     * Get the person's location
     * 
     * @return Location
     */
    public function location()
    {
        return $this->morphOne('Location', 'locationable');
    }

    // ...
class Building extends Eloquent {

    // ...

    /**
     * Get the building's location
     * 
     * @return Location
     */
    public function location()
    {
        return $this->morphOne('Location', 'locationable');
    }

    // ...

当我运行以下测试代码时,它会创建位置条目,但如果我重复它,它会创建更多条目。

$person = Person::first();

$loc = new Location;

$loc->lat = "123";
$loc->lng = "321";

$person->location()->save($loc);

我在这里做错了吗?我希望morphOne将此约束条件限制为每个类型一个条目,因此下表中的最后一个条目不应该存在:

+---------------------+--------------------------+
|  locationable_id    |   locationable_type      |
+---------------------+--------------------------+
|  2                  |  Building                |
|  3                  |  Building                |
|  2                  |  Person                  |
|  2                  |  Building                |
+---------------------+--------------------------+

4 个答案:

答案 0 :(得分:3)

实际上,通过调用

$loc = new Location;

根据定义,您可以创建一个新位置!

调用

$person->location()->save($loc);

也无济于事。

如果您要更新某个位置,则需要找到该位置,更新其值,然后保存。独立于父模型:

$person = Person::first();

$loc = $person->location;

$loc->lat = "123";
$loc->lng = "321";

$loc->save();

完成。

答案 1 :(得分:3)

根据我目前的经验,这个解决方案应该是有效的

通过新的位置模型实例创建或替换旧的:

$person = Person::first();

$loc = new Location;

$loc->lat = "123";
$loc->lng = "321";

$loc->save();
$person->location()->associate($loc);
$person->save();

更新

$person = Person::first();

$person->location->lat = "123";
$person->location->lng = "321";

$person->location->save();
$person->save();

我花了很多天才找到这个解决方案。希望他们能够更好地正式记录它。

答案 2 :(得分:2)

也许我参加晚会很晚,但这对我有用!

# Do we have location already?
if($person->location) {
    return $person->location()->update($location);
}
return $person->location()->create($location);

答案 3 :(得分:0)

在hasOne或morphOne相关模型上创建或更新内容的最佳方法是使用“ updateOrCreate”功能。

在我的情况下,客户可以有一个地址,因此我可以执行以下操作并为我工作

$client->address()->updateOrCreate([], $addressData);

如果具有hasOne关系,例如用户只能拥有一个配置文件,则同样可以应用。

$user->profile()->updateOrCreate([], $data);

User.php

class User {
    /**
     * Get the user profile information associated with the user.
     */
    public function profile()
    {
        return $this->hasOne('App\UserProfile');
    }
}

Client.php

class Client {
    /**
     * Get all of the client's addresses.
     */
    public function address()
    {
        return $this->morphOne('App\Address', 'addressadder');
    }
}