За последние 24 часа нас посетили 56983 программиста и 1682 робота. Сейчас ищут 1256 программистов ...

Небольшие вопросы по Yii2

Тема в разделе "Yii", создана пользователем Walk, 2 авг 2017.

  1. Walk

    Walk Активный пользователь

    С нами с:
    7 сен 2008
    Сообщения:
    452
    Симпатии:
    86
    А какой из этих правил валидации отвечает за вес файла?

    - `boolean`: [[BooleanValidator]]
    - `captcha`: [[\yii\captcha\CaptchaValidator]]
    - `compare`: [[CompareValidator]]
    - `date`: [[DateValidator]]
    - `datetime`: [[DateValidator]]
    - `time`: [[DateValidator]]
    - `default`: [[DefaultValueValidator]]
    - `double`: [[NumberValidator]]
    - `each`: [[EachValidator]]
    - `email`: [[EmailValidator]]
    - `exist`: [[ExistValidator]]
    - `file`: [[FileValidator]]
    - `filter`: [[FilterValidator]]
    - `image`: [[ImageValidator]]
    - `in`: [[RangeValidator]]
    - `integer`: [[NumberValidator]]
    - `match`: [[RegularExpressionValidator]]
    - `required`: [[RequiredValidator]]
    - `safe`: [[SafeValidator]]
    - `string`: [[StringValidator]]
    - `trim`: [[FilterValidator]]
    - `unique`: [[UniqueValidator]]
    - `url`: [[UrlValidator]]
    - `ip`: [[IpValidator]]
     
  2. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    denis01 нравится это.
  3. Walk

    Walk Активный пользователь

    С нами с:
    7 сен 2008
    Сообщения:
    452
    Симпатии:
    86
    Разобрался:

    PHP:
    1. public function rules()
    2.     {
    3.         return [
    4.             [['imageFile'], 'file', 'extensions' => 'jpg, png, gif', 'maxSize' => 1000000],
    5.         ];
    6.     }
     
    #28 Walk, 6 сен 2017
    Последнее редактирование: 6 сен 2017
    denis01 нравится это.
  4. Walk

    Walk Активный пользователь

    С нами с:
    7 сен 2008
    Сообщения:
    452
    Симпатии:
    86
    Как в GridView::widget() можно указать произвольную колонку с произвольным значением? В документации, как обычно, все очень поверхностно.

    Ответ, желательно, сразу в виде примера, как-то так:

    Код (Text):
    1. GridView::widget([
    2.         'dataProvider' => $dataProvider,
    3.         'filterModel' => $searchModel,
    4.         'columns' => [
    5.             ['class' => 'yii\grid\SerialColumn'],
    6.             'code',
    7.             'name',
    8.             'population',
    9.             'id',
    10.             [
    11.                 'attribute' => 'imageFile',
    12.                 'format' => 'html',
    13.                 'value' => function($data) {
    14.                     return '<img src="/uploads/'.$data->imageFile.'" width="200" alt="" />';
    15.                 }
    16.             ],
    17.             ['class' => 'yii\grid\ActionColumn'],
    18.         ],
    19.     ]);
     
  5. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Обычный DataColumn, "format" ставишь "raw", "attribute" не задаёшь, "value" - генеришь, что надою
     
  6. Walk

    Walk Активный пользователь

    С нами с:
    7 сен 2008
    Сообщения:
    452
    Симпатии:
    86
    Пишу:
    PHP:
    1.         [
    2.             'format' => 'raw',
    3.             'value' => '123'
    4.         ],
    Выдает ошибку: Unknown Property
     
  7. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Потому что, согласно документации, если "value" - строка, то она трактуется как имя атрибута тоже. Поставь анонимную функцию, будет счастье.
    Код (Text):
    1.  
    2. [
    3.     "value" => function () {
    4.         return "123";
    5.     }
    6. ],
    --- Добавлено ---
    Для чего нужны строки, тоже написано:
    А если что-то произвольное, то нужен callable
     
    denis01 и Walk нравится это.
  8. Walk

    Walk Активный пользователь

    С нами с:
    7 сен 2008
    Сообщения:
    452
    Симпатии:
    86
    Мне этот термин ничего не говорит.

    Гугл, кстати, по запросу "php имя атрибута", "php атрибут" тоже ничего внятного не говорит.

    Спасибо, работает.

    Риторический вопрос - всегда удивляло, зачем эти объяснения, ссылки на документации, когда простой пример намного понятней?
     
  9. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Интересно ты программируешь на yii2. Поля моделей в yii2 называют атрибутами. Они могут быть как объявленными в классе, так и динамически считываемыми из таблицы (ActiveRecord).
    Ссылки нужны, для того, чтобы дать нормальное понимание.
     
    denis01 нравится это.
  10. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    Потому что пример не объясняет принцип, проще запомнить 1 принцип, чем 1000 фактов, тебе просто нужно было почитать код DataColumn класса и из него всё выяснить, если текст не понятен, но и пример легко гуглится
     
  11. Walk

    Walk Активный пользователь

    С нами с:
    7 сен 2008
    Сообщения:
    452
    Симпатии:
    86
    Не знал. Меня учили, что у объектов есть только свойства и методы.

    1. Ссылки на документацию не являются сокровенной тайной.
    2. Если человек задает вопросы, то логично предположить, что документация ему не помогла.
    3. Отправлять человека обратно читать документацию - аналогично простому отправлению на три буквы.
    Спрашивается, зачем? Не хочешь отвечать - пройди мимо.

    Конечно просто. Всего то почитать код DataColumn, а также Column от которого он наследуется, а также код Object, от которого наследуется Column, а также понять смысл пустого интерейса Configurable.

    Возможно опытным программистам это и легко - но начинающим - это далеко не просто, и далеко не быстро. Когда я вижу такой код:
    PHP:
    1. if ($provider instanceof ActiveDataProvider && $provider->query instanceof ActiveQueryInterface) {
    2.                 /* @var $model Model */
    3.                 $model = new $provider->query->modelClass;
    4.                 $label = $model->getAttributeLabel($this->attribute);
    5.             } elseif ($provider instanceof ArrayDataProvider && $provider->modelClass !== null) {
    6.                 /* @var $model Model */
    7.                 $model = new $provider->modelClass;
    8.                 $label = $model->getAttributeLabel($this->attribute);
    9.             } elseif ($this->grid->filterModel !== null && $this->grid->filterModel instanceof Model) {
    10.                 $label = $this->grid->filterModel->getAttributeLabel($this->attribute);
    То мне над каждой строчкой надо тупить минут 5, чтобы понять что куда идет, откуда берется, и как взаимосвязано. А таких строчек там не мало.

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

    По факту наоборот. Эти принципы - ни о чем не говорят.
    А вот конкретные примеры показывают как решать конкретные задачи, и анализируя тысячи таких примеров приходит понимание как оно в целом работает.
     
  12. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Я не читал код DataColumn, ответ на этот вопрос нашёл в официальной доке, которой и процитировал.
    Правильно учили. Но это у объектов в целом. А разработчики Yii2 в рамках своего фреймворка ввели ещё термин атрибут. В документации написано об этом. Имеют право :) Точно так же, как и всякие активные формы, активные запросы и прочее, и прочее.
    Вот это понять важно, кстати, на этом весь yii2 построен. Object автоматически инициализирует все поля на основе переданного в конструктор массива. Для этого, правда, либо поля должны быть public, либо должен быть реализован сеттер (который будет автоматически вызван). Так же, кстати, Object превращает код типа
    PHP:
    1. $obj->fignya = "something";
    в код
    PHP:
    1. $obj->setFignya("something");
    ,
    и с геттером - аналогично.

    Соответственно, это умеют все его наследники, кроме тех, что перекрывают этот функционал (из известных мне перекрывает ActiveRecord). Следующий уровень иерархии, класс Component, добавляет к этому функционалу события и поведения. Тоже из доки узнал, если что
     
  13. Walk

    Walk Активный пользователь

    С нами с:
    7 сен 2008
    Сообщения:
    452
    Симпатии:
    86
    Думаю все использовали Gii и видели стандартный код и функционал, который он генерирует.

    По умолчанию он берет все поля из таблицы, и делает из полученных данных таблицу через GridView::widget

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

    Попробовал - не получилось. Можно конечно все переписать с нуля, но хочется найти более простое и правильное решение.

    Что сделал:
    1. Изменил запрос, чтобы он получал дополнительное поле из другой таблицы (SQL запрос проверял - работает):
    PHP:
    1.     public function search($params)
    2.     {
    3.         $query = Osagocompanies::find();
    4.  
    5.         $query
    6.             ->select([
    7.                 'main.id',
    8.                 'main.company_name',
    9.                 'main.company_link',
    10.                 'main.insurance_users_id',
    11.                 'main.photo',
    12.                 'main.view',
    13.                 'insurance_users.company_name as id_name',
    14.             ])
    15.             ->from('e-osago_companies as main')
    16.             ->leftJoin('insurance_users', '`main`.`insurance_users_id` = `insurance_users`.`user_id`');
    17.  
    18.         $dataProvider = new ActiveDataProvider([
    19.             'query' => $query,
    20.         ]);
    21.  
    22.         $this->load($params);
    23.  
    24.         if (!$this->validate()) {
    25.             return $dataProvider;
    26.         }
    27.  
    28.         $query->andFilterWhere([
    29.             'company_name' => $this->company_name,
    30.             'company_link' => $this->company_link,
    31.             'photo' => $this->photo,
    32.         ]);
    33.  
    34.         $query->andFilterWhere(['like', 'company_name', $this->company_name])
    35.             ->andFilterWhere(['like', 'company_link', $this->company_link])
    36.             ->andFilterWhere(['like', 'photo', $this->photo]);
    37.  
    38.         return $dataProvider;
    39.     }
    2. Добавил аттбитут нового поля в модель (что с ним, что без него - без разницы):
    PHP:
    1. public function attributeLabels()
    2. {
    3.     return [
    4.         // другие поля
    5.         'id_name' => 'id_name',
    6.     ];
    7. }
    3. Добавил поле в GridView::widget
    PHP:
    1. [
    2.     'format' => 'html',
    3.     "value" => function ($data) {
    4.         $data->id_name;
    5.     }
    6. ],
    При выходе данных из модели - return $dataProvider новый параметр есть, но при генерации таблицы в GridView::widget параметр исчезает.
     
  14. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Лучшее решение - сделать связь (hasOne, hasMany) и использовать with(). И как данные из связанных моделей пихать в Grid в доках описано. А так, можно попробовать id_name объявить в модели публичным свойством, поскольку, думаю, оно туда не пишется (Active Record по дефолту берёт набор атрибутов из show fields).
     
  15. Walk

    Walk Активный пользователь

    С нами с:
    7 сен 2008
    Сообщения:
    452
    Симпатии:
    86
    Читал про такую возможность - там стены текстов, с гулькин нос примеров (как обычно) - прикинул, что я с этим неделю разбираться буду.

    В итоге:
    $query = (new Query()) в контроллере
    и foreach в виде

    Просто и работает.
     
  16. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Ну так тексты - это главное, а примеры так, чтоб пояснить :) Но твоё решение тоже норм. ActiveDataProvider хорош, если надо автоматом пагинацию, сортировку подставлять. Если не надо, то можно с ним и не заморачиваться
    --- Добавлено ---
    В ларке, кстати, примерно в этом же ключе связи между моделями реализованы.
     
  17. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    Неделю бы разбирался и потом бы очень много вопросов отпало, а пока будешь месяцы терять просто ожидая ответы
     
  18. Walk

    Walk Активный пользователь

    С нами с:
    7 сен 2008
    Сообщения:
    452
    Симпатии:
    86
    Мне и так сегодня уже намекнули коллеги, что я слишком много читаю документации.

    Я не против хоть с утра до вечера их читать и разбираться, вот только боюсь мне работодатель за такую работу платить не захочет.
     
  19. Walk

    Walk Активный пользователь

    С нами с:
    7 сен 2008
    Сообщения:
    452
    Симпатии:
    86
    При добавлении записи в бд через:

    PHP:
    1. Yii::$app->db->createCommand()
    2.                     ->insert('table', [
    3.                         'name' => $name
    4.                     ])
    5.                     ->execute();
    Можно как-то просто получить id добавленной записи? Аналогично mysqli_insert_id в нативном пхп?
     
  20. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    PHP:
    1. \Yii::$app->db->getLastInsertID()
     
    Walk нравится это.
  21. Walk

    Walk Активный пользователь

    С нами с:
    7 сен 2008
    Сообщения:
    452
    Симпатии:
    86
    Спасибо

    При выполнении запросов через new Query() можно перехватить и посмотреть отправляемый запрос через:
    PHP:
    1. $query->prepare(Yii::$app->db->queryBuilder)->createCommand()->rawSql
    А можно каким-то аналогичным образом перехватить SQL запрос создаваемый Yii::$app->db->createCommand() ?
     
  22. Walk

    Walk Активный пользователь

    С нами с:
    7 сен 2008
    Сообщения:
    452
    Симпатии:
    86
    Нашел ответ:
    Yii::$app->db->createCommand()->rawSql