首页 > 解决方案 > 尝试使用 attach() 填充中间表,但得到“调用未定义的方法 Illuminate\Database\Eloquent\Relations\HasMany::attach()”

问题描述

我有名为users,places和的表user_placeusers有一个名为的列id,其中包含用户的 id,places 也有一个名为的列place_id。该user_place表有 2 列称为user_idplace_id我正在尝试使用相应的 id 自动填充它们。我读到我必须在设置我相信我已经完成的关系后使用 attach() 函数,但我可能是错的。他们来了:

class PlaceController extends Controller
{
    public function likePlace(Request $request){
        $placeId = $request['placeId'];
        $userId = $request['userId'];
        $user = User::where('id', $userId)->first();

        $place = new Place();
        $place->place_id = $placeId;
        $place->save();

        $user->places()->attach($place);
    }
}

用户型号:

class User extends \Eloquent implements Authenticatable
{
    use AuthenticableTrait;

    public function places(){
        return $this->hasMany('App\Place');
    }
}

放置模式:

class Place extends Model
{
    public function user(){
        return $this->belongsToMany('App\User');
    }
}

标签: phplaraveleloquent

解决方案


多对多关系中,您应该定义两种关系,如下所示:

用户.php

class User extends \Eloquent implements Authenticatable
{
    use AuthenticableTrait;

    public function places()
    {
        return $this->belongsToMany('App\Place', 'user_place', 'user_id', 'place_id');
    }   //                                       ^^^^^^^^^^^^
}

注意:鉴于您的中间表名称不遵循我们指定的命名约定,因此 Laravel 知道在哪里查找表。

Place.php

请注意,您提到 Place 模型的主键是place_id,这也脱离了Laravel 约定,您应该指定它:

protected $primaryKey = 'place_id'; // <----

class Place extends Model
{
    public function user()
    {
        return $this->belongsToMany('App\User', 'user_place', 'place_id', 'user_id');
    }
}

所以现在在你的控制器中:

class PlaceController extends Controller
{
    public function likePlace(Request $request)
    {
        $placeId = $request['placeId'];
        $userId = $request['userId'];

        $user = User::where('id', $userId)->first();

        $place = new Place();
        $place->place_id = $placeId;
        $place->save();

        $user->places()->attach($place);
    }
}

边注

正如我旁注的那样,您可以节省几行将某些句子替换为等效的句子:

    $userId = $request['userId'];
    $user = User::where('id', $userId)->first();

使用find()方法,这等于:

    $user = User::find($request['userId']);

然后,您可以使用 Eloquent 模型的静态方法创建相关对象,create这样:

    $placeId = $request['placeId'];
    $place = new Place();
    $place->place_id = $placeId;
    $place->save();

等于:

    $place = Place::create(['place_id' => $request['placeId']]);

然后您的控制器将简化为:

class PlaceController extends Controller
{
    public function likePlace(Request $request)
    {

        $user = User::find($request['userId']);
        $place = Place::create(['place_id' => $request['placeId']]);

        $user->places()->attach($place);
    }
}

推荐阅读