Технологии разработки | Языки программирования | Фреймворки | База данных |
Для начала нужно установить и настроить OpenServer
OpenServer — готовая платформа для автоматизации работы мини-хостинга.
- Установка при помощи Composer
Composer - это пакетный менеджер уровня приложений для языка программирования PHP, который предоставляет средства по управлению зависимостями в PHP-приложении.
Для того, чтобы установить Yii2-фреймворк, нужно открыть консоль в OpenServer:
И ввести соответствующую команду:
cd domains
composer create-project yiisoft/yii2-app-basic basic
//composer create-project yiisoft/yii2-app-версия придуманное_название_проекта
Эта команда устанавливает последнюю стабильную версию Yii в директорию basic
. Если хотите, можете выбрать другое имя директории.
- Установка из архива
Установка Yii из архива состоит из трёх шагов:- Скачайте архив с yiiframework.com;
- Создать папку в
domains
; - Загрузить в папку архив;
- Распаковать архив;
- Зайти в папку
/config/web.php
добавьте секретный ключ в значение cookieValidationKey (при установке через Composer это происходит автоматически):
// !!! Напишите секретный ключ в поле (если оно пустое) - это требуется для проверки файлов cookie
'cookieValidationKey' => 'Введите_здесь_секретный_ключ_(произвольный_набор_символов)',
ЧПУ – красивые адреса, ставшие стандартом в веб-разработке.
Фреймворк Yii2 из коробки не имеет настроенных ЧПУ, но исправить это крайне легко. По умолчанию сразу после установки фреймворка для доступа к главной странице необходимо обратиться к папке web
, в которой и лежит публичная часть Yii2 приложения. Для доступа к главной странице нужно набрать адрес «http://название_проекта/web/».
От папки web
можно легко избавиться с помощью файлов .htaccess
.
.htaccess
в корне приложения:
RewriteEngine on
RewriteRule ^(.+)?$ /web/$1
.htaccess
в папке web
:
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
Таким образом, папки web
больше нет в адресной строке. Однако это еще не все. Для того, чтобы получить доступ к странице с формой, которая находится в действии actionIndex
контроллера SiteController
, нужно набрать следующий адрес: «http://название_проекта/?r=site/index». Вместо такого адреса хотелось бы иметь возможность обратиться к данной странице по такому адресу: «http://название_проекта/site/index».
Для решения поставленной задачи необходимо обратиться к файлу /config/web.php
и прописать в массив components
компонента urlManager
необходимый код:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
],
],
В элемент request
массива components
нужно добавить строчку 'baseUrl' => ' '
:
'components' => [
'request' => [
'cookieValidationKey' => 'произвольный_код',
'baseUrl' => '',
],
...
],
Для связи проекта с базой данных в файле /config/db.php
прописываются dbname
, username
и password
:
return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=название_базы_данных',
'username' => 'логин_от_PhpMyAdmin',
'password' => 'пароль_от_PhpMyAdmin',
'charset' => 'utf8',
];
В зависимости от того, авторизован ли пользователь, на странице компаний отображаются определенные элементы.
Страница компаний, как гостя, так и авторизованного пользователя, включает в себя:
- По 6 карточек компаний на каждой странице.
Каждая карточка имеет информацию: название компании, адрес, телефон и генеральный директор. - Пагинация.
Контроллер SiteController
действие Index
:
use app\models\Companies;
use yii\data\Pagination;
//Компании
public function actionIndex()
{
$query = Companies::find();
$pages = new Pagination(['totalCount' => $query->count(), 'pageSize' => 6]);
$model = $query->offset($pages->offset)->limit($pages->limit)->orderBy(['id' => SORT_DESC])->all();
return $this->render('index', compact('model', 'pages'));
}
Модуль Companies
:
namespace app\models;
use Yii;
class Companies extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'companies';
}
public function rules()
{
return [
['name', 'required', 'message' => 'Введите название вашей компании!'],
['inn', 'required', 'message' => 'Введите ИНН вашей компании!'],
[['inn'], 'integer'],
['inn', 'string', 'min' => 10, 'max' => 10],
['general_information', 'required', 'message' => 'Введите общую информацию вашей компании!'],
['general_manager', 'required', 'message' => 'Введите генерального директора вашей компании!'],
['address', 'required', 'message' => 'Введите адрес вашей компании!'],
['phone', 'required', 'message' => 'Введите телефон вашей компании!'],
[['name', 'general_manager', 'phone'], 'string', 'max' => 255],
];
}
public function attributeLabels()
{
return [
'name' => 'Название',
'inn' => 'ИНН',
'general_information' => 'Общая информация',
'general_manager' => 'Генеральный директор',
'address' => 'Адрес',
'phone' => 'Телефон',
];
}
//Связь комментария с компанией
public function getComments()
{
return $this->hasMany(Comments::class, ['id_company' => 'id']);
}
}
Представление index
:
<?php
use yii\bootstrap4\Html;
use yii\bootstrap4\LinkPager;
$this->title = 'Компании';
?>
<div class="container">
<div class="body-content">
<div class="row">
<?php foreach ($model as $company) { ?>
<div class="col-lg-3 bg-dark company_block">
<?php
echo "<a href = '/site/view/$company->id'>";
echo "<span style='color: #FFC134; font-weight: bold'>" . $company->name . "</span><br>";
echo "<span class = 'title_company'>Адрес: </span>" . $company->address . "<br>";
echo "<span class = 'title_company'>Телефон: </span>" . $company->phone . "<br>";
echo "<span class = 'title_company'>Генеральный директор: </span>" . $company->general_manager;
echo "</a>";
if (!Yii::$app->user->isGuest && \Yii::$app->user->identity->id == $company->id_user) {
echo "<div style='margin-left: 96%'>" .
"<div style='padding-bottom: 15px'>" . Html::a(Html::img('@web/img/pencil-fill.svg'), ['update', 'id' => $company->id]) . "</div>" .
Html::a(Html::img('@web/img/trash-fill.svg'), ['delete', 'id' => $company->id], [
'data' => [
'confirm' => 'Вы уверены, что хотите удалить эту компанию?',
'method' => 'post',
]
]) .
"</div>";
}
?>
</div>
<?php } ?>
</div>
<div class="mt-4">
<?php
if (!Yii::$app->user->isGuest) {
echo Html::a('Новая компания', ['create'], ['class' => 'btn btn-success']);
}
?>
</div>
</div><br>
<?= LinkPager::widget([
'pagination' => $pages,
]);
?>
</div>
Мобильная версия (гость):
companies.guest.mobile.version.mp4
Авторизованный пользователь на странице компаний имеет возможность: добавлять компании, а также редактировать и удалять созданные им компании. Доступны страницы "Мои компании" и раздел личной страницы пользователя, включающий в себя аватар и логин пользователя, при нажатии на которые всплывает выпадающий список со страницей "Профиль" и кнопкой "Выйти".
Десктопная версия (пользователь):
Мобильная версия (пользователь):
companies.mobile.version.user.mp4
📑 Оглавление
Поля и их заполнение:
Поля | Обязательность заполнения | Правила заполнения |
Фамилия | Да | |
Имя | Да | |
Отчество | Нет | |
Пол | Да | Две радиокнопки ("Мужчина" и "Женщина"). |
Дата рождения | Да | 1) Пользователь должен быть старше 18 лет; 2) Нельзя выбрать дату больше текущей. Формат даты рождения: гггг-мм-дд Пример: 2023-05-22 |
Телефон | Нет | Формат телефона должен быть: +7 (XXX) XXX-XX-XX Пример: +7 (981) 942-53-40 |
Да | Значение Email должно быть правильным email адресом. Пример: multiveb@mail.ru |
|
Местоположение | Да | При вводе местоположения всплывают текстовые подсказки. |
Краткое описание | Нет | |
Логин | Да | Логин должен быть уникальным (не должен совпадать с логиным из базы данных). |
Пароль | Да | Пароль от 8 до 12 символов должен содержать хотя бы одну большую букву, одну маленькую букву и одну цифру. Пример: Goodpassword7 |
Повторите пароль | Да | Введенные данные должны совпадать с данными из поля "Пароль". |
Для того, чтобы пользователь смог зарегистрироваться, для начала нужно создать модель.
Модуль (Module) – предоставляет данные, позволяет работать с конкретной таблицей из базы данных и реагирует на команды контроллера, изменяя своё состояние.
Для занесения данных зарегистрированного пользователя в базу данных, требуется получить таблицу с именем user
. Для этого используется статическая функция tableName
, которая возвращает имя таблиц. Функция attributeLabels
возвращает ассоциативный массив, в котором передаются имена для отображения в представлении.
Для более наглядного понимания безопасного заполнения полей данных информацией, стоит поподробнее описать функцию rules
. Она проверяет является ли выбранное поле строкой, числом и т.д. Также в rules
при желании можно написать собственные валидаторы, которые можно будет использовать для своих каких-либо проверок.
Валидатор | Описание | Для каких полей |
required | Поля обязательны для заполнения | surname, name, gender, date_birth, email, address, username, password, confirm_password |
safe | Атрибут безопасен для добавления в базу данных | middle_name, phone, description |
unique | Проверка на уникальность | username |
match | Проверка совпадения значения с заданным условием | password |
pattern | Регулярное выражение, с которым должно совпадать входящее значение | password |
compare | Проверка на совпадение | confirm_password |
compareAttribute | Сравнение введенного значения со значением из таблицы | confirm_password |
message | Сообщение/предупреждение | password, confirm_password |
Модуль RegistrationForm
:
namespace app\models;
use Yii;
use yii\base\Model;
use yii\db\ActiveRecord;
use app\models\User;
class RegistrationForm extends ActiveRecord {
public static function tableName() {
return 'user';
}
public function attributeLabels() {
return [
'avatar' => 'Аватар',
'surname' => 'Фамилия',
'name' => 'Имя',
'middle_name' => 'Отчество',
'gender' => 'Пол',
'date_birth' => 'Дата рождения',
'phone' => 'Телефон',
'email' => 'Email',
'address' => 'Местоположение',
'description' => 'Краткое описание',
'username' => 'Логин',
'password' => 'Пароль',
'confirm_password' => 'Повторите пароль',
];
}
public $confirm_password;
public function rules() {
return [
[['surname', 'name', 'gender', 'date_birth', 'email', 'address', 'username', 'password', 'confirm_password'], 'required'],
[['middle_name', 'phone', 'description'], 'safe'],
['email', 'email'],
['username', 'unique'],
['password', 'match', 'pattern' => '/^\S*(?=\S{8,12})(?=\S*[a-z])(?=\S*[A-Z])(?=\S*[\d])\S*$/', 'message' => 'Пароль от 8 до 12 символов должен содержать хотя бы одну большую букву, одну маленькую букву и одну цифру'],
['confirm_password', 'compare', 'compareAttribute' => 'password', 'message' => 'Пароли не совпадают'],
];
}
public function registration() {
if ($this->validate()) {
$this->avatar = "avatars/null_user.png";
$this->registration_date = date("Y-m-d");
$this->password = md5($this->password);
if ($this->save(false)) {
if (Yii::$app->user->login(User::findIdentity($this->id), 3600 * 24 * 30)) {
return true;
}
}
}
return false;
}
}
Далее в контроллере SiteController
было реализовано действие actionRegistration
.
Контроллер (Controller) – при запуске выполняет соответствующее действие, что обычно подразумевает создание соответствующих моделей и отображение необходимых представлений.
Действие (Action) – это метод класса контроллера, имя которого начинается на action
.
В переменной $model
при помощи new
реализована связь с моделью RegistrationForm
. Вызов $model->load()
ищет подмассив, который имеет имя, которое должно быть у формы модели, а уже из этого правильно именованного подмассива извлекает атрибуты. Для того, чтобы получить параметры запроса, нужно использовать методы Yii::$app->request->post()
компонента request
. Вызов $model->registration()
расписан в модели RegistrationForm
. Для перенаправления на домашнюю страницу в контроллере наследнике \yii\web\Controller
есть метод goHome()
. Данный метод позволяет успешно зарегистрированному пользователю попасть сразу на главную страницу, а именно на страницу представления index.php
в папке /views/site
авторизированного пользователя.
Передача введенных и автоматически прописанных данных, а именно username, password, confirm_password
происходит при помощи метода render
, куда первым параметром поступает строка – название представления и информация, передаваемая представлению.
В модели RegistrationForm
прописана функция registration
, в которой проверяется валидность введенных данных при помощи метода $this->validate()
. Для безопасного хранения и использования хэшированных паролей в базе данных используется md5
. Если данных успешно прошли проверку на валидность, определяется id
зарегистрированного пользователя, используя выражение Yii::$app->user->login(User::findIdentity($this->id))
. Оно возвращает экземпляр класса идентификатора, представляющего текущего пользователя, вошедшего в систему.
Контроллер SiteController
действие Registration
:
use app\models\RegistrationForm;
//Регистрация
public function actionRegistration() {
$model = new RegistrationForm();
if ($model->load(Yii::$app->request->post()) && $model->registration()) {
return $this->goHome();
}
return $this->render('registration', compact('model'));
}
Наконец, представление.
Представление (View) – отвечает за отображение данных модели пользователю, зашедшему на страницу сайта, реагируя на изменения модели.
Представление содержит в себе ту информацию, которая передается ей в контроллере. Здесь осуществляется вёрстка данной страницы, и в места, где это нужно, вставляется информация из контроллера.
Для создания интерактивной HTML-формы используется виджет ActiveForm
. Его следует описать поподробнее.
В контроллере передается экземпляр этой модели ($model
) в представление для виджета ActiveForm
, который генерирует форму. В вышеприведённом коде ActiveForm::begin()
не только создаёт экземпляр формы, но также и знаменует её начало. Весь контент, расположенный между ActiveForm::begin()
и ActiveForm::end()
, будет завёрнут в HTML-тег <form>
. Для создания в форме элемента с меткой и любой применимой валидацией с помощью JavaScript, вызывается ActiveForm::field()
, который возвращает экземпляр yii\bootstrap4\ActiveField
. Дополнительные HTML-элементы можно добавить к форме, используя обычный HTML или методы из класса помощника Html, как это было сделано с помощью Html::submitButton()
.
Также присутствует виджет DatePicker
. DatePicker
– это поле отображения и ввода даты, оно выглядит так же, как выпадающий календарь. Документация по DatePicker.
Помимо этого, дополнительно настроена связь поля ввода местоположения с API Яндекс.Карт. Данную настройку следует описать поподробнее.
Создаем файл представления registration.php
в папке /views/site
, в который добавляется код:
<script src = "https://api-maps.yandex.ru/2.1?apikey=51785512-ffbb-44c5-9044-7f1ab310d38e&lang=ru_RU" type = "text/javascript"></script>
<script src = "script.js"></script>
Затем создается файл script.js
в папке /web/js
, в который добавляется код:
ymaps.ready(init);
function init() {
let suggestView = new ymaps.SuggestView('registrationform-address');
}
В котором 'registrationform-address'
является id
поля ввода местоположения.
Представление registration
:
<?php
use yii\helpers\Html;
use yii\bootstrap4\ActiveForm;
use kartik\date\DatePicker;
$this->title = 'Регистрация';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class = "site-registration">
<h1><?= Html::encode($this->title) ?></h1>
<?php
$form = ActiveForm::begin([
'id' => 'myform',
'method' => 'post',
]);
echo $form->field($model, 'surname', ['template' => '{label}<span class="star"> *</span>{input}{error}'])->textInput();
echo $form->field($model, 'name', ['template' => '{label}<span class="star"> *</span>{input}{error}'])->textInput();
echo $form->field($model, 'middle_name', ['template' => '{label}{input}{error}'])->textInput();
echo $form->field($model, 'gender', ['template' => '{label}<span class="star"> *</span>{input}{error}'])->radioList([1 => 'Мужчина', 2 => 'Женщина']);
echo $form->field($model, 'date_birth', ['template' => '{label}<span class="star"> *</span>{input}{error}'])->widget(DatePicker::classname(), [
'options' => [
'placeholder' => 'гггг-мм-дд'
],
'pluginOptions' => [
'format' => 'yyyy-mm-dd',
'endDate' => '-18y'
]
]);
echo $form->field($model, 'phone')->widget(\yii\widgets\MaskedInput::className(), ['mask' => '+7 (999) 999-99-99'])->textInput();
echo $form->field($model, 'email', ['template' => '{label}<span class="star"> *</span>{input}{error}'])->textInput();
echo $form->field($model, 'address', ['template' => '{label}<span class="star"> *</span>{input}{error}'])->textInput();
echo $form->field($model, 'description')->textarea();
echo $form->field($model, 'username', ['template' => '{label}<span class="star"> *</span>{input}{error}'])->textInput();
echo $form->field($model, 'password', ['template' => '{label}<span class="star"> *</span>{input}{error}'])->passwordInput();
echo $form->field($model, 'confirm_password', ['template' => '{label}<span class="star"> *</span>{input}{error}'])->passwordInput();
echo "<br>";
echo Html::submitButton("Зарегистрироваться", ['class' => 'btn btn-success']);
ActiveForm::end();
?>
</div>
<script src = "https://api-maps.yandex.ru/2.1?apikey=51785512-ffbb-44c5-9044-7f1ab310d38e&lang=ru_RU" type = "text/javascript"></script>
<script src = "script.js"></script>
registration.mobile.version.mp4
📑 Оглавление
Поля и их заполнение:
Поля | Обязательность заполнения | Правила заполнения |
Логин | Да | Введенные данные должны совпадать с данными из таблицы. |
Пароль | Да | Введенные данные должны совпадать с данными из таблицы. |
Запомнить меня | Нет |
Для того, чтобы доступ к системе имели только авторизированные пользователи, используются фильтры контроля доступа (ACF).
ACF – это фильтры, которые могут присоединяться к контроллеру или модулю как поведение.
Контроллер SiteController
в папке /controllers
:
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['logout', 'my', 'create', 'update', 'delete'],
'rules' => [
[
'actions' => ['logout', 'my', 'create', 'update', 'delete'],
'allow' => true,
'roles' => ['@'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post', 'get'],
],
],
];
}
Код выше показывает ACF фильтр, связанный с контроллером SiteController
через поведение. Параметр only
указывает, что фильтр ACF нужно применять только к действиям logout, my, create, update, delete
. Параметр rules
задает правила доступа, которые означают следующее: разрешить аутентифицированным пользователям доступ к действиям logout, my, create, update, delete
.
При попытке доступа к действиям logout, my, create, update, delete
неавторизированного пользователя перенаправляет на форму авторизации, за которую отвечает метод действия actionLogin
контроллера SiteController
. Это действие проверяет, не является ли пользователь гостем. Если условие возвращает false
, это значит, что пользователь авторизован и он попадает на главную страницу. Если возвращается true
– создается экземпляр модели LoginForm
, в нее загружаются данные и вызывается метод login()
, который авторизует пользователя. Если данные загружены и метод login()
вернул true
, то пользователь переносится туда, откуда он пришел. В противном случае, передается модель в вид login
.
Контроллер SiteController
действие Login
:
use app\models\LoginForm;
//Авторизация
public function actionLogin()
{
if (!Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
return $this->goBack();
}
$model->password = '';
return $this->render('login', compact('model'));
}
Контроллер SiteController
действие Logout
(выход пользователя из личного кабинета):
//Выход из личного кабинета пользователя
public function actionLogout()
{
Yii::$app->user->logout();
return $this->goHome();
}
Метод login()
проверяет данные на соответствие правилам, описанных в модели. Здесь вызывается метод validatePassword()
, который при отсутствии ошибок создает объект User
, вызывая метод getUser()
. Метод проверяет, не авторизован ли пользователь. Если не авторизован – вызывается статический метод findByUsername()
с переданным ему введенным именем пользователя класса User
.
Модель User
реализует интерфейс yii\web\IdentityInterface
. В данной моделе должно быть объявлено семь методов:
Методы | Описание |
findIdentity() | Данный метод находит экземпляр identity class , используя ID пользователя. |
findIdentityByAccessToken() | Данный метод находит экземпляр identity class , используя токен доступа. Метод используется, когда требуется аутентифицировать пользователя только по секретному токену. |
findByUsername() | Данный метод находит пользователя по его логину. |
getId() | Данный метод возвращает ID пользователя, представленного данным экземпляром identity . |
getAuthKey() | Данный метод возвращает ключ, используемый для основанной на cookie аутентификации. Ключ сохраняется в аутентификационной cookie и позже сравнивается с версией, находящейся на сервере, чтобы удостоверится, что аутентификационная cookie верная. |
validateAuthKey() | Данный метод реализует логику проверки ключа для основанной на cookie аутентификации. |
validatePassword() | Данный метод сравнивает хранящийся в базе данных пароль с тем, что ввел пользователь. |
А так же объявляется метод tableName()
, который укажет, что модель User
будет взаимодействовать с таблицей user
.
Модуль User
:
namespace app\models;
use yii\db\ActiveRecord;
class User extends ActiveRecord implements \yii\web\IdentityInterface
{
public static function findIdentity($id)
{
return static::findOne($id);
}
public static function findIdentityByAccessToken($token, $type = null)
{
}
public static function findByUsername($username)
{
return static::findOne(['username' => $username]);
}
public function getId()
{
return $this->id;
}
public function getAuthKey()
{
return $this->auth_key;
}
public function validateAuthKey($authKey)
{
return $this->auth_key === $authKey;
}
public function validatePassword($password)
{
return $this->password === md5($password);
}
}
Представление login
:
<?php
use yii\bootstrap4\Html;
use yii\bootstrap4\ActiveForm;
$this->title = 'Войти';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-login">
<h1><?= Html::encode($this->title) ?></h1>
<?php
$form = ActiveForm::begin([
'id' => 'login-form',
'fieldConfig' => [
'template' => '{label}{input}{error}',
],
]);
echo $form->field($model, 'username')->textInput();
echo $form->field($model, 'password')->passwordInput();
echo $form->field($model, 'rememberMe')->checkbox();
echo "<br>";
echo Html::submitButton("Войти", ['class' => 'btn btn-success']);
?>
<?php ActiveForm::end(); ?>
</div>
authorization.mobile.version.mp4
📑 Оглавление
В зависимости от того, авторизован ли пользователь, на странице компании отображаются определенные элементы.
Страница компании, как гостя, так и авторизованного пользователя, включает в себя расширенную информацию. Каждая компания имеет информацию: название компании, ИНН, общая информация, генеральный директор, адрес и телефон.
Авторизованный пользователь имеет возможность:
- К каждому полю каждой компании оставить комментарии;
- Оставить комментарий к компании целиком;
- Видеть комментарии других пользователей.
Каждый комментарий включает в себя: время добавление, логин пользователя и текст комментария.
Реализована интерактивность добавления комментария (поле ввода по умолчанию скрыто, открывается по желанию пользователя, закрывается после сохранения). При добавлении нового комментария на экране появляется оповещение, в котором сказано, что комментарий успешно добавлен.
Контроллер SiteController
действие View
:
use app\models\Companies;
use app\models\Comments;
//Страница компании
public function actionView($id)
{
$model = Companies::findOne(['id' => $id]);
$model_c = Comments::find($id)->where(['=', 'id_company', $id])->orderBy(['time_comment' => SORT_DESC])->all();
//Добавить комментарий
$model_cr = new Comments();
if ($model_cr->load(Yii::$app->request->post())) {
$model_cr->id_company = $id;
$model_cr->id_user = Yii::$app->user->identity->id;
$model_cr->time_comment = date('Y-m-d H:i:s');
Yii::$app->session->setFlash('success', "Комментарий успешно добавлен");
if ($model_cr->save(false)) {
return $this->redirect(['view', 'id' => $id]);
}
}
return $this->render('view', compact('model', 'model_c', 'model_cr'));
}
Модуль Companies
указан в подразделе Компании.
Модуль Comments
:
namespace app\models;
use Yii;
class Comments extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'comments';
}
public function rules()
{
return [
[['id_company', 'id_user', 'time_comment'], 'required'],
[['name_comment', 'inn_comment', 'general_information_comment', 'general_manager_comment', 'address_comment', 'phone_comment', 'general_comment'], 'string'],
[['time_comment'], 'safe'],
[['id_company'], 'exist', 'skipOnError' => true, 'targetClass' => Companies::class, 'targetAttribute' => ['id_company' => 'id']],
[['id_user'], 'exist', 'skipOnError' => true, 'targetClass' => User::class, 'targetAttribute' => ['id_user' => 'id']],
];
}
public function attributeLabels()
{
return [
'name_comment' => '',
'inn_comment' => '',
'general_information_comment' => '',
'general_manager_comment' => '',
'address_comment' => '',
'phone_comment' => '',
'general_comment' => '',
];
}
//Связь комментария с компанией
public function getCompany()
{
return $this->hasOne(Companies::class, ['id' => 'id_company']);
}
//Связь комментария с пользователем
public function getUser()
{
return $this->hasOne(User::class, ['id' => 'id_user']);
}
}
Представление view
:
<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
use yii\bootstrap4\ActiveForm;
$this->title = $model->name;
if (!Yii::$app->user->isGuest) {
$this->params['breadcrumbs'][] = ['label' => 'Мои компании', 'url' => ['my']];
}
$this->params['breadcrumbs'][] = $this->title;
?>
<style>
.alert-success.alert.alert-dismissible {
margin-left: 0px;
}
</style>
<br><div class="companies-view">
<div id="accordion">
<div class="card">
<!--Название-->
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
<?=
DetailView::widget([
'model' => $model,
'attributes' => [
'name',
],
]);
?>
</button>
<?php if (!Yii::$app->user->isGuest) { ?>
<span class="comment_chat" onmousedown = "viewNameCom()">Прокомментировать <img style="width: 20px" src="/web/img/chat-fill.svg"></span>
<?php } ?>
</h5>
</div>
<?php if (!Yii::$app->user->isGuest) { ?>
<div id="collapseOne" class="collapse show" aria-labelledby="headingOne">
<div class="card-body">
<?php
foreach ($model_c as $comment) {
if ($comment->name_comment !== NULL) {
echo "<span style='color: #7D7C7C'>" . $comment->time_comment . "</span>" .
"<span style='margin-left: 10px; color: #eea90a'>" . $comment->user->username . ":" . "</span>" .
"<span style='margin-left: 10px'>" . $comment->name_comment . "</span><br>";
}
}
?>
<!--Комментарии к названию компании-->
<div class="comments-form" id="add_name_comment">
<?php $form = ActiveForm::begin([
'id' => 'add_nam_comment',
'method' => 'post',
]);
echo $form->field($model_cr, 'name_comment')->textInput();
echo Html::submitButton('Добавить комментарий', ['class' => 'btn btn-success']);
ActiveForm::end(); ?>
</div>
</div>
</div>
<?php } ?>
<!--ИНН-->
<div class="card-header" id="headingTwo">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
<?=
DetailView::widget([
'model' => $model,
'attributes' => [
'inn',
],
]);
?>
</button>
<?php if (!Yii::$app->user->isGuest) { ?>
<span class="comment_chat" onmousedown = "viewAddInnCom()">Прокомментировать <img style="width: 20px" src="/web/img/chat-fill.svg"></span>
<?php } ?>
</h5>
</div>
<?php if (!Yii::$app->user->isGuest) { ?>
<div id="collapseTwo" class="collapse show" aria-labelledby="headingTwo">
<div class="card-body">
<?php
foreach ($model_c as $comment) {
if ($comment->inn_comment !== NULL) {
echo "<span style='color: #7D7C7C'>" . $comment->time_comment . "</span>" .
"<span style='margin-left: 10px; color: #eea90a'>" . $comment->user->username . ":" . "</span>" .
"<span style='margin-left: 10px'>" . $comment->inn_comment . "</span><br>";
}
}
?>
<!--Комментарии к ИНН компании-->
<div class="comments-form" id="add_inn_comment">
<?php $form = ActiveForm::begin([
'id' => 'add_in_n_comment',
'method' => 'post',
]);
echo $form->field($model_cr, 'inn_comment')->textInput();
echo Html::submitButton('Добавить комментарий', ['class' => 'btn btn-success']);
ActiveForm::end(); ?>
</div>
</div>
</div>
<?php } ?>
<!--Общая информация-->
<div class="card-header" id="headingThree">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
<?=
DetailView::widget([
'model' => $model,
'attributes' => [
'general_information',
],
]);
?>
</button>
<?php if (!Yii::$app->user->isGuest) { ?>
<span class="comment_chat" onmousedown = "viewGenInfCom()">Прокомментировать <img style="width: 20px" src="/web/img/chat-fill.svg"></span>
<?php } ?>
</h5>
</div>
<?php if (!Yii::$app->user->isGuest) { ?>
<div id="collapseThree" class="collapse show" aria-labelledby="headingThree">
<div class="card-body">
<?php
foreach ($model_c as $comment) {
if ($comment->general_information_comment !== NULL) {
echo "<span style='color: #7D7C7C'>" . $comment->time_comment . "</span>" .
"<span style='margin-left: 10px; color: #eea90a'>" . $comment->user->username . ":" . "</span>" .
"<span style='margin-left: 10px'>" . $comment->general_information_comment . "</span><br>";
}
}
?>
<!--Комментарии к общую информацию компании-->
<div class="comments-form" id="add_general_information_comment">
<?php $form = ActiveForm::begin([
'id' => 'add_gen_inf_comment',
'method' => 'post',
]);
echo $form->field($model_cr, 'general_information_comment')->textInput();
echo Html::submitButton('Добавить комментарий', ['class' => 'btn btn-success']);
ActiveForm::end(); ?>
</div>
</div>
</div>
<?php } ?>
<!--Генеральный директор-->
<div class="card-header" id="headingFour">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#collapseFour" aria-expanded="false" aria-controls="collapseFour">
<?=
DetailView::widget([
'model' => $model,
'attributes' => [
'general_manager',
],
]);
?>
</button>
<?php if (!Yii::$app->user->isGuest) { ?>
<span class="comment_chat" onmousedown = "viewGenManCom()">Прокомментировать <img style="width: 20px" src="/web/img/chat-fill.svg"></span>
<?php } ?>
</h5>
</div>
<?php if (!Yii::$app->user->isGuest) { ?>
<div id="collapseFour" class="collapse show" aria-labelledby="headingFour">
<div class="card-body">
<?php
foreach ($model_c as $comment) {
if ($comment->general_manager_comment !== NULL) {
echo "<span style='color: #7D7C7C'>" . $comment->time_comment . "</span>" .
"<span style='margin-left: 10px; color: #eea90a'>" . $comment->user->username . ":" . "</span>" .
"<span style='margin-left: 10px'>" . $comment->general_manager_comment . "</span><br>";
}
}
?>
<!--Комментарии к генеральному директору компании-->
<div class="comments-form" id="add_general_manager_comment">
<?php $form = ActiveForm::begin([
'id' => 'add_gen_man_comment',
'method' => 'post',
]);
echo $form->field($model_cr, 'general_manager_comment')->textInput();
echo Html::submitButton('Добавить комментарий', ['class' => 'btn btn-success']);
ActiveForm::end(); ?>
</div>
</div>
</div>
<?php } ?>
<!--Адрес-->
<div class="card-header" id="headingFive">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#collapseFive" aria-expanded="false" aria-controls="collapseFive">
<?=
DetailView::widget([
'model' => $model,
'attributes' => [
'address',
],
]);
?>
</button>
<?php if (!Yii::$app->user->isGuest) { ?>
<span class="comment_chat" onmousedown = "viewAddressCom()">Прокомментировать <img style="width: 20px" src="/web/img/chat-fill.svg"></span>
<?php } ?>
</h5>
</div>
<?php if (!Yii::$app->user->isGuest) { ?>
<div id="collapseFive" class="collapse show" aria-labelledby="headingFive">
<div class="card-body">
<?php
foreach ($model_c as $comment) {
if ($comment->address_comment !== NULL) {
echo "<span style='color: #7D7C7C'>" . $comment->time_comment . "</span>" .
"<span style='margin-left: 10px; color: #eea90a'>" . $comment->user->username . ":" . "</span>" .
"<span style='margin-left: 10px'>" . $comment->address_comment . "</span><br>";
}
}
?>
<!--Комментарии к адресу компании-->
<div class="comments-form" id="add_address_comment">
<?php $form = ActiveForm::begin([
'id' => 'add_addr_comment',
'method' => 'post',
]);
echo $form->field($model_cr, 'address_comment')->textInput();
echo Html::submitButton('Добавить комментарий', ['class' => 'btn btn-success']);
ActiveForm::end(); ?>
</div>
</div>
</div>
<?php } ?>
<!--Телефон-->
<div class="card-header" id="headingSix">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#collapseSix" aria-expanded="false" aria-controls="collapseSix">
<?=
DetailView::widget([
'model' => $model,
'attributes' => [
'phone',
],
]);
?>
</button>
<?php if (!Yii::$app->user->isGuest) { ?>
<span class="comment_chat" onmousedown = "viewPhoneCom()">Прокомментировать <img style="width: 20px" src="/web/img/chat-fill.svg"></span>
<?php } ?>
</h5>
</div>
<?php if (!Yii::$app->user->isGuest) { ?>
<div id="collapseSix" class="collapse show" aria-labelledby="headingSix">
<div class="card-body">
<?php
foreach ($model_c as $comment) {
if ($comment->phone_comment !== NULL) {
echo "<span style='color: #7D7C7C'>" . $comment->time_comment . "</span>" .
"<span style='margin-left: 10px; color: #eea90a'>" . $comment->user->username . ":" . "</span>" .
"<span style='margin-left: 10px'>" . $comment->phone_comment . "</span><br>";
}
}
?>
<!--Комментарии к телефону компании-->
<div class="comments-form" id="add_phone_comment">
<?php $form = ActiveForm::begin([
'id' => 'add_ph_comment',
'method' => 'post',
]);
echo $form->field($model_cr, 'phone_comment')->textInput();
echo Html::submitButton('Добавить комментарий', ['class' => 'btn btn-success']);
ActiveForm::end(); ?>
</div>
</div>
</div>
<?php } ?>
</div><br>
<!--Общие комментарии-->
<?php if (!Yii::$app->user->isGuest) { ?>
<span style="color: #FFC134; font-weight: bold; font-size: 25px">Общие комментарии</span>
<span style="float: right; color: #eea90a; cursor: pointer" onmousedown = "viewGenCom()">Прокомментировать компанию <img style="width: 25px" src="/web/img/chat-fill.svg"></span>
<?php foreach ($model_c as $comment) {
if ($comment->general_comment !== NULL) {
echo "<div style='border-top: 1px solid #DFDFDF; margin-top: 25px'>";
echo "<br><span style='color: #7D7C7C'>" . $comment->time_comment . "</span>" .
"<span style='margin-left: 10px; color: #eea90a'>" . $comment->user->username . ":" . "</span>" .
"<span style='margin-left: 10px'>" . $comment->general_comment . "</span>";
echo "</div>";
}
} ?>
<div class="comments-form" id="add_general_comment">
<?php $form = ActiveForm::begin([
'id' => 'add_gen_comment',
'method' => 'post',
]);
echo $form->field($model_cr, 'general_comment')->textarea(['rows' => 6]);
echo Html::submitButton('Добавить комментарий', ['class' => 'btn btn-success']);
ActiveForm::end(); ?>
</div>
<?php } ?>
</div>
</div>
Создаем файл script.js
в папке /web/js
:
//При клике появляется поле для ввода комментария и кнопка
//Название
function viewNameCom() {
document.getElementById("add_name_comment").style.display = "block";
};
//ИНН
function viewAddInnCom() {
document.getElementById("add_inn_comment").style.display = "block";
}
//Общая информация
function viewGenInfCom() {
document.getElementById("add_general_information_comment").style.display = "block";
};
//Генеральный директор
function viewGenManCom() {
document.getElementById("add_general_manager_comment").style.display = "block";
};
//Адрес
function viewAddressCom() {
document.getElementById("add_address_comment").style.display = "block";
};
//Телефон
function viewPhoneCom() {
document.getElementById("add_phone_comment").style.display = "block";
};
//Общие комментарии
function viewGenCom() {
document.getElementById("add_general_comment").style.display = "block";
};
Десктопная версия (пользователь):
page-company.mobile.version.mp4
📑 Оглавление
Модуль Companies
указан в подразделе Компании.
Поля для заполнения:
- Название;
- ИНН;
- Общая информация;
- Генеральный директор;
- Адрес;
- Телефон.
При добавлении новой компании на экране появляется оповещение, в котором сказано, что компания успешно добавлена.
Контроллер SiteController
действие Create
:
use app\models\Companies;
//Добавить новую компанию
public function actionCreate()
{
$model = new Companies();
if ($this->request->isPost) {
if ($model->load($this->request->post())) {
$model->id_user = Yii::$app->user->identity->id;
Yii::$app->session->setFlash('success', "Новая компания успешно добавлена");
if ($model->save()) {
return $this->redirect(['index', 'id' => $model->id]);
}
}
} else {
$model->loadDefaultValues();
}
return $this->render('create', compact('model'));
}
Представление create
:
<?php
use yii\helpers\Html;
$this->title = 'Новая компания';
$this->params['breadcrumbs'][] = ['label' => 'Мои компании', 'url' => ['my']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="companies-create">
<h1><?= Html::encode($this->title) ?></h1>
<?= $this->render('_form', ['model' => $model]) ?>
</div>
Представление _form
:
<?php
use yii\helpers\Html;
use yii\bootstrap4\ActiveForm;
?>
<div class="companies-form">
<?php
$form = ActiveForm::begin();
echo $form->field($model, 'name')->textInput();
echo $form->field($model, 'inn')->textInput();
echo $form->field($model, 'general_information')->textarea(['rows' => 6]);
echo $form->field($model, 'general_manager')->textInput();
echo $form->field($model, 'address')->textarea(['rows' => 6]);
echo $form->field($model, 'phone')->textInput();
?>
<div class="form-group">
<?= Html::submitButton('Сохранить', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
Мобильная версия:
create-company.mobile.version.mp4
📑 Оглавление
Модуль Companies
указан в подразделе Компании.
Поля для редактирования:
- Название;
- ИНН;
- Общая информация;
- Генеральный директор;
- Адрес;
- Телефон.
При редактировании компании на экране появляется оповещение, в котором сказано, что компания успешно обновлена.
Контроллер SiteController
действие Update
:
use app\models\Companies;
//Редактировать компанию
public function actionUpdate($id)
{
$model = Companies::findOne($id);
if ($this->request->isPost && $model->load($this->request->post()) && $model->save()) {
Yii::$app->session->setFlash('success', "Компания успешно обновлена");
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('update', compact('model'));
}
Представление update
:
<?php
use yii\helpers\Html;
$this->title = 'Редактировать компанию ' . $model->name;
$this->params['breadcrumbs'][] = ['label' => 'Мои компании', 'url' => ['my']];
$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->id]];
$this->params['breadcrumbs'][] = 'Редактировать компанию ' . $model->name;
?>
<div class="companies-update">
<h1><?= Html::encode($this->title) ?></h1>
<?= $this->render('_form', ['model' => $model]) ?>
</div>
Представление _form
:
<?php
use yii\helpers\Html;
use yii\bootstrap4\ActiveForm;
?>
<div class="companies-form">
<?php
$form = ActiveForm::begin();
echo $form->field($model, 'name')->textInput();
echo $form->field($model, 'inn')->textInput();
echo $form->field($model, 'general_information')->textarea(['rows' => 6]);
echo $form->field($model, 'general_manager')->textInput();
echo $form->field($model, 'address')->textarea(['rows' => 6]);
echo $form->field($model, 'phone')->textInput();
?>
<div class="form-group">
<?= Html::submitButton('Сохранить', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
Мобильная версия:
update-company.mobile.version.mp4
📑 Оглавление
При удалении компании на экране появляется оповещение, в котором сказано, что компания успешно удалена.
Контроллер SiteController
действие Delete
:
use app\models\Companies;
//Удалить компанию
public function actionDelete($id)
{
$model = Companies::findOne($id);
Companies::findOne($id)->delete();
Yii::$app->session->setFlash('success', "Компания успешно удалена");
return $this->redirect(['/site/index']);
return $this->render(compact('model'));
}
Модуль Companies
указан в подразделе Компании.
Изображение корзины, при нажатии на которую удаляется компания (и относящиеся к ней комментарии), находится в представлении index
, которое указано в подразделе Компании.
Мобильная версия:
delete-company.mobile.version.mp4
📑 Оглавление
В данном разделе находятся компании, которые принадлежат конкретному пользователю. Пользователь может добавлять, редактировать и удалять компании, а также, кликнув по названию, перейти на страницу компании с комментариями.
Поля каждой компании:
- Название;
- ИНН;
- Общая информация;
- Генеральный директор;
- Адрес;
- Телефон.
Контроллер SiteController
действие My
:
use app\models\CompaniesSearch;
//Мои компании
public function actionMy()
{
$searchModel = new CompaniesSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('my', compact('searchModel', 'dataProvider'));
}
Модуль CompaniesSearch
:
namespace app\models;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\models\Companies;
class CompaniesSearch extends Companies
{
public function rules()
{
return [
[['id', 'id_user', 'inn'], 'integer'],
[['name', 'general_information', 'general_manager', 'address', 'phone'], 'safe'],
];
}
public function scenarios()
{
return Model::scenarios();
}
public function search($params)
{
$query = Companies::find()->where(['id_user' => \Yii::$app->user->identity->id]);
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
return $dataProvider;
}
$query->andFilterWhere([
'id' => $this->id,
'id_user' => $this->id_user,
'inn' => $this->inn,
]);
$query->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'general_information', $this->general_information])
->andFilterWhere(['like', 'general_manager', $this->general_manager])
->andFilterWhere(['like', 'address', $this->address])
->andFilterWhere(['like', 'phone', $this->phone])
->orderBy(['id' => SORT_DESC]);
return $dataProvider;
}
}
Представление my
:
<?php
use yii\helpers\Html;
use yii\grid\GridView;
$this->title = 'Главная';
$this->params['breadcrumbs'][] = 'Мои компании';
?>
<div class="my-index">
<h1>Мои компании</h1>
<div class="mt-4">
<?php
echo Html::a('Новая компания', ['create'], ['class' => 'btn btn-success']);
?>
</div>
<div class="table-responsive mt-4">
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
[
'attribute' => 'name',
'format' => 'raw',
'value' => function($data) {
return '<a href = "/site/view/'.$data->id.'">' . $data->name . '</a>';
}
],
'inn',
'general_information',
'general_manager',
'address',
'phone',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
</div>
</div>
Десктопная версия (компаний нет):
Десктопная версия (компания есть):
Десктопная версия (несколько компаний), а также поиск:
my-companies.mobile.version.mp4
📑 Оглавление
В данном разделе выводится информация о пользователе, а именно:
- Аватарка;
- Фамилия;
- Имя
- Отчество;
- Пол;
- Дата рождения;
- Телефон;
- Email;
- Местоположение;
- Краткое описание;
- Дата регистрации.
Контроллер PersonalController
действие Page
:
//Личный кабинет пользователя
public function actionPage() {
return $this->render('page');
}
Для того, чтобы доступ к системе имели только авторизированные пользователи, используются фильтры контроля доступа (ACF).
ACF – это фильтры, которые могут присоединяться к контроллеру или модулю как поведение.
Контроллер PersonalController
в папке /controllers
:
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['personal', 'update'],
'rules' => [
[
'actions' => ['personal', 'update'],
'allow' => true,
'roles' => ['@'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post', 'get'],
],
],
];
}
Модуль Personal
:
namespace app\models;
class Personal extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'user';
}
public function rules()
{
return [
[['surname', 'name', 'gender', 'date_birth', 'email', 'address'], 'required'],
['avatar', 'file', 'extensions' => 'png, jpg'],
[['middle_name', 'phone', 'description'], 'safe'],
['email', 'email'],
];
}
public function attributeLabels()
{
return [
'avatar' => 'Аватар',
'surname' => 'Фамилия',
'name' => 'Имя',
'middle_name' => 'Отчество',
'gender' => 'Пол',
'date_birth' => 'Дата рождения',
'phone' => 'Телефон',
'email' => 'Email',
'address' => 'Местоположение',
'description' => 'Краткое описание'
];
}
public function getComments()
{
return $this->hasMany(Comments::class, ['id_user' => 'id']);
}
public function getCompanies()
{
return $this->hasMany(Companies::class, ['id_user' => 'id']);
}
}
Представление page
:
<?php
use yii\helpers\Html;
$this->title = 'Профиль';
$this->params['breadcrumbs'][] = 'Профиль';
?>
<div class="personal-index">
<div class="row">
<div class="col-lg-3 col-md-4 col-sm-12 mt-3 ml-auto mr-auto personal_block img">
<img src="/web/<?= Yii::$app->user->identity->avatar ?>" class="avatar_img">
</div>
<div class="col-lg-4 col-md-7 col-sm-12 mt-3 ml-auto mr-auto personal_block">
<span class="block">
<span class="data">Фамилия:</span><?= Yii::$app->user->identity->surname ?>
</span>
<span class="block">
<span class="data">Имя:</span><?= Yii::$app->user->identity->name ?>
</span>
<?php if (Yii::$app->user->identity->middle_name != NULL) { ?>
<span class="block">
<span class="data">Отчество:</span><?= Yii::$app->user->identity->middle_name ?>
</span>
<?php } ?>
<span class="block">
<span class="data">Пол:</span>
<?php if (Yii::$app->user->identity->gender == 1) {
echo "Мужчина";
} else {
echo "Женщина";
} ?>
</span>
<span class="block">
<span class="data">Дата рождения:</span><?= date("d.m.Y", strtotime(Yii::$app->user->identity->date_birth)) ?>
</span>
<span class="block grey">
<span class="data">Дата регистрации:</span><?= date("d.m.Y", strtotime(Yii::$app->user->identity->registration_date)) ?>
</span>
</div>
<div class="col-lg-4 col-md-12 col-sm-12 mt-3 ml-auto mr-auto personal_block">
<?php if (Yii::$app->user->identity->phone != NULL) { ?>
<span class="block">
<span class="data">Телефон:</span><?= Yii::$app->user->identity->phone ?>
</span>
<?php } ?>
<span class="block">
<span class="data">Email:</span><?= Yii::$app->user->identity->email ?>
</span>
<span class="block">
<span class="data">Местоположение:</span>
</span>
<span>
<?= Yii::$app->user->identity->address ?>
</span>
<?php if (Yii::$app->user->identity->description != NULL) { ?>
<span class="block">
<span class="data">Краткое описание:</span>
</span>
<span>
<?= Yii::$app->user->identity->description ?>
</span>
<?php } ?>
</div>
</div>
<div class="mt-4">
<?php
echo Html::a('Редактировать профиль', ['update', 'id' => Yii::$app->user->id], ['class' => 'btn btn-success']);
?>
</div>
</div>
Мобильная версия:
personal.mobile.version.mp4
📑 Оглавление
Контроллер PersonalController
действие Update
:
use Yii;
use app\models\Personal;
//Редактировать информацию о пользователе
public function actionUpdate($id)
{
$model = Personal::findOne($id);
$model->avatar_now = $model->avatar;
if ($model->load(\Yii::$app->request->post()) && $model->uppage()) {
}
return $this->render('update', compact('model'));
}
В модуль Personal
, указанный в подразделе Личный кабинет пользователя, добавляем код для добавления/редактирования и удаления заменяемой аватарки пользователя, а именно виджет UploadedFile
. Документация по UploadedFile.
Модуль Personal
:
use Yii;
use yii\web\UploadedFile;
use yii\helpers\Url;
public $avatar_now;
public function uppage() {
if ($this->validate()) {
if ($this->avatar = UploadedFile::getInstance($this, 'avatar')) {
$file_name = time() . '_user.' . $this->avatar->extension;
if ($this->avatar->saveAs('avatars/' . $file_name)) {
if (file_exists($this->avatar_now)) {
unlink($this->avatar_now);
}
$this->avatar = 'avatars/' . $file_name;
}
} else {
$this->avatar = $this->avatar_now;
}
}
if ($this->save(false)) {
Yii::$app->response->redirect(Url::to(['personal/page', 'id' => Yii::$app->user->id]));
}
}
В представлении указан немаловажный виджет DatePicker
. DatePicker
представлен в подразделе Регистрация.
Представление update
:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use kartik\date\DatePicker;
$this->title = 'Редактировать профиль';
$this->params['breadcrumbs'][] = ['label' => 'Профиль', 'url' => ['page', 'id' => $model->id]];
$this->params['breadcrumbs'][] = 'Редактировать профиль';
?>
<div class="personal-form">
<?php $form = ActiveForm::begin([
'id' => 'mypersonal',
'method' => 'post',
'fieldConfig' => [
'template' => '{label} {input}<span style="color: #dc3545">{error}</span>',
],
]); ?>
<div class="row mb-4">
<img src="/web/<?= Yii::$app->user->identity->avatar ?>" class="col-lg-3 col-md-12">
</div>
<?php
echo $form->field($model, 'avatar')->fileInput();
echo $form->field($model, 'surname', ['template' => '{label}<span class="star"> *</span>{input}<span style="color: #dc3545">{error}</span>'])->textInput();
echo $form->field($model, 'name', ['template' => '{label}<span class="star"> *</span>{input}<span style="color: #dc3545">{error}</span>'])->textInput();
echo $form->field($model, 'middle_name')->textInput();
echo $form->field($model, 'gender', ['template' => '{label}<span class="star"> *</span>{input}<span style="color: #dc3545">{error}</span>'])->radioList([1 => 'Мужчина', 2 => 'Женщина']);
echo $form->field($model, 'date_birth', ['template' => '{label}<span class="star"> *</span>{input}<span style="color: #dc3545">{error}</span>'])->widget(DatePicker::classname(), [
'options' => [
'placeholder' => 'гггг-мм-дд'
],
'pluginOptions' => [
'format' => 'yyyy-mm-dd',
'endDate' => '-18y',
'todayHighlight' => true
]
]);
echo $form->field($model, 'phone')->widget(\yii\widgets\MaskedInput::className(), ['mask' => '+7 (999) 999-99-99'])->textInput();
echo $form->field($model, 'email', ['template' => '{label}<span class="star"> *</span>{input}<span style="color: #dc3545">{error}</span>'])->textInput();
echo $form->field($model, 'address', ['template' => '{label}<span class="star"> *</span>{input}<span style="color: #dc3545">{error}</span>'])->textInput();
echo $form->field($model, 'description')->textarea();
echo "<br>";
echo Html::submitButton("Сохранить", ['class' => 'btn btn-success']);
ActiveForm::end(); ?>
</div>
personal-update.mp4
📑 Оглавление