Использование красноречивых отношений - PullRequest
0 голосов
/ 09 декабря 2018

Я пытаюсь понять, как эффективно использовать отношения Eloquent, чтобы иметь некоторые высокоуровневые функции в модели.У меня есть приложение подписки с 2 таблицами, «пользователи» и «подписки».Это устаревшая система, поэтому я не могу просто что-то изменить, как захочу.

 Table users (model App\User)
 id
 email
 active (0/1)
 join_date
 address etc
 phone

 Table subscriptions (model App\Subscription)
 id
 user_id
 box_id (what the person is subscribed to get)
 amount

Пользователи отмечены как активные или неактивные.

Я хотел бы использовать статический метод дляМодель подписки, которая выдаст мне все активные подписки.Эти данные затем передаются в другие части приложения.

Это получается путем присоединения подписок к пользователям и фильтрации по столбцу active.Запрос выглядит так:

SELECT users.*, subscriptions.*
FROM subscriptions
JOIN users ON users.id = subscriptions.user_id
WHERE users.active = 1

Модель подписки

class Subscription extends Model
{
    public static function allActive()
    {
        // This works except it doesn't use the eloquent relationship
        return static::where('users.active', 1)
            ->join('users', 'users.id', '=', 'subscriptions.user_id')
            ->select('users.*','subscriptions.*')
            ->get();
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

Модель пользователя

class User extends Authenticatable
{
    use Notifiable;
    public function subscriptions()
    {
        return $this->hasMany(Subscription::class);
    }
}

Я бы использовал ее так:

$subscriptions = \App\Subscription::allActive()->toArray();
print_r($subscriptions);

У меня есть 2 вопроса.

  1. Как переписать функцию allActive, чтобы использовать отношения, которые я уже определил?Любое решение должно генерировать SQL с JOIN.

  2. Как в возвращаемых данных отделить столбцы от двух отдельных таблиц, чтобы было ясно, из какой таблицы получены данные?

1 Ответ

0 голосов
/ 09 декабря 2018

Учитывая связи, которые вы установили, чтобы получить только активные подписки из класса модели, вам нужно будет сделать это следующим образом:

class Subscription extends Model
{
    public static function allActive()
    {
        $activeSubcriptions = Subscription::whereHas('user', function($query){
            $query->where('active', 1) //or you could use true in place of 1
        })->get();
        return $activeSubcriptions;
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

То, что работа с closures в Laravel, довольно эффективноспособ написания расширенных красноречивых запросов.

В функции обратного вызова вы будете делать практически все с объектом $ query, который в основном работает с моделью User, поскольку вы упомянули его как первый параметр * 1008.*

Обратите внимание, что эта переменная должна иметь ИМЕННО то же имя, которое использовалось при объявлении отношения

Выше я полагаю, что ответ на ваш первый вопрос, однако настоятельно рекомендуется, чтобы вывыполните большую часть этой логики в файле контроллера

Чтобы ответить на вопрос 2, когда вы выполните этот get(), он вернет массив Subscription объектов, поэтому для доступа к информации, основанной на столбцах, вы должны будете выглядеть так:

$subscriptions = \App\Subscription::allActive();

foreach($subscriptions as $subscription){
    $amount = $subscription->amount; //this you access directly since we working with the subscription object
    $box_id = $subscription->box_id;

    //when accessing user columns
    $email = $subscription->user->email; //you will have to access it via the relationship you created
    $address = $subscription->user->address;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...