Область действия по умолчанию для красноречивых моделей?

Область действия по умолчанию для красноречивых моделей?

16.02.2014 06:57:28 Просмотров 18 Источник

Вот пример базы данных-таблица (users):

id - int(11) auto_increment
name - varchar(100)
banned - int(1)

banned-это логическое значение, которое 0( false). Если пользователь был запрещен, значение равно 1.

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

Я также мог бы создать newQuery

Однако таким образом я не смогу отключить это поведение. Я мог бы захотеть увидеть запрещенных пользователей в моей личной админ-панели, но не смог бы, так как это ограничение будет применяться к любому запросу, сделанному через Eloquent.

Есть идеи, как решить эту проблему?

У вопроса есть решение - Посмотреть?

https://stackoverflow.com/questions/21812826/default-scope-for-eloquent-models#comment35637416_21812826
Немного покопался. Вы можете применять глобальные области, как это . Пример, который я привожу, относится к областям многократного использования; вам это может не понадобиться, так как только пользователи могут быть запрещены.

Ответы - Область действия по умолчанию для красноречивых моделей? / Default scope for Eloquent-models?

JohnTaa

16.02.2014 07:25:31

Почему бы вам не использовать переменную config для этого:

public function newQuery($excludeDeleted = true)
{
    $builder = parent::newQuery($exludeDeleted);
    if (Config::get('hide_banned_users', true) !== false) {
        $builder->where('banned', '=', '0');
    }
    return $builder;
}

и измените значение конфигурации всякий раз, когда вам нужно увидеть запрещенных пользователей.

sigmus

16.02.2014 07:59:07

Это звучит очень похоже на мягкое удаление, но с banned_atвместо deleted_at. Если поведение по умолчанию-не показывать запрещенных пользователей, я думаю, что более интуитивно понятно явно попросить запрещенных (напримерwithTrashed), когда они вам нужны (панель администратора).

https://stackoverflow.com/questions/21812826/default-scope-for-eloquent-models/21813604#comment33011405_21813604
Мне нужна такая же функциональность, как и при мягком удалении, да.
https://stackoverflow.com/questions/21812826/default-scope-for-eloquent-models/21813604#comment35631215_21813604
@MarttiLaine я тоже расследую это дело. Мы еще не нашли решение, но это может дать нам ключ к разгадке.
trm42

04.02.2015 07:05:30

Я настоятельно рекомендую использовать шаблон проектирования репозитория для запросов БД вместо выполнения прямых красноречивых запросов в контроллерах и везде.

// Quick example, not tested
class UserRepositoy { // You should create an interface and maybe super class for handling common cases like caching, find(), all() etc

    protected $include_banned = false;
    protected $model;

    public function __construct() // you can use DI here
    {
            $this->model = new User;
    }

    public function setIncludeBanned($bool)
    {
        $this->include_banned = $bool;
    }

    protected function includeBanned($query)
    {
        if ($this->include_banned) {
            return $query->where('banned', 1);
        }
    }

    public function find($id)
    {
        $res = $this->model->where('id', $id);

        $res = $this->includeBanned($res);

        return $res->get();
    }

}

Теперь вы можете создать класс репозитория там, где вам нужны запросы, и у вас есть унифицированный API для вызовов. В Laravel действительно легко распространять небольшие красноречивые запросы здесь и там, но в долгосрочной перспективе это будет действительно раздражать, чтобы обновить/изменить и справиться. Попробуйте поискать Laravel Design Pattern, и там будет много информации и примеров. Сделал мой день уже пару раз.

Этот паттерн также позволяет легче отделаться от всего красноречивого с чем-то другим, если это необходимо.

Ben Claar

19.04.2019 07:37:39

Laravel предоставляет глобальные области именно для этой цели. Из документов:

class AgeScope implements Scope
{
    public function apply(Builder $builder, Model $model)
    {
        return $builder->where('age', '>', 200);
    }
}

class User extends Model
{
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope(new AgeScope);
    }
}
David Maksimov

21.01.2020 12:14:52

Отвечая здесь для других, которые могут искать аналогичный ответ.

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

Смотрите документы Laravel: https://laravel.com/docs/5.8/eloquent#global-scopes


Таким образом, в вашем случае вы создадите новую глобальную область для запроса пользователей, которые не запрещены.

<?php

namespace App\Scopes;

use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class ExcludeBannedScope implements Scope
{
    /**
     * Apply the scope to a given Eloquent query builder.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function apply(Builder $builder, Model $model)
    {
        $builder->where('banned', '=', 0);
    }
}

Примените глобальную область к модели пользователя.

<?php

namespace App;

use App\Scopes\ExcludeBannedScope;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The "booting" method of the model.
     *
     * @return void
     */
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope(new ExcludeBannedScope);
    }
}

Это теперь прибавился where banned = 0 для всех запросов.

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

User::withoutGlobalScope(\App\Scopes\ExcludeBannedScope::class)->get();
Закрыть X