Автор Анна Евкова
Преподаватель который помогает студентам и школьникам в учёбе.

Разработка сайта для парикмахерской

Содержание:

Введение

Каждый год растет количество людей, подключенных к сети интернет. В России правительством решается задача цифровизации и облегчения доступа к сети разных слоев населения.

Чаще всего пользователи интернет проводят время в сети в поисках информации о различных знаниях, общении, образовании, информации о товарах или предприятиях, оказывающих услуги.

На веб сайтах компаний, оказывающих услуги, можно ознакомится с прейскурантом и ценой, узнать порядок и время работы, задать вопросы сотрудникам по интересующим вопросам, узнать местоположение предприятия.

Сегодня очень важно хозяину предприятия, заинтересованному в росте и прочному положению на рынке, иметь свои странички в социальных сетях и, безусловно, иметь отдельный сайт.

Сайт — это не только главный рекламный инструмент, но и место где потенциальные потребители и тех, кто предлагает услуги могут познакомится и принять решение о сотрудничестве.

Сайт должен иметь понятную структуру, логичные связи между частями и иметь дружественный интерфейс. Также он должен быть настроенным так, чтобы поисковые системы предлагали потенциальным клиентам его в числе первых, как известно, пользователи редко заглядывают дальше второй странички в результатах запроса поисковых систем.

Целью данной работе является разработка сайта для сети парикмахерских «Парикмахерская №1 где потенциальных клиентов оставить заявку на запись и получить ответ от сотрудников, и возможность разместить этот сайт в сети интернет.

Задачами для достижения поставленной цели являются:

  • Разработка дизайна сайта
  • Создание базы данных
  • Программирование внутренней логики сайта
  • Тестирование работы на локальном сервере.

Сайт должен быть в современном стиле и соответствовать корпоративному стилю. Он должен содержать информацию о компании, ее истории, о новостях и прейскуранту оказываемых услуг.

Глава 1. Техническое задание и выбор средств реализации.

Сеть парикмахерских «Парикмахерская №1» оказывает широкий спектр услуг, это не только классические стрижки, но и помывка головы, укладка праздничных причесок, косметические услуги. Помимо этого, есть перечень услуг, которые предлагаются только мужчинам, такие как подравнивание усов и бороды. Формирование бакенбарды.

Структурно организация выглядит следующим образом (рисунок 1).

https://eduherald.ru/i/2015/6/339/image004.png

Рисунок 1. Структурная схема предприятия.

Владелец сети «Парикмахерская №1» надеется благодаря созданию сайта увеличить объемы оказания услуг и прибыль за счет привлечения большего числа клиентов, открытию новых салонов – расширить бизнес.

Одним из пожеланий владельца сети, является чтобы сайт обладал той же стилистической и цветовой направленностью что и уже действующие салоны.

Для достижения поставленной цели и решения задач, необходимо выбрать инструменты.

Обычно сайт представляет собой набор страниц, на который отображены текстовая, графическая и иная информация в понятном посетителям виде. Эти страницы имеют свою логику построения и стандартизированный язык. Этот язык называется HTML (от англ. HyperText Markup Language — «язык гипертекстовой разметки»). Чтобы придать динамичности и интерактивности на странице, необходимо использовать другой язык, который называется Javascript.

Язык Javascript предназначен для использования в браузере, и практически каждый из браузеров сегодня понимают его без каких-либо дополнительных программным средств. Каждый браузер уже готов для исполнения команд этого языка. Я буду его использовать внутри страниц, который будут показаны пользователям.

Сервер — это компьютер на котором хранится весь сайт и выдается по запросу пользователей. Чтобы эффективно обрабатывать запросы пользователей и хранить данные о них и о услугах, необходим язык программирования и база данных.

Лидером среди языков по использованию при создании веб сайтов является PHP. Это скриптовый язык общего назначения, который поддерживается подавляющим большинством хостинг-провайдеров. Я буду его использовать для построение внутренней логики работы сайта.

В качестве базы данных для хранения информации я выбрал свободная реляционная система управления базами данных MySQL. Эта СУБД является решением для малых и средних приложений, и она очень гибкая, к тому же очень хорошо работает в связке с языком PHP.

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

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

  • Яндекс браузер версии 21
  • Opera браузер версии 73
  • Internet Explorer версии 11
  • Mozilla Firefox версии 85
  • Google Chrome версии 88

Функционально внутренняя программа, написанная на PHP, должна уметь:

  • Выдавать по запросу нужную страницу
  • Осуществлять обратную связь с пользователями
    • Принимать отзывы и записывать их в базу данных
    • Принимать заявку на прием
    • Вести учет посещений
    • Вести учет голосов, отданных за конкретного специалиста

Структура сайта предполагается стандартной для малых предприятий и будет включать следующие разделы:

  1. Главная страница
  2. О компании
  3. Услуги
  4. Предварительная запись
  5. Отзывы о нас
  6. Контакты
  7. Страница администратора

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

На странице администратора должен быть доступен интерфейс для

  • Ответов на отзывы
  • Просмотр и редактирование списка работающих специалистов
  • Просмотр посещений сайта
  • Назначение скидки зарегистрированным посетителям.

Каждая страница сайта должна корректно отображаться на всех видах разрешений экранов монитора, т.е. иметь адаптивную разметку. А мета теги (техническая не отображаемая информация, но считываемая поисковыми системами) должны быть настроены для возможности без ошибочного попадания в поисковую выдачу следующих поисковых систем:

  • www.Google.com
  • www.Yandex.ru
  • www.bing.com
  • www.baidu.com

Глава 2. Описание модулей серверной части и их взаимодействие.

2.1 Общая структура

В общем виде структура сайта состоит из взаимодействия клиентской и серверной частей и базы данных. Структура представлена на рисунке 2.1.

Серверная часть

Клиентская часть

БД

