Yii. Записки сумасшедшего админа.

Это записная книжка по некоторым аспектам Yii версии 2. Здесь нет никакого систематизирования материала или логического изложения, скорее сюда попали вещи, которые были записаны, чтобы не забыть.

Установка Yii framework 2 на хостинг извращённым способом

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

Итак. Композер нахрен, ставим только из исходников. Для чего идём в за архивом на сайт. Качаем basic версию. После чего кидаем содержимое архива в корневой каталог сайта и готовимся к танцам с бубном.

Суть в том, что из соображений безопасности, корневым каталогом сайта должен стать подкаталог web. И как следствие, всё, кроме этого каталога должно быть вынесено за пределы сайта и доступности веб-сервера. И по умолчанию, фреймворк и заточен на то, что будет так. Однако, не все хостинги позволяют такие извращения. И поэтому мы сейчас эту схему сломаем!

  1. Создайте подкаталог yii2 и переместите туда все файлы и каталоги.
  2. Теперь зайтите в yii2/web и переместите оттуда все файлы и каталоги на ДВА уровня вверх, т.е. в корневой каталог вашего сайта. В подкаталоге web должно стать пусто!
  3. Выходим на уровень вверх и стираем подкаталог web. Затем создаём вместо него симлинку, которая будет называться также web залинкована будет на каталог уровнем выше, т.е. на «..»
  4. И последний штрих, редактируем файл index.php, чтобы пути указанные в нём, соответствовали реалиям, т.е. вместо строк:
require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');

$config = require(__DIR__ . '/../config/web.php')

у нас будут:

require(__DIR__ . '/yii2/vendor/autoload.php');
require(__DIR__ . '/yii2/vendor/yiisoft/yii2/Yii.php');

$config = require(__DIR__ . '/yii2/config/web.php');

Вот собственно почти и всё, но не нужно забывать и об ещё одном важном моменте. Момент этот называется файл .htaccess. Дело в том, что вам наверняка захочется пользоваться «чистыми» или как некоторые говорят «красивыми» ссылками. Но это не получится до тех пор пока вы не настроите модуль переадресации в apache, который называется mod_rewrite. Вот как раз дня него и создаётся .htaccess, куда добавляются строки:

RewriteEngine on

# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# otherwise forward it to index.php
RewriteRule . index.php

Данные правила говорят о том, что если не будет найден запрошенный файл или каталог, то запрос будет передан на выполнение файлу index.php.

Начальная настройка Yii2

Для начала необходимо настроить подключение к базе данных:

1. Откройте файл настроек по адресу config/db.php

return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=%ИМЯ_БАЗЫ_ДАННЫХ%',
'username' => '%ПОЛЬЗОВАТЕЛЬ%',
'password' => '%ПАРОЛЬ%',
'charset' => 'utf8',
];

Соответственно замените всё, что выделено процентами(включая проценты, например, %ИМЯ_БАЗЫ_ДАННЫХ% заменяем на blog). Кодировку можете изменить, если используете не utf8. БД разумеется надо предварительно создать как и %ПОЛЬЗОВАТЕЛЯ% для неё и назначить ему %ПАРОЛЬ%.

2. Теперь откройте файл настроек по адресу config/web.php

1) Первым делом, если вы ставили Yii из исходников нам надо сделать одну вещь. Найдите в файле строки:

 // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => '',

Если значение cookieValidationKey пустое (а оно будет пустым, если ставили с нуля из исходников), то его надо заполнить. Напишите туда какую-нибудь белиберду из букв смешанного регистра и цифр длиной не менее, чем 32 символа.

Теперь мы настроим отображение даты и времени в нужном формате, настроим красивые ссылки, настроим доступ к gii.

2) Настройки формата даты и времени
Настроим вывод даты и времени в привычном нам формате:

'formatter' => [
'class' => 'yii\i18n\Formatter',
'dateFormat' => 'php:d.m.Y',
'datetimeFormat' => 'php:d.m.Y H:i',
'timeFormat' => 'php:H:i:s',
],

Таким образом мы настроили формат даты (например, 01.01.2020), формат даты и времени одновременно(например, 01.02.2020 10:22), формат времени(например, 21:47:26). Обратите внимание, формат даты и времени с отображением без секунд, а в формате времени есть отображение секунд. За это отвечает «s».

3) Настроим красивые ссылки (urlManager)
Для начала составим скелет:

