Laravel Eloquent Relationship: неправильно их понимать - PullRequest
0 голосов
/ 02 июня 2019

Добрый день!Я думаю, что я делаю что-то не так или я неправильно понимаю Eloquent практики.

У меня есть три таблицы.

  1. orders {city, county}
  2. city {id, имя}
  3. графства {id, имя}

Я выполняю запросы к этим таблицам, используя Laravel Eloquent отношения один-ко-многим-обратным.orders.city содержит один идентификатор cities, а orders.county содержит один идентификатор counties.Ниже приведен код моих моделей.

Приложение \ Заказы

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Orders extends Model
{
    /*
    *   Table name
    */
    protected $table = 'orders';

    /*
    *   Get county
    */
    public function county()
    {
        return $this -> hasOne('App\Counties', 'id', 'county');
    }

    /*
    *   Get city
    */
    public function city()
    {
        return $this -> hasOne('App\Cities', 'id', 'city');
    }

}

Приложение \ Графства

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Counties extends Model
{
    protected $table = 'account_county';
    public $timestamps = false;

    /*
    *   Counties relationship
    */
    public function county()
    {
        return $this -> belongsTo('App\Orders', 'county', 'id');
    }
}

App \ Cities

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Cities extends Model
{
    protected $table = 'account_city';
    public $timestamps = false;

    /*
    *   City relationship
    */
    public function city()
    {
        return $this -> belongsTo('App\Orders', 'city', 'id');
    }
}

Когда я выполняю в Тинкере следующее: $order = App\Orders::with(['city', 'county']) -> first();

.... Я получаю следующий ответ:

App\Orders {#3042
     county: App\Counties {#3041
       id: 23,
       name: "Argeș",
     },
     city: App\Cities {#3046
       id: 6924,
       name: "Argeșelu",
     },
   }

Теперь, когда я запускаю следующий код: $order -> city

, я получаю следующий ответ:

"6924"

Когда я выполняю следующий код, однако: $order -> City

Я получаю всю коллекцию:

App\Cities {#3046
       id: 6924,
       name: "Argeșelu",
     },

Почему мне нужно прописать первую букву свойства, чтобы получить экземпляр коллекции?В документации говорится, что я должен использовать динамическое имя свойства напрямую: $order -> city однако в моем случае это возвращает необработанный идентификатор строки, а не экземпляр коллекции.Я что-то пропустил?Я обеспокоен производительностью и хорошими практическими соображениями.Прошу прощения, если это плохой вопрос или он уже был объяснен где-то еще.

1 Ответ

0 голосов
/ 02 июня 2019

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

При загрузке данных из таблицы базы данных каждое поле, которое вы извлекаете из базы данных, назначается атрибуту вашей модели. Они извлекаются с помощью магических методов PHP __get и __set, основанных на имени поля базы данных. Таким образом, $order->city фактически выбирает значение поля базы данных в строке этой таблицы.

Здесь следует отметить, что city в качестве имени атрибута чувствительно к регистру , что подводит нас к следующей проблеме.

Когда вы вызываете $order->City для модели (обратите внимание на случай), она сначала ищет атрибут поля базы данных с именем City. Из-за чувствительности к регистру он не может найти поле базы данных с таким именем.

Следующее, что делает Eloquent, проверяет, есть ли функция отношения, называемая city. Обратите внимание на случай. Функции класса PHP не чувствительны к регистру, поэтому вы можете определить функцию с именем city и вызвать ее как City(). Поэтому, когда вы запрашиваете $order->City, он вызывает функцию отношения этого имени и возвращает результаты БД.

По этой причине вы получаете правильные результаты, когда звоните City вместо city.

Чтобы решить эту проблему, я рекомендую переименовать поля ваших отношений city и county в более стандартные (для Eloquent) значения city_id и county_id. Это не только уменьшит ваши заблуждения, но и позволит вам воспользоваться некоторыми из встроенных функций Eloquent, которые сделают вашу жизнь проще.


Помимо этого, причина, по которой ваш $order->city возвращался в виде строки, была вызвана тем, что Eloquent по традиции обрабатывает поля базы данных. Как правило, он не читает схему для просмотра типов данных, но обычно обрабатывает все как строки, если вы явно не приводите его к типу PHP, или это не соответствует определенному соглашению об именах. Например, Eloquent будет предполагать, что любое поле, оканчивающееся на _id, является числом, и по умолчанию обрабатывает его как целое число. Поэтому переименование city в city_id автоматически исправит это.

Кроме того, проверьте ваши отношения в целом. Похоже, вам было бы лучше иметь отношения с BelongsTo как в городе, так и в округе.

...