Рисунок 2.1 Общая структура сайта.

Серверная часть работает на отдельном хостинге и должна решать следующие задачи:

  • разграничение доступа
  • добавление записи в расписание
  • возможность отвечать на отзывы о мастерах
  • редактирование списка работающих мастеров
  • вести учёт пользователей

В целях решения данных задач, структура серверной части, должна иметь модульный тип. Структура серверной части представлена на рисунке 2.2.

Каждый модуль хранится отдельной от других и содержит набор функций, реализующих его функционал. В таблице 2.1 представлен список с описание использованных программных модулей. На рисунке 2.7 приведено дерево вызова программных модулей.

Таблица 2.1 Таблица с описание программных модулей

Название модуля

Назначение

Auth.php

Модуль авторизации

Otzivi.php

Модуль управления отзывами

Masters.php

Модуль управления информацией о мастерах

Zapis.php

Модуль записи к конкретному мастеру и занятость

Statistik.php

Модуль ведения статистики

DB.php

Модуль работы с базой данных

Controll.php

Модуль контроллера вызовов

Страница

авторизации

Главная страница сайта

Возможность

записи

Редактор мастеров

Ответы на отзывы

Страница администратора сайта

Статистика

сайта

Рисунок 2.2 Структура серверной части.

2.2 Алгоритм работы сайта

Алгоритм взаимодействия пользователей и администраторов сайта приведен в виде UML диаграммы последовательности и представлен на рисунках 2.4 - 2.6.

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

Рисунок 2.3 Алгоритм работы при запросе главной страницы и авторизации в виде UML последовательности.

Рисунок 2.4 Алгоритм работы при запросе мастеров и записи к ним в виде UML последовательности.

Рисунок 2.5 Алгоритм работы при работе с отзывами в виде UML последовательности.

Рисунок 2.6 Алгоритм работы при запросе статистики посещения в виде UML последовательности.

2.3 Средства разработки

В качестве средства разработки и отладки программного решения серверной части выбрана специализированная свободная интегрированная для создания кода на языке PHP - IDE NetBeans. Эта среда имеет возможность полной интеграции с веб-стандартами, а также реализует полную поддержку технологий разработки HTML5, JavaScript и CSS3.

Эта среда бесплатная, т.е. каждый может её использовать для разработки программных решений и не платить создателям NetBeans.

Среда IDE NetBeans содержит инструмент Xdebug, который является отладчиком и позволяет выполнять следующие функции:

  • Наблюдение за переменными
  • Установка точек останова и просматривание выполнение кода в реальном времени
  • Переход к действиям объявления, типам и файлам
  • Использование глобального пути включения (include)

DB.php

Controll.php

Запрос

Auth.php

Otzivi.php

Masters.php

Zapis.php

Statistik.php

Рисунок 2.7 Дерево вызова программных модулей.

В качестве локального сервера выбран локальный сервер WAMP (общепринятая аббревиатура Windows, Apache, MySQL и PHP) – Денвер. Этот набор инструментов содержит интерпретатор PHP, библиотеки работы с базой данных, дистрибутив систему управления данными MySQL и веб-сервер Apache.

Этот набор разработчика является бесплатным и доступным средством для начинающих разработчиков, но вместе с тем, те средства, которые в него входят позволяют решать широкий круг задач, включая создание высоконагруженных сайтов.

Также вместе с MySQL поставляется панель администрирования phpMyAdmin, которая позволяет полностью проводить администрирования созданной базы данных.

Этапы реализации функционала серверной части представлены на рисунках 2.8-2.10.

На рисунке 2.8 представлен процесс разработки и тестирования модуля Controll.php. Этот модуль отвечает за обработку вызовов пользователей и в зависимости от них реализует логику всего приложения. Часть некоторых функций приведены в Приложении 1. Более подробно список используемых функций данным модулем приведен в таблице 2.2.

Рисунок 2.8 Проектирование модуля Controll.php.

Модуль «Отзывы» позволяет просматривать и добавлять ответы на отзывы от посетителей. У посетителей на каждого мастера есть возможность оставить отзыв. Такая возможность позволяет другим посетителям сделать правильный выбор, а для мастеров служит дополнительным стимулом делать свою работу лучше. На рисунке 2.9 представлен процесс разработки и тестирования модуля Otzivi.php. Часть некоторых функций приведены в Приложении 1.

Для администратора ведется статистика посещения пользователями сайта. Эта информация важна, так как дает представление откуда пришли посетители, сколько раз и в какой промежуток времени они приходили. Можно понять какой самый популярный мастер, а какой наименее. На рисунке 2.10 представлен процесс разработки и тестирования модуля Statistik.php. Часть некоторых функций приведены в Приложении 1.

Рисунок 2.9 Проектирование модуля Otzivi.php.

Рисунок 2.10 Проектирование модуля Statistik.php.

Таблица 2.2 Список некоторых функций, используемых модулями

Модуль

Перечень некоторых используемых функций

Auth.php

isUserExists – проверка, есть ли такой пользователь

createUser – добавление нового пользователя

Otzivi.php

setNewOtziv – добавление отзыва конкретному мастеру

setAnswer – добавление ответа администратором

Masters.php

getListMaster – вывод всех доступных мастеров

Zapis.php

setUsluga – добавление записи об предстоящей услуге

getFreeTime – узнать свободное время конкретного мастера

Statistik.php

setStatis – внесение сведений о статистике посещения

DB.php

insertNewUser – добавление нового пользователя

Controll.php

checkIsAdmin – проверка роль=администратор

checkFreeTime – составление графика когда свободен конкретный мастер

Глава 3. Описание структуры базы данных и ее функций.

3.1 Моделирование базы данных

В качестве инструмента для проектирования базы данных был выбран онлайн сервис dbdesigner.net. Данный сервер имеет бесплатный план подписки и позволяет создавать ER схему и по ней генерировать исходный код для большого количества разных СУБД.

