Красноречивая эффективность для создания ссылок в API отдыха - PullRequest
2 голосов
/ 21 мая 2019

Мы проводим учебное упражнение с Laravel 5.8 и Eloquent для разработки версии REST API.

Таблицы базы данных (компания, контакт и примечание) довольно просты с точки зрения их отношений:

company -> hasMany -> contacts
company -> hasOne -> note

Код модели выглядит так:

class Company extends Model
{
    // ....

    public function contacts()
    {
        return $this->hasMany(Contact::class);
    }

    public function note()
    {
        return $this->hasOne(Note::class);
    }
}

Чтобы получить доступ к каждому из этих ресурсов, API:

/api/companies
/api/notes
/api/contacts

Мы хотим вернуть ссылки на иностранные ресурсы, когда нажата /api/companies. e.g.:

{
    "data": [
        {
            "id": 1,
            "trading_name": "Example Company",
            "_links": {
                "contacts": [
                    "http://localhost:8100/api/contacts/1",
                    "http://localhost:8100/api/contacts/2",
                    "http://localhost:8100/api/contacts/3"
                ],
                "notes": "http://localhost:8100/api/notes/1"
            }
        }
    ]
}

Мы используем JsonResource Laravel для форматирования объекта ответа.

Вопрос вокруг _links. Для ссылок мы используем следующий код:

$contacts = $this->contacts->map(
    function($contact) {
        return route('contacts.show', [ 'contact' => $contact->id ]);
    }
);

$links['contacts'] = $contacts;
$note = $this->note;
if ($note != null) {
    $links['note'] = route('notes.show', [ 'note' => $note->id ]);
}
$links['self'] = route('companies.show', [ 'company' => $this->id ]);

Мы получаем только поле id для генерации массива _links.

Вышеописано, как эти ссылки генерируются в Laravel / Eloquent?

Ответы [ 2 ]

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

Нет «правильного способа» сделать это, но для меня то, что вы делаете, хорошо.

Тем не менее, есть спецификация под названием jsonapi , которая описывает, как делитьсяссылки.

Для этого существует пакет Laravel .

1 голос
/ 22 мая 2019

Вы описали наиболее разумный способ создания ссылок, хотя ваш код можно немного оптимизировать, удалив некоторые ненужные назначения:

$links['contacts'] = $this->contacts->map(function ($contact) {
    return route('contacts.show', [ 'contact' => $contact->id ]);
});

if ($this->note !== null) {
    $links['note'] = route('notes.show', [ 'note' => $this->note->id ]);
}

$links['self'] = route('companies.show', [ 'company' => $this->id ]);

Если, однако, id - это все, что вам нужно для вашегоcontacts и note, вы можете загрузить эту информацию только из вашей базы данных.Будьте внимательны и при загрузке внешних ключей, необходимых для сопоставления этих внешних объектов с их родителями:

$company = Company::query()
    ->with([
        'contacts' => function ($query) {
            $query->select(['id', 'company_id']);
        },
        'note' => function ($query) {
            $query->select(['id', 'company_id']);
        },
    ])
    ->find($companyId);

Абсолютно грязный способ, и я даже не уверен, что он гораздо более эффективен,создать шаблон маршрута и заменить часть id непосредственно в SQL.Но я не рекомендую его и пишу только для демонстрации:

$companyRoute = route('companies.show', ['company' => 999999]);
$contactRoute = route('contacts.show', ['contact' => 999999]);
$noteRoute    = route('notes.show', ['note' => 999999]);

$company = Company::query()
    ->with([
        'contacts' => function ($query) {
            $query->select(['id', 'company_id', \DB::raw("REPLACE(?, '999999', id) as link")])
                ->addBinding($contactRoute, 'select');
        },
        'note' => function ($query) {
            $query->select(['id', 'company_id', \DB::raw("REPLACE(?, '999999', id) as link")])
                ->addBinding($noteRoute, 'select');
        },
    ])
    ->select([
        '*',
        \DB::raw("REPLACE(?, '999999', id) as link"),
    ])
    ->addBinding($companyRoute, 'select')
    ->find($companyId);

Последний фрагмент не проверен и НЕ предназначен для использования.

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