'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false
],

enablePrettyUrl — включение красивых ссылок. При значенииfalse у вас будут проходить запросы длинными некрасивыми ссылками: http://test.com/?controller=site&action=index. Как вам? Согласитесь, не очень. Как будет выглядеть при значении true:http://test.com/site/index. Гораздо лучше, не так ли?

showScriptName — показывать ли расширение файла. Допустим .php или .html. Не советую включать, такие ссылки выглядит не очень красиво: http://test.com/site/contacts.html, либо http://test.com/site/contacts. На мой взгляд второй вариант лучше, чем первый. Но тут дело вкуса.

3) Теперь перейдем к настройке gii.

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

Изначально gii расположен по адресу http://test.com/gii, на своё усмотрение вы можете изменить ссылку, но я не буду об этом рассказывать. Перейдя в первый раз, вы можете заметить, что доступ запрещен. Идёт блокировка по IP. Чтобы добавить ваш IP в белый лист, необходимо в конце нашего файла настроек найти allowedIPs и в массив добавить еще один IP — ваш.

3.  И теперь давайте настроим последний файл настроек по адресу config/params.php

В данном файле вы можете вводить любые переменные, к которым позже сможете обращаться. Здесь вы можете задать данные, которые статичны. Например, контактный e-mail, имя сайта.

return [
'email' => 'admin@example.com',
....
]

Получить значение вы можете такой строчкой:

Yii::$app->params['email']


Локализация Yii2. Добавление русского языка в Yii2

По умолчанию, в Yii включен английский язык. Чтобы включить русский язык в вашем приложении, нужно открыть конфигурационный файл config/web.php и добавить параметр:

language' => 'ru-RU'

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

\Yii::$app->language = 'ru-RU';

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

Создаём каталог messages/ru-RU и заходим в неё. Теперь мы можем создать различные .php файлы, в которых массивы будут возвращать переводы. Создайте app.php и вносите туда общие сообщения. Затем можно создать buttons.php и помещать туда переводы кнопок. Это удобно и позволяет вам редактировать без долгого поиска по одному файлу.

Формат файлов такой:

<?php
return [ 'Message' => 'Сообщение',
'Test' => 'Тест',
//и так далее
];

Теперь, чтобы воспользоваться переводом просто воспользуйтесь такой строчкой:

Yii::t('app', 'Test');

Как вы догадались, app — название файла, а test — текст. Если у вас в настройках выставлен русский язык, то выведется «Тест», а если английский — Test.

Можно пользоваться и таким вариантом функции t:

$username = 'Alexander';
echo \Yii::t('app', 'Hello, {username}!', [
    'username' => $username,
]);

Здесь вместо {username}! будет подставлено значение из определённого списка, т.е. $username.

и такой вариант:

$sum = 42;
echo \Yii::t('app', 'Balance: {0}', $sum);

Здесь значение {0} будет заменено ПЕРВЫМ ПО СЧЁТУ аргументом после ‘Balance: {0}’, сответственно {1} вторым и т.д.

и это далеко не всё: расширенное и специальное форматирование, множественное число, настройка файлов переводов можно прочитать в документации https://www.yiiframework.com/doc/guide/2.0/ru/tutorial-i18n.

Для тех, кто хочет дать пользователям менять язык — воспользуйтесь данной техникой:

1. Создайте модель Lang.php в папке models соответственно.

<?php
namespace app\models;
 
use Yii;
use yii\base\Model;
 
class Lang extends Model
{
 
public function getCurrentLang()
{
$lang = Yii::$app->request->cookies->getValue('lang');
return $lang;
}
 
}

Затем создайте файл /assets/LangRequest.php с содержимым:

<?php
 
namespace app\assets;
 
use Yii;
use yii\web\Request;
use app\models\Lang;
 
class LangRequest extends Request
{
 
CONST RU = "ru-RU";
CONST EN = "en-US";
 
public function resolve()
{
$resolve = parent::resolve();
 
$lang = Lang::getCurrentLang();
($lang == "en") ? $language = self::EN : $language = self::RU;
Yii::$app->language = $language;
 
return $resolve;
}
 
private function getCurrentLang()
{
$lang = Yii::$app->request->cookies->getValue('lang');
return $lang;
}
 
}
 
?>

Теперь нам нужно подключить LangRequest. Открываем настройки и в request вставляем