В данной работе используется СУБД MySQL. Необходимые таблицы были созданы в онлайн сервисе и экспортированный в файл сценария. Исходный код таблиц представлен в Приложении 3.

Рисунок 3.1 ER-модель базы данных

Процесс создания базы данных представлен на рисунках 3.2-3.5

Рисунок 3.2 Создание базы данных Парикмахерская

Рисунок 3.3 Импортирование таблиц из файла SQL

Рисунок 3.4 Отчет об успешном импорте

Рисунок 3.5 Проверка одной из таблиц

3.2 Структура таблиц базы данных

В таблицах 3.1-3.6 приведено описание структуры каждой из таблиц. Таблица 3.1 «Мастера» служит хранилищем данных о мастерах, работающих в парикмахерской.

Таблица 3.1 Структура таблицы «Мастера»

Поле

Тип данных

Сведения

Назначение

ID

INT

PRIMARY KEY

Уникальный ключ таблицы

id_users

INT

FOREIGN KEY

Ключ к таблицы Пользователи

Name

VARCHAR(255)

Имя для отображения н сайте

isDostupen

BINARY

Флаг. Работает ли сейчас мастер

foto_filename

VARCHAR(255)

Адрес фото на сайте

opisanie

VARCHAR(255)

Описание услуг которые может выполнить мастер

Таблица 3.2 хранит сведения о статистики посещения любыми пользователями сайта и содержит информацию о браузере и времени запроса.

Таблица 3.3 хранит сведения об отзывах оставленный зарегистрированными посетителями. Также в этой же таблице – ответ администратора.

Таблица 3.4 хранит сведения о пользователях. Это основная таблица в базе данных. Она содержит сведения о логине и пароле, а также флаги что это за пользователь, какая у него роль. Дополнительно здесь же пишутся сведения о контактах: е-майл и номер телефона.

Таблица 3.2 Структура таблицы «Статистика»

Поле

Тип данных

Сведения

Назначение

ID

INT

PRIMARY KEY

Уникальный ключ таблицы

browser

VARCHAR(255)

Имя браузера

ip

VARCHAR(30)

Адрес в сети интернет откуда был запрос страницы

host

VARCHAR(255)

Адрес запрошенной страницы

Refferer

VARCHAR(255)

Откуда пришел посетитель

time

VARCHAR(30)

Время захода на сайт

request

VARCHAR(255)

Отклик сайта

Таблица 3.3 Структура таблицы «Отзывы»

Поле

Тип данных

Сведения

Назначение

ID

INT

PRIMARY KEY

Уникальный ключ таблицы

ID_master

INT

FOREIGN KEY

Ключ к таблицы Пользователи

ID_user

INT

FOREIGN KEY

Ключ к таблицы Пользователи

stars

INT

Оценка мастера пользователем

text_user

VARCHAR(255)

Текст отзыва оставленный пользователем

text_admin

VARCHAR(255)

Текст ответа администратора

Таблица 3.4 Структура таблицы «Пользователи»

Поле

Тип данных

Сведения

Назначение

ID

INT

PRIMARY KEY

Уникальный ключ таблицы

login

VARCHAR(30)

Логин пользователя

password

VARCHAR(32)

Пароль пользователя

hash

VARCHAR(32)

Хэш код пароля

isAdmin

BOOLEAN

Флаг. Администратор

isMaster

BOOLEAN

Флаг. Мастер

name

VARCHAR(50)

Имя на сайте

e-mail

VARCHAR(50)

Контакты. е-майл

telefon

VARCHAR(50)

Контакты. Телефон

Таблица 3.5 хранит записи о посещениях сайта зарегистрированными пользователями. Благодаря ей, можно узнать, как долго конкретный пользователь проводит времени на сайте.

Таблица 3.6 хранит сведения о записях на услуги. В ней ключ мастера и пользователя, а также время на которое записан посетитель и сколько денег он заплатил за оказанные услуги.

Таблица 3.5 Структура таблицы «Посещения сайта»

Поле

Тип данных

Сведения

Назначение

ID

INT

PRIMARY KEY

Уникальный ключ таблицы

id_users

INT

Ключ к таблицы Пользователи

time_in

VARCHAR(32)

Время захода на сайт

time_long

VARCHAR(32)

Время когда в последний раз была запрошена любая страничка

browser

INT

FOREIGN KEY

Ключ к таблицы Статистика

Таблица 3.6 Структура таблицы «Запись на услуги»

Поле

Тип данных

Сведения

Назначение

ID

INT

PRIMARY KEY

Уникальный ключ таблицы

master_id

INT

FOREIGN KEY

Ключ к таблицы Мастера

datetime

VARCHAR(50)

Время на которое осуществлена запись н услугу

datetime_end

VARCHAR(50)

Сколько времени будет длиться сеанс

id_user

BOOLEAN

FOREIGN KEY

Ключ к таблицы Пользователи

money

FLOAT

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

  • Запрос на добавление нового пользователя
  • Запрос на проверку есть ли данный пользователь
  • Запрос на добавление статистики посещения пользователем.
  • Запрос на список мастеров.
  • Запрос на добавление отзыва конкретному мастеру.
  • Запрос на свободное время у мастера
  • Запрос на добавления времени записи на услугу

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

Глава 4. Описание структуры клиентской части.

Клиентская часть приложения, это то, что будет отображено в браузере для клиента. Посетитель вводит в адресную строку путь до сайта или переходит по внешней ссылке и попадает на главную страницу.

Структура сайта представлена на рисунке 4.1.

Рисунок 4.1. Структура клиентской части

Сайт сверстан с адаптивным дизайном, это значит, что он автоматически подстраивает контент под разрешение того экрана на котором он отображается. На рисунке 4.9 показана главная страница, так, как если бы она была открыта на смартфоне. На рисунке 4.2 та же самая страница показана с экрана монитора стационарного компьютера.

