Технологии разработки | Языки программирования | Фреймворки | База данных |
- Техническое задание
- Блок-схема
- База данных
- Yii2-framework
- Реализация программного продукта
- Главная страница
- Контакты и форма обратной связи
- Регистрация
- Авторизация
- Меню
- Подменю
- Товары
- Добавление товара в корзину
- Форма оформления заказа
- Поля и их заполнение
- Верстка формы оформления заказа
- Акции
- Форма бронирования столика
- Поля и их заполнение
- Верстка формы бронирования столика
- Отзывы
- Поля и их заполнение
- Верстка формы отзывов
- Страницы личных заказов и столиков
- Админ-панель
- Категории меню
- Подкатегории меню (напитки)
- Товары
- Заказчики и их заказы
- Забронированные столики
- Акции
- Отзывы
- Размещение сайта на хостинге
На сайте реализовано семь разделов: «Главная страница», «Акции», «Меню», «Забронировать столик», «Отзывы», «Контакты» и «Корзина»; и формы регистрации и авторизации пользователей.
Для администраторов доступна админ-панель, включающая в себя семь разделов: «Категории меню», «Подкатегории меню (напитки)», «Товары», «Заказчики и их заказы», «Забронированные столики», «Акции» и «Отзывы».
Для начала нужно установить и настроить 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',
];
Главная страница кафе-ресторана состоит из трех составляющих:
- Лендинг: пользователь видит его сразу при входе на сайт.
Лендинг (целевая страница) – веб-страница, которая используется для усиления эффективности рекламы, увеличения аудитории. Целевая страница обычно содержит информацию о товаре или услуге. Призывает выполнить целевое действие: оставить контакты, подписаться на рассылку, оформить заявку.
- «О нас»: краткое описание кафе-ресторана «Pleasure».
- «Интерьер»: показ интерьера при помощи слайдера.
Слайдер – это специальный элемент веб-дизайна, представляющий собой блок определенной ширины. Их функция заключается в добавлении картинок в текст и более выгодный показ данных сайта. Описание того, какие атрибуты содержит в себе разработанный слайдер, представлено в таблице:
Атрибуты | Описание |
data-nav = "thumbs" |
По стандарту слайдер переключается по флажкам, которые находятся под изображением. Чтобы эти флажки заменить на изображения из слайдера, нужно прописать дополнительный атрибут со значением data-nav = "thumbs" |
data-loop = "true" |
По стандарту слайдеры доходят до последнего изображения и останавливаются. Есть специальный атрибут, который запускает просмотр заново — data-loop = "true" |
data-keyboard = "true" |
Позволяет листать слайды кнопками на клавиатуре |
Мобильная версия главной страницы:
mobile-version-of-the-main-page.mp4
📑 Оглавление
В начале раздела «Контакты» указаны адрес, телефон, e-mail и режим работы кафе-ресторана, а также была добавлена Google карта.
Стоит разобрать добавление Google карты на сайт поподробнее:
- Открыть сайт Google Maps;
- Ввести компанию на картах, нажать на «Поделиться»;
- Нажать «Встраивание карт» и выбрать размер из предложенных или выбрать «Другой размер» и указать свои параметры;
- Скопировать получившийся HTML-код и вставить его в код своего сайта в то место, где будет размещена карта.
Поля | Обязательность заполнения | Правила заполнения |
Ваше имя | Да | |
Ваш E-mail | Да | Формат: ***@yandex.ru Пример: multiveb@yandex.ru |
Тема письма | Да | |
Сообщение | Да | |
Проверочные символы | Да | Пример: zugioo |
Отправка сообщения на почту происходит через Simple Mail Transfer Protocol (SMTP) с помощью yandex. В файле настроек /config/web.php
и добавляется настройка отправки почты в элемент массива components
:
'components' => [
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'useFileTransport' => false,
'transport' => [
'class' => 'Swift_SmtpTransport',
'host' => 'smtp.yandex.ru',
'username' => 'ваша_почта@yandex.ru',
'password' => 'ваш_пароль',
'port' => '465',
'encryption' => 'ssl',
],
],
...
],
Код для отправки введенных данных на почту, прописанный в вашей модели:
public function contact($email)
{
if ($this->validate()) {
Yii::$app->mailer->compose()
->setTo('***@yandex.ru') //Кому отправить
->setFrom(['***@yandex.ru' => $this->name]) //От кого
->setSubject($this->subject) //Тема сообщения
->setHtmlBody($this->body. '<br><br>' . $this->email) //Текст сообщения и отправивший
->send(); //Отправка сообщения
return true;
}
return false;
}
Код для отправки введенных данных на почту, прописанный в вашем контроллере:
public function actionContact() //actionContact() - название контроллера
{
$model = new ContactForm(); //ContactForm() - название модели
if ($model->load(Yii::$app->request->post()) && $model->contact(Yii::$app->params['adminEmail'])) {
if (true) {
Yii::$app->session->setFlash('success', "Благодарим Вас за обращение к нам. Мы ответим вам как можно скорее.");
return $this->refresh();
} else {
Yii::$app->session->setFlash('error', 'Внимание! Ваше письмо по каким-то причинам не отправлено!
Вы можите связаться с нами по телефону 8 (981) 942-53-40 или написать нам на почту cafe_restaurant_pleasure@email.com');
}
}
return $this->render('contact', ['model' => $model]); //contact - название вьюшки
}
После того, как клиент ввел корректные данные и нажал на кнопку «ОТПРАВИТЬ», всплывает Flash-сообщение «Благодарим Вас за обращение к нам. Мы ответим вам как можно скорее.». Все данные, которые ввел пользователь, отправляются на почту администратора.
Форма обратной связи с корректно заполненными полями:
Оповещение об успешной отправке письма:
Мобильная версия страницы "Контакты":
mobile-version-of-the-feedback-form.mp4
Отправленное письмо:
Поля | Обязательность заполнения | Правила заполнения |
Логин | Да | Логин должен быть уникальным (не должен совпадать с логиным из базы данных). |
Пароль | Да | Пароль от 8 до 12 символов должен содержать хотя бы одну большую букву, одну маленькую букву и одну цифру. Пример: Goodpassword7 |
Повторите пароль | Да | Введенные данные должны совпадать с данными из поля "Пароль". |
Для того, чтобы пользователь смог зарегистрироваться, для начала нужно создать модель.
Модуль (Module) – предоставляет данные, позволяет работать с конкретной таблицей из базы данных и реагирует на команды контроллера, изменяя своё состояние.
Для занесения данных зарегистрированного пользователя в базу данных, требуется получить таблицу с именем user
. Для этого используется статическая функция tableName
, которая возвращает имя таблиц. Функция attributeLabels
возвращает ассоциативный массив, в котором передаются имена для отображения в представлении.
Для более наглядного понимания безопасного заполнения полей данных информацией, стоит поподробнее описать функцию rules
. Она проверяет является ли выбранное поле строкой, числом и т.д. Также в rules
при желании можно написать собственные валидаторы, которые можно будет использовать для своих каких-либо проверок.
Валидатор | Описание | Для каких полей |
required | Поля обязательны для заполнения | login, password, confirm_password |
unique | Проверка на уникальность | login |
match | Проверка совпадения значения с заданным условием | password |
pattern | Регулярное выражение, с которым должно совпадать входящее значение | password |
compare | Проверка на совпадение | confirm_password |
compareAttribute | Сравнение введенного значения со значением из таблицы | confirm_password |
message | Сообщение/предупреждение | login, password, confirm_password |
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 [
'login' => 'Логин',
'password' => 'Пароль',
'confirm_password' => 'Повторите пароль',
];
}
public $confirm_password;
public function rules() {
return [
[['login', 'password', 'confirm_password'], 'required'],
['login', '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->password = md5($this->password);
$this->role = 2;
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\base\Controller
есть метод goHome()
. Данный метод позволяет успешно зарегистрированному пользователю попасть сразу на главную страницу, а именно на страницу представления index.php
в папке /views/site
авторизированного пользователя.
Передача введенных и автоматически прописанных данных, а именно login, password, confirm_password, role
происходит при помощи метода render
, куда первым параметром поступает строка – название представления и информация, передаваемая представлению.
В модели RegistrationForm
прописана функция registration
, в которой проверяется валидность введенных данных при помощи метода $this->validate()
. Для безопасного хранения и использования хэшированных паролей в базе данных используется md5
. Если данных успешно прошли проверку на валидность, определяется id
зарегистрированного пользователя, используя выражение Yii::$app->user->login(User::findIdentity($this->id))
. Оно возвращает экземпляр класса идентификатора, представляющего текущего пользователя, вошедшего в систему.
//Регистрация пользователя
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\widgets\ActiveField
. Дополнительные HTML-элементы можно добавить к форме, используя обычный HTML или методы из класса помощника Html, как это было сделано с помощью Html::submitButton()
.
<?php
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
$this->title = 'Регистрация';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class = "site-registration">
<div class = "admin-panel_name"><?= Html::encode($this->title) ?></div><br>
<?php
$form = ActiveForm::begin([
'id' => 'myform',
'method' => 'post',
'fieldConfig' => [
'template' => '{label}{input}{error}',
],
]);
echo $form->field($model, 'login')->textInput();
echo $form->field($model, 'password')->passwordInput();
echo $form->field($model, 'confirm_password')->passwordInput();
echo "<br>";
echo Html::submitButton("Зарегистрироваться", ['class' => 'btn btn-primary']);
ActiveForm::end();
?>
</div>
Мобильная версия страницы "Регистрация":
mobile-version-of-the-registration-form.mp4
📑 Оглавление
Поля | Обязательность заполнения | Правила заполнения |
Логин | Да | Введенные данные должны совпадать с данными из таблицы. |
Пароль | Да | Введенные данные должны совпадать с данными из таблицы. |
Запомнить меня | Нет |
Для того, чтобы доступ к системе имели только авторизированные пользователи, используются фильтры контроля доступа (ACF).
ACF – это фильтры, которые могут присоединяться к контроллеру или модулю как поведение.
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['logout'],
'rules' => [
[
'actions' => ['logout'],
'allow' => true,
'roles' => ['@'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post', 'get'],
],
],
];
}
Код выше показывает ACF фильтр, связанный с контроллером SiteController
через поведение. Параметр only
указывает, что фильтр ACF нужно применять только к действию logout
(выйти из системы). Параметр rules
задает правила доступа, которые означают следующее: разрешить аутентифицированным пользователям доступ к действию logout
.
При попытке доступа к действию logout
неавторизированного пользователя перенаправляет на форму авторизации, за которую отвечает метод действия actionLogin
контроллера SiteController
. Это действие проверяет, не является ли пользователь гостем. Если условие возвращает false
, это значит, что пользователь авторизован и он попадает на главную страницу. Если возвращается true
– создается экземпляр модели LoginForm
, в нее загружаются данные и вызывается метод login()
, который авторизует пользователя. Если данные загружены и метод login()
вернул true
, то пользователь переносится туда, откуда он пришел. В противном случае передается модель в вид login
.
//Авторизация
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', [
'model' => $model,
]);
}
Метод 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
.
namespace app\models;
use yii\db\ActiveRecord;
class User extends ActiveRecord implements \yii\web\IdentityInterface
{
public static function tableName() {
return 'user';
}
public static function findIdentity($id)
{
return static::findOne($id);
}
public static function findIdentityByAccessToken($token, $type = null)
{
}
public static function findByUsername($login)
{
return static::findOne(['login' => $login]);
}
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);
}
}
Мобильная версия страницы "Авторизация":
mobile-version-of-the-authorization-form.mp4
📑 Оглавление
Хостинг – это комплекс услуг, которые позволяют разместить сайт или другие данные в сети Интернет. Обычно под фразой "хостинг для сайта" подразумевают место и мощности на сервере (специальном компьютере с круглосуточным подключением к сети). Таблица сравнений популярных хостинг-компаний за май 2022 года (Данные были взяты с сайтов https://ru.hostings.info и https://hostinghub.ru):
Хостинг | Оценка | Количество клиентов | Стоимость от, р. | Поддержка | Тестовый период, дн. |
timeweb | 9.5/10 | 210000 | 179 | PHP, Python, HTTP/2, Memcached | 10 |
спринт ХОСТ | 9.5/10 | 358669 | 133 | PHP, Python, Node.js, HTTP/2, Memcached, Perl, Sphinx | 30 |
Beget | 9.3/10 | 165000 | 169 | PHP, Python, HTTP/2, Memcached, Redis, Perl, Sphinx | 30 |
FORNEX | 9.0/10 | 110000 | 75 | PHP, Python, Node.js, Memcached, Ruby | 7 |
REG.RU | 9.0/10 | 2200000 | 152 | PHP, Python, HTTP/2, Perl | 14 |
Для размещения проекта на сервере был выбран хостинг-провайдер Beget по следующим причинам: долгий пробный период, оперативная деятельность технической поддержки, стабильная и быстрая работа расположенных на нем сайтов.
Загрузка проекта на сервер состоит из следующих этапов:
- Выбор хостинга;
- Выбор и регистрация домена;
- Загрузка сайта на хостинг:
3.1. Добавление архива, который содержит в себе все файлы сайта;
3.2. Импорт SQL-файла в PhpMyAdmin.
Ссылка на разработанный программный продукт (на данный момент сайт расположен на хостинге "спринт ХОСТ"): f0635336.xsph.ru