'class' => 'app\assets\LangRequest'

Теперь вы можете менять ваш язык по запросу http://site.com/lang/. Язык меняется автоматически. То есть, если у вас сейчас русский, то станет английский и наоборот.

 

Технология MVC применительно к Yii

Значит так. MVC (Model->View->Controller) Модель->Представление->Контроллер. Но на самом деле всё наоборот. Запрос попадает в контроллер, контроллер может подгружать данные, используя модель, а может и просто генерировать их сам. А для вывода уже используется представление. А что такое эти Контроллер, Модель и Представление на практике? Контроллер — это класс, который наследуется от служебного класса Yii с названием Controller (yii\web\Controller в общем случае), Модель — это класс, который наследуется от служебного класса Yii с названием Model (yii\base\Model в общем случае), а представление — это php-файл с HTML-шаблоном для отображения данных (генерации веб-страницы или её части).

Итак, допустим URL у нас http://mysite.com/index.php?r=site/baka

Здесь site — это контроллер, baka — это действие. Что это означает на практике? Означает, что управление по такому запросу передаётся в файл controllers/SiteController.php (обратите внимание, что имя файла пишется именно так: две половинки имени с заглавной буквы. Служебное слово Controller обязательно, а Site соотвественно имя которое в r=site/baka, с заглавной буквы. Если сделать по другому, то Yii не найдёт файл с классом контроллера) и на действие, которое внутри класса представляет собой публичную функцию класса SiteController имеет название actionBaka (public function actionBaka() в общем случае). Опять же имя функции должно быть именно в таком формате: слово action является служебным, а Baka это из r=site/baka но где Baka с заглавной буквы.

Далее, внутри функции actionBaka() может произойти работа с одной или несколькими моделями (которые кстати хранятся в подкаталоге models/ и которые должны подключаться в файл, где расположен контроллер перед использованием), а потом может быть вызвана функция (имя_представления часто совпадает с тем, которое используется в action, т.е. в нашем случае baka) $this->render(‘имя_представления’, [данные]), которая подключит шаблон представления views/site/baka.php и загрузит туда данные, ранее полученные контроллером из модели (или сгенерированные самим контроллером), которые представляют из себя именной массив. Обратите внимание, что site в имени файла views/site/baka.php — это опять же имя контроллера.

Вот вкратце и всё.

Как в Yii получить переменную из запроса

Yii::$app->request->get('имя_переменной');
Yii::$app->request->post('имя_переменной');

Как в Yii получить параметры запроса

Например есть запрос /index.php?r=kaka/baka&color=blue

Мы можем получить значение param (которое blue) вот так: Yii::$app->params[‘color’].

Как работать с сессиями в Yii

Никаких дополнительных действий по созданию, открытию или закрытию сессии не требуется. Просто создаём объект сессии:

$session = Yii::$app->session;

и далее получаем данные из сессии:

$session->get('имя_переменной');

записываем данные в сессию:

$session->set('имя_переменной', значение);

или удаляем определённые данные из сессии:

$session->remove('имя_переменной');

или провреяем на существование переменную в сессии:

$session->has('имя_переменной');

Безусловно можно не создавать $session и обращаться к методу напрямую:

$session = Yii::$app->session->get('имя_переменной');

Как работать с куками в Yii

  1. Запись и удаление. Создаём объект ответа:
    $cookies = Yii::$app->response->cookies;

    и записываем значение в браузер:

    $cookies->add(new \yii\web\Cookies([
    'name' => 'имя_куки',
    'value' => 'значение_куки'
    ]));

    и удаляем

    $cookies->remove('имя_куки');
    
    
  2. Чтение. Создаём объект запроса:
    $cookies = Yii::$app->request->cookies;

    и читаем значение:

    $name = $cookies->getValue('name');

Как закодировать URL, содержащий специальные символы и не ASCII символы

Html::encode(строка)

Как сформировать ссылку в Yii

Это делается через специальный класс urlManager:

Yii:$app->urlManager->createUrl(['контроллер/действие'], 'имя_параметра' => 'значение_параметра');

Формы ввода в Yii

Поскольку формы ввода являются частью моделей, то собственно работа с формами — это работа с моделями.  Т.е. необходимо создать класс с формой, который будет размещаться в файле в том же каталоге models/ и будет унаследована от класса Model (yii\base\Model в общем случае). Как и в любом типичном случае для модели, в классе необходимо объявить перечень публичных переменных, которые будут являться названиями полями формы (а также могут выступать названиями полей с данными в базе данных в случае использования работы с БД и ActiveForm).

