Laravel использует динамические мутаторы в предложении where

Итак, у меня есть два столбца - SizeX и SizeY. Для внешних пользователей я использую мутатор Laravel.

public function getSizeAttribute(){
    /**
     * Set Size
     */
    $size = $this->SizeX. " x ". $this->SizeY;
    /**
     * Return
     */
    return $size;
}

Чтобы отформатировать такие размеры SizeX x SizeY. Столбец Sizes не существует, потому что он динамический. Можно ли использовать мутаторы или альтернативу в модели Elaquent, чтобы определить, что это динамический атрибут, и использовать какой-то метод для преобразования SizeX x SizeY в отдельные столбцы? Как только пользователь отправляет атрибут Size обратно в приложение laravel для фильтрации?

Редактировать:

Правильно, это метод, который я использую для получения отфильтрованных элементов.

public function scopeFilteredMaterials($query,$params = array()){ 
    /**
     * Get filters
     */
    $filters = array();
    /**
     * Extract Info
     */
    if(!empty($params) && is_array($params)){
        /**
         * Get Available Filters
         */
        $filters = $this->getAvailableFilters();

        foreach ($filters as $key => $filter){
            if(isset($params[$filter])){

                $filters[$filter] = $params[$filter];

                unset($filters[$key]);
            }else{

                unset($filters[$key]);
            }
        }
    }

    foreach ($filters as $key => $filter){

        $query->whereIn(key ,$filter);
    }

    $result = $query->get();
}

Это переменная фильтров, которая содержит доступные фильтры для просмотра пользователем.

protected $filters = array( "Name", "url", "Size", );

Я использую приведенное выше, чтобы показать пользователю конкретные значения. Как только пользователь выбирает эти значения, я использую тот же массив для проверки этих фильтров и запускаю запрос. Моя проблема заключается в том, что атрибут Size состоит из двух столбцов, и у меня нет проблем с использованием следующих переменных Mutator и $appends для автоматического предоставления значения пользователю.

/**
 * Get Size Attribute
 */
public function getSizeAttribute(){
    /**
     * Set Size
     */
    $size = $this->SizeX. " x ". $this->SizeY;
    /**
     * Return
     */
    return $size;
}

Но я не могу найти способ преобразовать переменную Size обратно в SizeX и SizeY


person Vilius    schedule 20.10.2017    source источник


Ответы (2)


Если вы всегда создаете составную переменную через метод доступа, вы можете использовать область, которая анализирует эту строку. Что-то вроде этого:

public function scopeSize($query, $size)
{
    $sizes = explode(' x ', $size);
    return $query->where('SizeX',  $sizes[0])->where('SizeY', $sizes[1]);
}

Затем вы можете использовать эту область в методе фильтра или где-либо еще.

person achillesp    schedule 20.10.2017

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

public function getSizesAttribute()
{
    return $this->SizeX . ' x ' . $this->SizeY;
}

Если вы хотите установить SizeX и SizeY автоматически, если свойство Sizes существует. В этом случае вы можете создать мутаторы как для SizeX, так и для SizeY. Например:

public function setSizeXAttribute($value)
{
    if (!empty($this->attributes['Sizes'])) {
        $this->attributes['SizeX'] = explode(' x ', $this->attributes['Sizes']))[0];
    }
}

public function setSizeYAttribute($value)
{
    if (!empty($this->attributes['Sizes'])) {
        $this->attributes['SizeY'] = explode(' x ', $this->attributes['Sizes']))[1];
    }
}

PS: Это решение для стандартных свойств змеиного случая, таких как size_x. Я действительно рекомендую вам использовать их в Laravel. Если вы все еще хотите использовать SizeX, вам также следует сделать это.

person Alexey Mezenin    schedule 20.10.2017
comment
Разве мне не нужно было бы явно указывать update SizeX для вызова метода setSizeXAttribute? - person Vilius; 20.10.2017
comment
Ну, это определенно работает, когда вы явно обновляете его чем-то вроде $model->attribute = $value;. Я стараюсь не использовать мутаторы, но насколько я помню, это работает и при создании модели с помощью create() или подобных методов. - person Alexey Mezenin; 20.10.2017
comment
Извините, я имел в виду, не должен ли я сделать что-то вроде: $query-›where(SizeX,200); для вызова метода setSizeXAttribute? Допустим, у меня есть $query-›where(Sizes, 200 x 300); можно ли вызвать методы setSizeXAttribute и setSizeYAttribute? Или, альтернативно, вызвать какой-то setSizesAttribute, который будет искать столбцы SizeX и SizeY на основе методов setSizeXAttribute и setSizeYAttribute? - person Vilius; 20.10.2017
comment
В этом случае я бы сделал что-то вроде `$query-›where('SizeX', 200)-›where('SizeY', 300)`. Это лучший способ справиться с этим. - person Alexey Mezenin; 20.10.2017
comment
ха-ха, да, я думал об этом, но у меня есть массив фильтров, и один из них использует два столбца, поэтому мне было интересно, могу ли я быть умным в этом и избегать использования этих... - person Vilius; 20.10.2017
comment
@Vilius Я не вижу здесь проблемы. Если вы хотите сделать его читабельным, используйте область действия (laravel.com/docs/5.5/ eloquent#query-scopes). Если вы хотите сделать много других where() и orWhere(), вы можете заключить их в замыкание where() (laravel.com/docs/5.5/queries#parameter-grouping). - person Alexey Mezenin; 20.10.2017
comment
Я не думаю, что прицелы решат эту проблему здесь, так как будут другие переменные поиска. Поэтому мне пришлось бы написать области для каждого фильтра поиска, чтобы цикл мог получить доступ, что противоречит цели этого упражнения... - person Vilius; 20.10.2017
comment
Области предназначены только для удобства чтения. Я не вижу здесь проблемы. Не могли бы вы показать код запроса и объяснить, что именно вас беспокоит? - person Alexey Mezenin; 20.10.2017
comment
@Вилиус Спасибо. Я не вижу здесь проблемы. Для размеров вы можете просто использовать закрытие where() или использовать где-то вроде этого where(['SizeX' => 200, 'SizeY' => 300]). - person Alexey Mezenin; 20.10.2017