На рисунках 4.3 – 4.8 показаны различные страницы сайта. Навигация по ним возможна с использованием меню, которое расположено в верхней части страницы. На каждой страницы за исключением главное, есть «хлебные крошки» ссылки на страницы, открытые перед выбранной.

Рисунок 4.2 Главная страница сайта.

Рисунок 4.3 Страница контакты.

Рисунок 4.4 Страница услуги.

Рисунок 4.5 Страница цены.

Рисунок 4.6 Страница акции.

Рисунок 4.7 Страница цены.

Рисунок 4.8 Страница портфолио.

Рисунок 4.9 Главная страница на экране смартфона.

В качестве инструмента для создания клиентской части сайта, был выбран программный пакет – Adobe Dreamweaver 20. Это программа имеет развитый графический интерфейс и позволяет быстро разрабатывать страницы и наполнять их контентом.

На Рисунка 4.10, 4.11 показан процесс создания страниц сайта.

Рисунок 4.10 Создание главное страницы сайта.

Рисунок 4.11 Редактирование страницы портфолио.

4.1 Описание интерфейса «Обычный пользователь».

Типовые сценарии посещения сайта могут быть такими:

  • Пользователь заходит на сайт, узнает номер телефона и звонит администратору
  • Пользователь заходит на сайт, находит нужного мастера и записывается к нему на прием
  • Пользователь заходит на сайт, находит раздел отзывы, читает из и принимает решение посетить одну из парикмахерских
  • Пользователь заходит на сайт, знакомится с ценами и звонит администратору чтобы выбрать удобное время для записи на прием.
  • Пользователь посещает одну из парикмахерских, затем заходит на сайт, и оставляет свой отзыв на конкретного мастера.

Особенностью режима Обычный пользователь является не возможность вносить изменения во внутреннюю работу сайта. Такому пользователю доступно лишь оставлять отзывы и запрашивать запись на конкретное время к конкретному мастеру. Эти возможности открываются после регистрации на сайте. Форма регистрации показана на рисунке 4.13.

Рисунок 4.13 Форма регистрации.

4.2 Описание интерфейса «Администратор».

Для администраторов сайта разработана специальная страница, доступная по адресу admin.php. Данная страница отличается от главной страницы сайта более простым дизайном.

Особенностью данной страницы является доступ к возможностям редактирования работающих мастеров, формирования ответов на отзывы, просмотр и редактирование расписания мастеров.

Чтобы попасть на эту страницу необходимо пройти авторизацию и ввести пароль и логин администратора.

Рисунок 4.12 Страница администратора.

4.3 Инструкция пользователя.

Разработанный сайт имеет понятный интерфейс и материалистический дизайн. В целом и большинства пользователей сети интернет не должно возникнуть трудностей с навигацией по сайту и получением контента.

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

Заключение

В данной курсовой работе реализован процесс создания полноценного сайта для сети парикмахерских «Парикмахерская №1». Он оттестирован и готов к размещению в сети интернет.

В первой части работы был разработан дизайн сайта и рассмотрены требования к веб серверу. Также описан бизнес процесс взаимодействия сотрудников и клиентов.

Во второй части спроектирована серверная часть и описано дерево вызова программных модулей. Представлено древо функций.

Третья часть была посвящена разработке структуры и реализация базы данных с использованием СУДБ MySQL.

Цели, которые были поставлены для решения задачи данной работы, такие как разработка дизайна сайта, создание базы данных, программирование внутренней логики сайта и тестирование работы на локальном сервере выполнены в полном объеме.

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

Список литературы

1. Мейер, Б. Инструменты, алгоритмы и структуры данных / Б. Мейер. - 2-е изд., испр. - М. : Национальный Открытый Университет «ИНТУИТ», 2016.

2. Савельева, Н.В. Язык программирования PHP / Н.В. Савельева. - 2-е изд., испр. - М. : Национальный Открытый Университет «ИНТУИТ», 2016

3. Прохоренок, Н. HTML, JavaScript, PHP и MySQL. Джентльменский набор Web-мастера / Н. Прохоренок. - СПб.: БХВ - Петербург., 2010. - 900 с.

4. Мазуркевич, А. PHP: настольная книга программиста / А. Мазуркевич. - М.: Новое знание, 2003. - 480 с.

5. Богданов, М.Р. Перспективные языки веб-разработки / М.Р. Богданов. - 2-е изд., испр. - М. : Национальный Открытый Университет «ИНТУИТ», 2016

6. http://biblioclub.ru/index.php?page=book&id=428953

7. Никсон, Р. Создаем динамические web-сайты с помощью PHP, MySQL и JavaScript / Р. Никсон. - П.: Питер, 2011. - 496 с.

8. PHP, SQL [Electronic resource] / блог. - Россия, 2010.: http://phpsql.ru/.

9. Томсон, Л. Разработка Web-приложений на РНР и MySQL/ Л. Томсон. - М.: ДиаСофтЮП, 2003. - 672 с.

10. PHPForum [Электронный ресурс] /форум.- Россия, 2003. - Режим доступа: http://phpforum.ru. - Дата доступа: 09.02.2012.

11. Харрис, Э. PHP/MySQL для начинающих / Э. Харрис. - М.: Кудиц - образ, 2005.

12. Парк, Д. PHP и MySQL. Библия программиста / Д. Парк, С. Суэринг. - Диалектика, 2010. - 912 с.

Приложение 1. Код серверной части

$link=mysqli_connect("localhost", "mysql_user", "mysql_password", "testtable");

if(isset($_POST['submit']))

