Alias полей в ActiveRecord

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
tlcl444w1plvc6c
Сообщения: 7
Зарегистрирован: 2019.12.18, 19:19

Alias полей в ActiveRecord

Сообщение tlcl444w1plvc6c »

Имеется таблица в базе данных в которой много полей и красивые названия.
Хотелось бы создавать ActiveRecord модели в каждой из которых задавать какие поля из таблицы использовать для неё и возможность задать алиансы этим полям.

Пример:
Имеется таблица myTable с полями: id, test1, test2, test3, test4, bla1, bla2, bla3, bla4

Код: Выделить всё

class My extends ActiveRecord {
	public function tableName() {
		return 'mytable';
	}
	
	public function useFields() {
		return ['id', 'test1', 'test2', 'test3', 'test4'];
	}
	
	public function fieldsAliase() {
		return ['test1' => 'name', 'test2' => 'title', 'test3' => 'order', 'test4' => 'counter'];
	}
}

$obj = new My();
$obj->name = 'String'; // запишет String в поле test1
$obj->save();

$query = My::find()->one();
echo $query->name; // вернёт значение из поля test1
echo $query->bla1; // ошибка, такого поля нет так как оно не задано в useFields.
Как реализовать?
Аватара пользователя
maleks
Сообщения: 1985
Зарегистрирован: 2012.12.26, 12:56

Re: Alias полей в ActiveRecord

Сообщение maleks »

tlcl444w1plvc6c писал(а): 2020.01.15, 14:24 Имеется таблица в базе данных в которой много полей и красивые названия.
может не красивые названия?
Yii2 universal module sceleton - for basic and advanced templates
yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

Re: Alias полей в ActiveRecord

Сообщение yiiliveext »

Примерно так

Код: Выделить всё

class My extends ActiveRecord {
	public function tableName() {
		return 'mytable';
	}
	
	public function useFields() {
		return ['id', 'test1', 'test2', 'test3', 'test4'];
	}
	
	public function fieldsAliase() {
		return [ 'name' => 'test1',  'title' => 'test2', 'order' => 'test3',  'counter' => 'test4'];
	}
	
	public function __get($name)
        {
            $aliases = $this->fieldsAliase();
            $fields = $ths->useFields();
            if (is_array($fields) && in_array($name, $filelds)) {
                if (is_array($aliases) && array_key_exists($name, $aliases)) {
                    return parent::__get($aliases[$name]);
                }
                return parent::__get($name);
            } elseif (array_key_exists($name, $this->_related)) {
                return parent::__get($name);
            }
            
            $value =  parent::__get($name);
            if ($value instanceof ActiveRecordInterface || is_array($value) || is_null($value)) {
                return $value;
            }
            
            throw new InvalidArgumentException(get_class($this) . ' has no attribute named "' . $name . '".');
        }
        
        public function __set($name, $value)
        {
            $aliases = $this->fieldsAliase();
            $fields = $ths->useFields();
            if (is_array($fields) && in_array($name, $filelds)) {
                if (is_array($aliases) && array_key_exists($name, $aliases)) {
                    parent::__set($aliases[$name], $value);
                    return;
                } else {
                    parent::__set($name,  $value);
                    return;
                }    
            } elseif (array_key_exists($name, $this->_related)) {
                parent::__set($name, $value);
                return;
            }           
            $value =  parent::__get($name);
            if ($value instanceof ActiveRecordInterface || is_array($value)) {
                parent::__set($name, $value);
                return;
            }
            
            throw new InvalidArgumentException(get_class($this) . ' has no attribute named "' . $name . '".');
        }
}
Но тут есть рад нюансов, будет недоступна магия обычных сеттеров и геттеров, будут некоторые нюансы со связями (все можно устранить, но решение этой задачи за рамками поста).
Если убрать ограничение на использование определенных полей, то этих недостатков не будет.

Код: Выделить всё

class My extends ActiveRecord {
	public function tableName() {
		return 'mytable';
	}
	
	public function fieldsAliase() {
		return [ 'name' => 'test1',  'title' => 'test2', 'order' => 'test3',  'counter' => 'test4'];
	}
	
	public function __get($name)
        {
            $aliases = $this->fieldsAliase();
            if (is_array($aliases) && array_key_exists($name, $aliases)) {
                return parent::__get($aliases[$name]);
            }
            
            return parent::__get($name);
        }
        
        public function __set($name, $value)
        {
            $aliases = $this->fieldsAliase();
            if (is_array($aliases) && array_key_exists($name, $aliases)) {
                parent::__set($aliases[$name], $value);
            } else {            
                parent::__set($name, $value);
            }
        }
}
Последний раз редактировалось yiiliveext 2020.01.17, 15:15, всего редактировалось 5 раз.
Аватара пользователя
Шлфк
Сообщения: 21
Зарегистрирован: 2018.04.25, 12:17
Откуда: СССР

Re: Alias полей в ActiveRecord

Сообщение Шлфк »

Если из таблицы будет только чтение, то можно сделать view `v_myTable`и переориентировать model на него. А во view уже сделать названия "красивыми"

Код: Выделить всё

Select test1 as [name] test2 as [title] ... From myTable
В таком случае в model добавляется функция
public static function tableName()
{
return 'v_myTable';
}
Если предполагается чтение/запись то такой вариант не пройдет (или пройдет, если сервер позволяет делать обновляемые view, то, на сколько я знаю, это редкость)
tlcl444w1plvc6c
Сообщения: 7
Зарегистрирован: 2019.12.18, 19:19

Re: Alias полей в ActiveRecord

Сообщение tlcl444w1plvc6c »

Большое спасибо за помощь!
Ответить