Использование красноречивых отношений ownTo с слагом, а не идентификатора взаимосвязи - PullRequest
0 голосов
/ 22 мая 2019

Учитывая следующие две таблицы и отношения:

Контейнеры моделей: id, name, desc, creation_at, updated_at

public function items()
{
    return $this->hasMany('App\Models\Items', 'container_id', 'id');
}

Элементы модели: идентификатор, идентификатор контейнера, идентификатор типа, имя, созданный, обновленный,

public function containers()
{
    return $this->belongsTo('App\Models\Containers', 'id', 'container_id');
}

Как я могу получить все items, принадлежащие container, где все, что у меня есть, container:name без необходимости что-то вроде:

//Route::get('/api/v1/containers/{container}/items', 'ItemsController@index'); 
public function index($container)
{
    //Show all items in a specific container
    return Containers::where('name', $container)
        ->firstOrFail()
        ->items()
        ->get()
        ->toJson();
}

... и просматривать определенный элемент в определенном контейнере, не выполняя что-то еще более неприятное, например:

//Route::get('/api/v1/containers/{container}/items/{item}', 'ItemsController@show');
public function show($container, $item)
{
    //Show specific item in a specific container
    return Containers::where('name', $container)
        ->firstOrFail()
        ->items()
        ->where('id', $item)
        ->firstOrFail()
        ->toJson();
}

В этом случае у меня есть только имя контейнера в качестве URL-адреса, дружественного к URL-адресу, и помогает предотвратить манипулирование URL-адресами.

Есть ли способ - даже если это вторичное отношение ownTo - добиться этого, ссылаясь на имя контейнера, чтобы я мог просто сделать Items::find($containerName) без изменения поля primaryKey в моделях.

1 Ответ

2 голосов
/ 22 мая 2019

Вы можете достичь этого, выполнив обратное тому, что вы сделали (вызывая Item вместо Contractor(s). Это будет выглядеть примерно так:

$items = Item::whereHas(['container' => function($query) use ($container) {
    $query->where('name', $container);
}])->get()->toJson();

::whereHas()Метод будет возвращать только items, которые имеют container с указанным вами именем.

Если этого недостаточно, вы можете создать область запроса на вашем Itemмодель, перемещая вышеупомянутую функциональность в нее:

// App\Item.php - or where the model is
public function scopeInContainer($query, $container, $id = null)
{
    $query = $query->whereHas(['container' => function($q) use ($container) {
        $q->where('name', $name);
    }]);

    if ($id) {
        $query = $query->where('id', $id)->firstOrFail();
    }

    return $query;
}

Затем, чтобы использовать ее:

$items = Item::inContainer($container)->get()->toJson();

Затем при вызове Item через $id вам нужно будет только позвонить:

$item = Item::find($id);

Надеюсь, это то, что вы искали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...