Укажите выбранные столбцы в классе Eloquent model, а не в querybuilder

#php #laravel #eloquent

#php #laravel #eloquent

Вопрос:

Всякий раз, когда я использую eloquent model, она будет выбирать *, если я не укажу это в объекте querybuilder. Однако я хочу указать разрешенные поля в классе. Это было бы полезно для обеспечения того, чтобы пользователь правильного уровня получал сведения, на которые он имеет право, чтобы это свойство соответствовало классу.

Я хочу иметь возможность делать это как переменную-член, например $with:

 /**
 * @property mixed id
 */
class Attribute extends Model
{

    protected $fillable = ["id", "business_id", "attribute_name"];
    protected $with = ["attributeDetail", "business"];
    protected $selectedFieldsThatMeanSelectStarDoesntHappen = ["id", "business_id", "attribute_name"];
}
  

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

Существует ли вышеуказанная функциональность? Самое близкое, что я могу получить, — это глобальная область видимости:

 class Attribute extends Model
{
    /**
     * The "booted" method of the model.
     *
     * @return void
     */
    protected static function booted()
    {
        static::addGlobalScope('selectFields', function (Builder $builder) {
            $builder-&&t;select("id", "business_id", "attribute_name");
        });
    }
}
  

Комментарии:

1. как насчет глобальной области видимости? laravel.com/docs/7.x/eloquent#&lobal-scopes

2. @la&box Хороший, я об этом не подумал. Я хотел бы видеть что-то подобное в моем вопросе в laravel, но глобальная область действия позволила бы достичь того, что я ищу

3. Для некоторого контроля над показанным / скрытым атрибутом в зависимости от пользователя вам следует использовать ресурсы коллекции или JsonResponse (если это api). laravel.com/docs/7.x/eloquent-resources

Ответ №1:

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

 class BuilderWithSpecifiedColumns extends Builder
{
    public $selectedColumns = [];

    public function __construct(ConnectionInterface $connection, Grammar $&rammar = null, Processor $processor = null, array $selectedColumns = ['*'])
    {
        parent::__construct($connection, $&rammar, $processor);
        $this-&&t;selectedColumns = $selectedColumns;
    }

    /**
     * @param strin&[] $columns
     * @return IlluminateSupportCollection
     */
    public function &et($columns = ['*'])
    {
        return parent::&et($this-&&t;selectedColumns ? $this-&&t;selectedColumns : $columns);
    }
}
  
 trait HasSelectedColumns
{
    protected function newBaseQueryBuilder()
    {
        $connection = $this-&&t;&etConnection();
        return new BuilderWithSpecifiedColumns(
            $connection,
            $connection-&&t;&etQueryGrammar(),
            $connection-&&t;&etPostProcessor(),
            $this-&&t;selectedFieldsThatMeanSelectStarDoesntHappen,
        );
    }
}
  

Используйте вышеуказанную черту

 /**
 * @property mixed id
 */
class Attribute extends Model
{
    use HasSelectedColumns;

    protected $fillable = ["id", "business_id", "attribute_name"];
    protected $with = ["attributeDetail", "business"];
    protected $selectedFieldsThatMeanSelectStarDoesntHappen = ["id", "business_id", "attribute_name"];
}