{

$err = [];

if(!preg_match("/^[a-zA-Z0-9]+$/",$_POST['login']))

{

$err[] = "Логин может состоять только из букв английского алфавита и цифр";

}

if(strlen($_POST['login']) < 3 or strlen($_POST['login']) > 30)

{

$err[] = "Логин должен быть не меньше 3-х символов и не больше 30";

}

$query = mysqli_query($link, "SELECT user_id FROM users WHERE user_login='".mysqli_real_escape_string($link, $_POST['login'])."'");

if(mysqli_num_rows($query) > 0)

{

$err[] = "Пользователь с таким логином уже существует в базе данных";

}

if(count($err) == 0)

{

$login = $_POST['login'];

$password = md5(md5(trim($_POST['password'])));

mysqli_query($link,"INSERT INTO users SET user_login='".$login."', user_password='".$password."'");

header("Location: login.php"); exit();

}

else

{

print "<b>При регистрации произошли следующие ошибки:</b><br>";

foreach($err AS $error)

{

print $error."<br>";

}

}

}

?>

<form method="POST">

Логин <input name="login" type="text" required><br>

Пароль <input name="password" type="password" required><br>

<input name="submit" type="submit" value="Зарегистрироваться">

function generateCode($length=6) {

$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHI JKLMNOPRQSTUVWXYZ0123456789";

$code = "";

$clen = strlen($chars) - 1;

while (strlen($code) < $length) {

$code .= $chars[mt_rand(0,$clen)];

}

return $code;

}

$link=mysqli_connect("localhost", "mysql_user", "mysql_password", "testtable");

if(isset($_POST['submit']))

{

$query = mysqli_query($link,"SELECT user_id, user_password FROM users WHERE user_login='".mysqli_real_escape_string($link,$_POST['login'])."' LIMIT 1");

$data = mysqli_fetch_assoc($query);

if($data['user_password'] === md5(md5($_POST['password'])))

{

$hash = md5(generateCode(10));

if(!empty($_POST['not_attach_ip']))

{

$insip = ", user_ip=INET_ATON('".$_SERVER['REMOTE_ADDR']."')";

}

mysqli_query($link, "UPDATE users SET user_hash='".$hash."' ".$insip." WHERE user_id='".$data['user_id']."'");

setcookie("id", $data['user_id'], time()+60*60*24*30, "/");

setcookie("hash", $hash, time()+60*60*24*30, "/", null, null, true); // httponly !!!

header("Location: check.php"); exit();

}

else

{

print "Вы ввели неправильный логин/пароль";

}

}

<form method="POST">

Логин <input name="login" type="text" required><br>

Пароль <input name="password" type="password" required><br>

Не прикреплять к IP(не безопасно) <input type="checkbox" name="not_attach_ip"><br>

<input name="submit" type="submit" value="Войти">

</form>

$link=mysqli_connect("localhost", "mysql_user", "mysql_password", "testtable");

if (isset($_COOKIE['id']) and isset($_COOKIE['hash']))

{

$query = mysqli_query($link, "SELECT *,INET_NTOA(user_ip) AS user_ip FROM users WHERE user_id = '".intval($_COOKIE['id'])."' LIMIT 1");

$userdata = mysqli_fetch_assoc($query);

if(($userdata['user_hash'] !== $_COOKIE['hash']) or ($userdata['user_id'] !== $_COOKIE['id'])

or (($userdata['user_ip'] !== $_SERVER['REMOTE_ADDR']) and ($userdata['user_ip'] !== "0")))

{

setcookie("id", "", time() - 3600*24*30*12, "/");

setcookie("hash", "", time() - 3600*24*30*12, "/", null, null, true); // httponly !!!

print "Хм, что-то не получилось";

}

else

{

print "Привет, ".$userdata['user_login'].". Всё работает!";

}

}

else

{

print "Включите куки";

}

setcookie("id", "", time() - 3600*24*30*12, "/");

setcookie("hash", "", time() - 3600*24*30*12, "/",null,null,true); // httponly !!!

header("Location: /"); exit;

<form method="POST">

Логин <input name="login" type="text" required><br>

Пароль <input name="password" type="password" required><br>

Не прикреплять к IP(не безопасно) <input type="checkbox" name="not_attach_ip"><br>

<input name="submit" type="submit" value="Войти">

</form>

Приложение 2.Код алгоритма работы сайта в виде UML последовательности

@startuml

actor Администратор

actor Пользователь

collections Сайт

database База_данных

== Главная ==

Пользователь->Сайт: Делает запрос \nглавной страницы

Сайт->Пользователь: Главная страница

== Авторизация ==

Пользователь->Сайт: Делает запрос \nрегистрация или авторизация

Сайт->База_данных: Запись в таблицу Пользователи \nили запрос есть ли такой

База_данных->Сайт: Авторизован/Зарегистрирован\n/Ошибка/Есть такой

Сайт->Пользователь: Сообщение об успехе/не удаче

== Мастера ==

Пользователь->Сайт: Делает запрос \nдоступные мастера

Сайт->Сайт: Пользователь авторизован? \nесли нет, то идет на страницу \nавторизации/регистрации

Сайт->База_данных: Запрос в таблицу Мастера

База_данных->Сайт: Список

Сайт->Пользователь: Выдача списка \nдоступных мастеров

... Запись ...

Пользователь->Сайт: Желает записаться \nна услуги к мастеру

Сайт->База_данных: Запись в таблицу график Мастера

База_данных->Сайт: Результат дейстия

Сайт->Пользователь: Сообщение об успехе/не удаче

== Отзывы ==

Пользователь->Сайт: Делает запрос \nдоступные мастера

Сайт->Сайт: Пользователь авторизован? \nесли нет, то идет на страницу \nавторизации/регистрации

Сайт->База_данных: Запрос в таблицу Мастера

База_данных->Сайт: Список

Сайт->Пользователь: Выдача списка \nдоступных мастеров

... Пользователь...

Пользователь->Сайт: Желает сделать отзыв \nна услуги к мастеру

Сайт->База_данных: Запись в таблицу отзыв