Далее в классе формы нам необходимо использовать служебную функцию rules() (это взято из basic примера):

public function rules()
{
return [
[['username', 'password'], 'required'],
['rememberMe', 'boolean'],
['password', 'validatePassword'],
];
}

В данной функции описываются правила валидации формы. Это означате, что каждому полю ввода мы прописываем определённые правила. Например, поля username и password имеют свойство required, т.е. обязательно должно быть заполнены в форме для успешной её отправки. Поле rememberMe имеет тип boolean, а поле password будет проходить валидацию с помощью функции validatePasswor(). Для поля, ещё можно использовать, например, свойство ’email’, тогда его содержимое должно будет соответствовать какому-либо email адресу. А ещё можно использовать свойство ‘captcha’, чтобы  получить капчу, а ещё… смотрите в доку, там дофига.

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

[['username', 'password'], 'required', 'message' => 'Незаполнено поле']
['email', 'email', 'message' => 'Неправильно введён адрес E-mail']

Далее, мы можем назначить подсказки к полям ввода, с помощью служебной функции attributeLabels():

public function attributeLabels()
{
return [
'verifyCode' => 'Verification Code',
];
}

Там массив из двух частей: имя поля (verifyCode), и подсказка к нему (Verification Code), которая будет выведена при отображении формы.

Далее, как это всё отобразить. В классе контроллера, в необходимом нам действии мы создаём экземпляр класса нашей формы, т.е. например, если наш класс формы называется MyForm, то прописываем:

$form = new MyForm();

if ($form->load(Yii::$app->request->post()) && $form->validate()) {
   .......
}

$this->render('myform');

Блок if сработает после отправки формы (проверяется метод POST, которым всегда происходит отправка формы и при этом если форма прошла валидацию). В этом блоке у нас уже есть готовые переменные, которые мы можем прочитать из формы и что-то с ними сделать — вывести на экран, сохранить в БД или что-то ещё. Доступ к переменной осуществляется через класс формы, например: $form->name;

Теперь переходим к созданию представления myform. В каталоге views/контроллер/ создаём файл myform.php. В нём во первых строках должно быть:

use yii\bootstrap\ActiveForm;

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

use yii\helpers\Html;
здесь находятся хелперы (подпрограммы) для генерации фрагмента HTML-кода. Можно писать HTML-код самому, но поскольку мы используем фреймфорк, рекомендуется делать это только средствами фреймворка. Если нужна КАПЧА, то также подключаем:

use yii\captcha\Captcha;

Далее обязательно должны присутствовать строки:

<?php $form = ActiveForm::begin(['id' => 'myform']); ?>
<?php ActiveForm::end(); ?>

между которых будут располагаться строки по выводу элементов формы, например:

<?= $form->field($model, 'name')->textInput(['autofocus' => true]) ?>

<?= $form->field($model, 'email') ?>

<?= $form->field($model, 'body')->textarea(['rows' => 6]) ?>
<?= $form->field($model, 'password')->passwordInput() ?>

<?= $form->field($model, 'rememberMe')->checkbox([
'template' => "<div class=\"col-lg-offset-1 col-lg-3\">{input} {label}</div>\n<div class=\"col-lg-8\">{error}</div>",
]) ?>
<?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [
'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>',
]) ?>

<?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?>

и т.д.

Замечание по загрузке файлов

Поле выбора файла в форме в rules обозначается так:

['file', 'file']

или если ещё нужно ограничить загрузку определёнными расширениями, то

['file', 'file', 'extensions' => 'jpg, png']

Далее нужно указать опции при открытии ActiveForm в представлении, т.е.:

$form = ActiveForm::begin([options => ['enctype' => 'multipart/form-data']]);

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

$form->field($model, 'file')->fileInput();

в контроллере нужно подключить пространство имён:

use yii\web\UploadedFile;

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

$form->file = UploadedFile::getInstance($form, 'file'); // получить объект из формы $form и поля 'file'
$form->file->saveAs(путь);

При этом можно использовать значения $form->file->baseName для получения части имени файла до точки и $form->file->extension для получения части имени файла после точки.

 

admin has written 75 articles

Leave a Reply