База_данных->Сайт: Результат дейстия

Сайт->Пользователь: Сообщение об успехе/не удаче

... Администратор...

Администратор->Сайт: Желает просмотреть \nотзывы без ответа

Сайт->База_данных: Запрос н обработанных отзывов

База_данных->Сайт: Результат дейстия

Сайт->Администратор: Список не обработанных отзывов

Администратор->Сайт: Ответ на отзыв

Сайт->База_данных: Запись нового ответа

База_данных->Сайт: Результат дейстия

Сайт->Администратор: Сообщение об успехе/не удаче

== Статистика посещения ==

Администратор->Сайт: Желает просмотреть \nстатистику посещений сайта \nили конкртного мастера

Сайт->Сайт: Пользователь авторизован? \nесли нет, то идет на страницу \nавторизации/регистрации

Сайт->База_данных: Запрос в таблицы статистика

База_данных->Сайт: Результат дейстия

Сайт->Администратор: Список посещений

Приложение 3. Код SQL для создания таблиц

CREATE TABLE `Master` (

`ID` INT NOT NULL,

`id_users` INT NOT NULL,

`name` VARCHAR(255) NOT NULL,

`isDostupen` BINARY NOT NULL,

`foto_filename` VARCHAR(255) NOT NULL,

`opisanie` VARCHAR(255) NOT NULL,

PRIMARY KEY (`ID`)

);

CREATE TABLE `Statistik` (

`ID` INT NOT NULL AUTO_INCREMENT,

`browser` TEXT(255) NOT NULL,

`ip` VARCHAR(15) NOT NULL,

`host` VARCHAR(255) NOT NULL,

`refferer` VARCHAR(255) NOT NULL,

`time` VARCHAR(30) NOT NULL,

`request` VARCHAR(255) NOT NULL,

PRIMARY KEY (`ID`)

);

CREATE TABLE `Otzivi` (

`ID` INT NOT NULL AUTO_INCREMENT,

`ID_master` INT NOT NULL,

`ID_user` INT NOT NULL,

`stars` INT NOT NULL,

`text_user` VARCHAR(255) NOT NULL,

`text_admin` VARCHAR(255) NOT NULL,

PRIMARY KEY (`ID`)

);

CREATE TABLE `users` (

`ID` INT NOT NULL AUTO_INCREMENT,

`login` VARCHAR(30) NOT NULL,

`password` VARCHAR(32) NOT NULL,

`hash` VARCHAR(32) NOT NULL DEFAULT '''',

`isAdmin` BOOLEAN NOT NULL,

`isMaster` BOOLEAN NOT NULL,

`name` VARCHAR(50) NOT NULL,

`e-mail` VARCHAR(50) NOT NULL,

`telefon` VARCHAR(50) NOT NULL,

PRIMARY KEY (`ID`)

);

CREATE TABLE `users_visit` (

`id` INT NOT NULL AUTO_INCREMENT,

`id_users` INT NOT NULL,

`time_in` VARCHAR(30) NOT NULL,

`time_long` VARCHAR(30) NOT NULL,

`browser` INT NOT NULL,

PRIMARY KEY (`id`)

);

CREATE TABLE `Zapis` (

`id` INT NOT NULL AUTO_INCREMENT,

`master_id` INT NOT NULL,

`datetime` VARCHAR(50) NOT NULL,

`datetime_end` VARCHAR(50) NOT NULL,

`id_user` INT(50) NOT NULL,

`money` FLOAT NOT NULL,

PRIMARY KEY (`id`)

);

ALTER TABLE `Master` ADD CONSTRAINT `Master_fk0` FOREIGN KEY (`id_users`) REFERENCES `users`(`ID`);

ALTER TABLE `Otzivi` ADD CONSTRAINT `Otzivi_fk0` FOREIGN KEY (`ID_master`) REFERENCES `users`(`ID`);

ALTER TABLE `Otzivi` ADD CONSTRAINT `Otzivi_fk1` FOREIGN KEY (`ID_user`) REFERENCES `users`(`ID`);

ALTER TABLE `users_visit` ADD CONSTRAINT `users_visit_fk0` FOREIGN KEY (`id_users`) REFERENCES `users`(`ID`);

ALTER TABLE `users_visit` ADD CONSTRAINT `users_visit_fk1` FOREIGN KEY (`browser`) REFERENCES `Statistik`(`ID`);

ALTER TABLE `Zapis` ADD CONSTRAINT `Zapis_fk0` FOREIGN KEY (`master_id`) REFERENCES `Master`(`ID`);

ALTER TABLE `Zapis` ADD CONSTRAINT `Zapis_fk1` FOREIGN KEY (`id_user`) REFERENCES `users`(`ID`);

Приложение 4. Код CSS табилицы стилей

*

{

margin: 0;

padding: 0;

}

body

{

font-family: arial,sans-serif;

}

.table-wrapper

{

margin: 30px;

border: solid 1px Silver;

padding: 10px;

display: inline-block;

}

.table-wrapper table

{

}

.table-wrapper table thead tr td div

{

color: #666;

text-align: center;

overflow: hidden;

background-color: White;

margin: 1px;

cursor: pointer;

padding: 8px 0;

font-size: 9pt;

font-weight: bold;

overflow: hidden;

border: solid 1px silver;

width: 80px;

background: url(../images/grad.png) left bottom repeat-x;

}

.table-wrapper table thead tr td div:hover

{

color: #555;

border-color: #bfbfbf;

background: url(../images/gradRev.png) left bottom repeat-x;

}

.table-wrapper table thead tr td.hovered div

{

color: #444;

}

.table-wrapper table thead tr td div.selected, .table-wrapper table thead tr td div.selected:hover

{

background: url(../images/ggrad.png) left -2px repeat-x;

border-color: #b7c4df;

color: #444;

}

.table-wrapper table tbody tr td div

{

border: solid 1px #ddd;

height: 25px;

cursor: pointer;

margin: 1px;

}

.table-wrapper table tbody tr td.hovered div

{

border-color: #ccc;

background: url(../images/ggrad2.png) left bottom repeat-x;

}

.table-wrapper table tbody tr td div.selected, .table-wrapper table tbody tr td div.selected:hover

{

background: url(../images/ggrad.png) left -2px repeat-x;

border-color: #b7c4df;

}

.table-wrapper table tbody tr td div:hover

{

border-color: #ccc;

background: url(../images/ggrad2.png) left bottom repeat-x;

}

.table-wrapper table tbody tr td div.selected:hover

{

}

.table-wrapper table tbody tr td:first-child div

{

padding: 1px 3px;

vertical-align: top;

font-size: 9pt;

cursor: default;

text-align: right;

margin: 0;

border: solid 1px White;

font-weight: bold;

color: #777;

}

.table-wrapper table tbody tr.hovered td:first-child div

{

color: #333;

border-color: White;

background: none;

}

.table-wrapper table tbody tr td:first-child div:hover

{

color: #777;

}

.ResultsHolder input

{

margin: 10px 40px;

}

.ResultsHolder #output

{

font-family: Courier New;

font-size: 10px;

padding: 20px;

}

Приложение 5. Код JS Пользовательские скрипты

(function($) {

$(function() {

$('table').wrap('<div class="table-wrapper"></div>');

var $body = $(document.body),

$html = $(document.documentElement),

$portf = $('.portfolio-main .wrapper-picture-mobile .dooble-bl'),

isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);

function menuWidth() {

var winWidth = window.matchMedia('only screen and (min-width : 768px)').matches,

MenuUl = $('.wrapper-top-menu .top-menu'),

count_li = MenuUl.find('> li').length-1;

if ( winWidth && count_li ) {

var width_li = 0, menuTWidth = MenuUl.width();

MenuUl.find('> li').each(function() {

width_li += Math.ceil($(this).outerWidth());

});

if ( menuTWidth < width_li ) {

MenuUl.append("<li class='popup_menu'><a href='javascript:void(0);'>...</a><ul class='level-2'></ul></li>");

menuTWidth -= Math.ceil(MenuUl.find('> li.popup_menu').outerWidth());

for ( var i = count_li; menuTWidth < width_li; i-- ) {

width_li -= MenuUl.find('> li:not(popup_menu)').eq(i).outerWidth();

MenuUl.find('> li.popup_menu > ul').prepend(MenuUl.find('> li:not(popup_menu)').eq(i));

}

}

}

}

$(window).on('load resize', function() {

menuWidth();

});

var cntGroup = 2;

divsArr = $portf.get();

for(var i = 0; i < $portf.length; i += cntGroup){

$(divsArr.slice(i,i+cntGroup)).wrapAll('<div class="port"></div>');

}

// Отзывы

var slider_click = $('.reviews-block .review').length > 2 ? true : false;

if (slider_click) {

$('.reviews-wrapper .reviews-block').css('padding-bottom','60px');

}

for ($rw = 0; $rw < $('.site-container .owl-review').length; $rw++) {

if ($('.owl-review').eq($rw).find('.review').length > 1) {

$('.owl-review').eq($rw).owlCarousel({

responsiveClass:true,

loop: true,

responsive: {

768: {

nav: slider_click,

items: 2,

dots: false,

center: false,

mouseDrag: slider_click,

touchDrag: slider_click

},

0: {

nav: true,

items: 1,

center: true,

mouseDrag: true,

touchDrag: true

}

}

});

}

}

// Портфолио

for ($sl = 0; $sl < $('.site-container .wrapper-picture-mobile').length; $sl++) {

if ($('.wrapper-picture-mobile').eq($sl).find('.port').length > 1) {

$('.wrapper-picture-mobile').eq($sl).owlCarousel({

nav: true,

items: 1,

center: true,

mouseDrag: true,

touchDrag: true,

loop: true

});

}

}

////

// Top Menu

$('.top-menu').on('click', 'li.s3-menu-allin-has > a', function(cl) {

if (isMobile) {

if (!$(this).parent().hasClass('popup_menu') && ( $(this).hasClass('s3-menu-allin-open') || $(this).parent().hasClass('s3-menu-allin-active') ) ) {

document.location.href = $(this).attr('href');

} else {

cl.preventDefault();

}

}

});

$('.top-menu').on('click', '> li.popup_menu > a', function(cls){

$body.offset().on('click touchstart', function() {

console.log(123);

});

cls.preventDefault();

});

$('.open-mobile-menu').on("click", function(){

setTimeout(function() {

$pos_m = $(window).scrollTop();

$html.css('top',-$pos_m);

$('.mobile-menu').addClass('opened');

$html.addClass('overflowHidden');

});

});

$('.close-menu').on("click", function(){

$('.mobile-menu').removeClass('opened');

$html.removeClass('overflowHidden').removeAttr('style');

$(window).scrollTop($pos_m);

});

$body.on("click touchstart", function(event){

if ($(event.target).closest(".mobile-menu").length) return;

if ($('.mobile-menu').hasClass('opened')) {

$('.mobile-menu').removeClass('opened');

$html.removeClass('overflowHidden').removeAttr('style');

$(window).scrollTop($pos_m);

}

});

// Top Menu End

// Service addClass

var indexService = 0;

$('.service-blocks .service-bl').each(function() {

indexService++;

if (indexService < 3) {

$(this).addClass("left-img");

} else if (indexService == 4) {

indexService = 0;

}

});

// Service addClass

$(window).on('resize load', function() {

if ($(this).width() > 380) {

setTimeout(function() {

$('.service-bl .body-service').height($('.service-bl .img-service img').innerHeight()-14);

});

} else {

$('.service-bl .body-service').removeAttr('style');

}

});

// POPUP FORM ///

$('.popup-form-inner .close-form').on('click', function() {

$('.popup-form-wrapper').fadeOut().removeClass('opened');

$html.removeClass('overflowHidden');

$(window).scrollTop($pos);

});

$('.button_form a').on('click', function(event) {

$pos = $(window).scrollTop();

$html.css('top',-$pos);

$('.popup-form-wrapper').fadeIn().addClass('opened').offset({top: $pos, left: 0});

$html.addClass('overflowHidden');

event.preventDefault();

});

$html.on('keyup', function(event) {

if ($('.popup-form-wrapper').hasClass('opened') && event.keyCode == 27) {

$('.popup-form-wrapper').fadeOut().removeClass('opened');

$(this).removeClass('overflowHidden').removeAttr('style');

$(window).scrollTop($pos);

}

});

$body.on('click touchstart', function(a) {

if ($(a.target).closest('.popup-form-inner').length || $(a.target).closest('.button_form a').length) return;

if ($('.popup-form-wrapper').hasClass('opened')) {

$('.popup-form-wrapper').fadeOut().removeClass('opened');

$html.removeClass('overflowHidden').css('top',-$pos).removeAttr('style');

$(window).scrollTop($pos);

}

});

// POPUP FORM ///

});

})(jQuery);

function DayClick(dayNum, obj) {

if ($(obj).hasClass('selected') && ($('.table-wrapper table tbody tr td.d' + dayNum + ' div.selected').length)) {

$('.table-wrapper table tbody tr td.d' + dayNum + ' div').removeClass('selected');

$(obj).removeClass('selected');

}

else {

$('.table-wrapper table tbody tr td.d' + dayNum + ' div').addClass('selected');

$(obj).addClass('selected');

};

}

$(document).ready(function() {

$('.table-wrapper table tbody tr .d0').hover(

function() { $('.table-wrapper table thead tr td.d0').addClass('hovered') },

function() { $('.table-wrapper table thead tr td.d0').removeClass('hovered') });

$('.table-wrapper table thead tr .d0').hover(

function() { $('.table-wrapper table td.d0').addClass('hovered') },

function() { $('.table-wrapper table td.d0').removeClass('hovered') })

.click(function() { DayClick('0', this) });

$('.table-wrapper table tbody tr .d1').hover(

function() { $('.table-wrapper table thead tr td.d1').addClass('hovered') },

function() { $('.table-wrapper table thead tr td.d1').removeClass('hovered') });

$('.table-wrapper table thead tr .d1').hover(

function() { $('.table-wrapper table td.d1').addClass('hovered') },

function() { $('.table-wrapper table td.d1').removeClass('hovered') })

.click(function() { DayClick('1', this) });

$('.table-wrapper table tbody tr .d2').hover(

function() { $('.table-wrapper table thead tr td.d2').addClass('hovered') },

function() { $('.table-wrapper table thead tr td.d2').removeClass('hovered') });

$('.table-wrapper table thead tr .d2').hover(

function() { $('.table-wrapper table td.d2').addClass('hovered') },

function() { $('.table-wrapper table td.d2').removeClass('hovered') })

.click(function() { DayClick('2', this) });

$('.table-wrapper table tbody tr .d3').hover(

function() { $('.table-wrapper table thead tr td.d3').addClass('hovered') },

function() { $('.table-wrapper table thead tr td.d3').removeClass('hovered') });

$('.table-wrapper table thead tr .d3').hover(

function() { $('.table-wrapper table td.d3').addClass('hovered') },

function() { $('.table-wrapper table td.d3').removeClass('hovered') })

.click(function() { DayClick('3', this) });

$('.table-wrapper table tbody tr .d4').hover(

function() { $('.table-wrapper table thead tr td.d4').addClass('hovered') },

function() { $('.table-wrapper table thead tr td.d4').removeClass('hovered') });

$('.table-wrapper table thead tr .d4').hover(

function() { $('.table-wrapper table td.d4').addClass('hovered') },

function() { $('.table-wrapper table td.d4').removeClass('hovered') })

.click(function() { DayClick('4', this) });

$('.table-wrapper table tbody tr .d5').hover(

function() { $('.table-wrapper table thead tr td.d5').addClass('hovered') },

function() { $('.table-wrapper table thead tr td.d5').removeClass('hovered') });

$('.table-wrapper table thead tr .d5').hover(

function() { $('.table-wrapper table td.d5').addClass('hovered') },

function() { $('.table-wrapper table td.d5').removeClass('hovered') })

.click(function() { DayClick('5', this) });

$('.table-wrapper table tbody tr .d6').hover(

function() { $('.table-wrapper table thead tr td.d6').addClass('hovered') },

function() { $('.table-wrapper table thead tr td.d6').removeClass('hovered') });

$('.table-wrapper table thead tr .d6').hover(

function() { $('.table-wrapper table td.d6').addClass('hovered') },

function() { $('.table-wrapper table td.d6').removeClass('hovered') })

.click(function() { DayClick('6', this) });

$('.table-wrapper table tr').hover(

function() { $(this).addClass('hovered') },

function() { $(this).removeClass('hovered') });

$('.table-wrapper table tbody tr td div').click(

function() { $(this).toggleClass('selected') });

});

function SubmitSchedule() {

var XMLSchedule = "<week>";

for (var d = 0; d < 7; d++) {

XMLSchedule += '<d id="' + d + '">'

for (var h = 7; h < 21; h++) {

if ($('.table-wrapper table tbody tr.h' + h + ' td.d' + d + ' div').hasClass('selected')) {

XMLSchedule += '<h v="' + h + '">1</h>';

}

else {

XMLSchedule += '<h v="' + h + '">0</h>';

};

}

XMLSchedule += '</d>';

}

XMLSchedule += "</week>";

$('#output').text(XMLSchedule);

}