Справочник телефонов на web-сервере.


31.07.2019

Всех приветствую. И так сегодня 11 июня 2019 года, и я начинаю проект онлайн телефонного справочника в своей организации. Давно эта идея витала в виде идеи, но я не решался её воплотить потому что не хватало знаний. Ну их всё еще конечно не хватает и приобретать буду по мере выполнения поставленной задачи. Суть в том, что я заведую телефонным справочником у себя в организации, и данный момент он существует в виде Excel файла. Это очень непрактично в плане мультидоступности как я бы сказал. Гораздо интереснее и безопаснее для самого контента если это будет web страница. В общем план такой – поднять виртуальную машину, на которой будет web сервер и база MySQL. Будет доступна главная Index страница для всех пользователей, а также дополнительная страница для администратора (edit.php), то есть меня, которая позволит вводить новые данные и редактировать уже существующие. Проект честно говоря для меня серьёзный, потому что придётся научится через PHP рулить базой MySQL, но будем пробовать узнавать новое вместе.

Начинаем мы с того что устанавливаем Ubuntu Server 18.04.2 на виртуальную машину. Задачи у сервера крайне скромные и поэтому ресурсов даём по минимуму:

CPU: одно ядро
RAM: 1024MB
Диск: 25GB
Как всегда, начинаем с того что обновим систему:
sudo apt update && sudo apt upgrade

Что будем ставить:
Web server: «Nginx»
СУБД: «MariaDB»
Управление БД: «phpMyAdmin»
FTP server: «vsftp»


Установим Nginx:
Добавим необходимые репозитории, где содержаться последние версии пакетов:
sudo su
add-apt-repository ppa:ondrej/php
add-apt-repository ppa:nginx/stable
apt update
apt install nginx -y
apt install php7.2-cli php7.2-fpm php7.2-curl php7.2-gd php7.2-mysql php7.2-mbstring zip unzip -y
Сделаем резерв конфиг файла nginx сайта по умолчанию:
mv /etc/nginx/sites-available/default /etc/nginx/sites-available/default.dist
Создадим свой:
nano /etc/nginx/sites-available/default

Вот с таким содержимым

server {
 listen 80;
 root /var/www/default;
 index index.php index.html index.htm;
 server_name example.com www.example.com;
 location / {
     try_files $uri $uri/ /index.html;
 }
 error_page 404 /404.html;
 error_page 500 502 503 504 /50x.html;
 location = /50x.html {
    root /usr/share/nginx/www;
 }
 location ~ .php$ {
     try_files $uri =404;
     fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
     fastcgi_index index.php;
     fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
     include fastcgi_params;
     }
}

Напоминаю работу с редактором "nano":
CTRL+O – сохранить.
Затем CTRL+X – выход.

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

mkdir /var/www/default
nano /var/www/default/index.php
Содержимое файла пока оставим пустое.

Ну а далее ставим MariaDB. Это собственно и есть MySQL в современной обвёртке. Казалось бы, а зачем вообще база данных для справочника телефонов организации, меня тут спросили. А дело в том, что нам надо реализовать занесение данных, которые будут отображаться на «php» странице, и это можно сделать через базу данных, за одно и изучить команды MySQL.

Установка MariaDB:
Добавляем репозиторий:
sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
sudo add-apt-repository 'deb [arch=amd64,arm64,ppc64el] http://mirror.timeweb.ru/mariadb/repo/10.3/ubuntu bionic main'
Обновим данные:
apt update

Установка:
apt install mariadb-server mariadb-client -y
Во время установки нужно будет задать пароль для пользователя root, для доступа к БД.
Перезапускаем mysql:
/etc/init.d/mysql restart
и пробуем подключиться:
mysql -u root -p
жмём CTRL+D для выхода.

Хорошо мы установили обработчик баз данных. Теперь установим замечательный инструмент для управления этими базами данных – «phpMyAdmin». Переходим на сайт и копируем ссылку загрузки с кнопки:


Далее переходим в каталог куда хотим скачать архив:
cd /tmp
затем даём команду wget и подставляем ей адрес ссылки, скопированный из кнопки:
wget https://files.phpmyadmin.net/phpMyAdmin/4.9.0.1/phpMyAdmin-4.9.0.1-all-languages.zip
затем распакуем:
unzip phpMyAdmin-*.zip
Создадим каталог, в который нужно бюджет переместить содержимое архива:
mkdir /var/www/default/phpmyadmin
mv phpMyAdmin-4.9.0.1-all-languages/* /var/www/default/phpmyadmin/
Далее скопируем пример конфига phpMyAdmin и отредактируем его:
cp /var/www/default/phpmyadmin/config.sample.inc.php /var/www/default/phpmyadmin/config.inc.php
nano /var/www/default/phpmyadmin/config.inc.php
Тут нужно задать значение для параметра $cfg['blowfish_secret'].
Значением должен быть случайный набор симоволов, например:
$cfg['blowfish_secret'] = 'ldkflkaf88fa99sdjkdjlasflafkk33939rfklkaf034rnnkvkk';
CTRL+O – сохранить.
Затем CTRL+X – выход.

Сделаем пользователя и группу «www-data» владельцем файлов и папок:

chown -R www-data:www-data /var/www

Перезапускаем nginx и php-fpm:

/etc/init.d/nginx restart
/etc/init.d/php7.2-fpm restart

Теперь если у вас есть уже заготовленный сайт, самое время его скопировать в «/var/www/default/».
Для заливки файлов в каталог «/var/www/default/» лучше использовать FTP.

Поднимем FTP сервер:

Ставим vsftp и db-util.
sudo su
apt install vsftpd db5.3-util -y
Создадим папку и файл с нужными логинами и паролями, а также сразу зададим правильные разрешения на файл:
mkdir /etc/vsftpd
touch /etc/vsftpd/vsftpdusers
chmod 0600 /etc/vsftpd/vsftpdusers

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

nano /etc/vsftpd/vsftpdusers

Содержимое
ftpuser
321


Захешируем наш файл и отредактируем разрешения на полученный:

db5.3_load -T -t hash -f /etc/vsftpd/vsftpdusers /etc/vsftpd/users.db
chmod 0600 /etc/vsftpd/users.db

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

mv /etc/vsftpd.conf /etc/vsftpd.conf.dist
nano /etc/vsftpd.conf

Содержимое должно быть следующим:

Содержимое
listen=YES
anonymous_enable=NO
local_enable=YES
xferlog_enable=YES
user_sub_token=$USER
local_root=/var/www/
chroot_local_user=YES
hide_ids=YES
guest_enable=YES
guest_username=www-data
virtual_use_local_privs=YES
write_enable=YES
pasv_enable=YES
# Тут указываем реальный глобальный IP адрес если нужно
#pasv_address=4.3.2.1
pasv_max_port=20200
pasv_min_port=20400
pam_service_name=vsftpd.virtual
rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
ssl_enable=NO
connect_from_port_20=YES
xferlog_file=/var/log/vsftpd.log
xferlog_std_format=YES
idle_session_timeout=600
data_connection_timeout=120
ascii_upload_enable=YES
ascii_download_enable=YES
allow_writeable_chroot=YES
seccomp_sandbox=NO
local_umask=022


Обращаем внимание на:
local_root=/var/www/ - коревая папка, куда будут попадать пользователя, после подключения к серверу.
guest_username=www-data – имя реального пользователя, который будет виден системе, от его имени будут происходить все операции с файлами.
#pasv_address=1.2.3.4 – если у вас сервер за NAT, то тут нужно указать реальный, внешний адрес.

И остался последний шаг – создадим конфиг для pam.d, что бы наши виртуальные пользователи могли подключаться:
nano /etc/pam.d/vsftpd.virtual

Содержимое файла должно быть таким:
auth required pam_userdb.so db=/etc/vsftpd/users
account required pam_userdb.so db=/etc/vsftpd/users
session required pam_loginuid.so


Перезапускаем vsftpd, и можно пробовать подключаться.
/etc/init.d/vsftpd restart

Ну а далее, если вы всё-таки поднимаете сайт с ноля, то консоль сервера можно пока отложить. Как это сделать я ещё не знаю, но будем разбираться вместе.

И так, верстка странички:
В качестве основы будем использовать фреймворк mdbootstrap.com
Заходим на сайт и качаем «MDB-Free_4.8.2.zip»
Содержимое этого архива и есть заготовка сайта:
Я переименовал каталог в «telphp» и переместил из загрузок в рабочий каталог.

В моём случае – справочник — это таблица с шапкой в виде логотипа компании, ну и конечно нужно сделать чтобы при печати на бумагу всё было красиво.


Создадим базу данных:

Переходим на IP адрес сервера – <АДРЕС СЕРВЕРА>/phpmyadmin/
Авторизуемся через root и пароль который указали при установке MariaDB.


Жмём создать БД:


Создаём базу с именем «tel» c сопоставлением кодировки «utf8_general_ci» и далее создаём таблицу «teltable» с 11ю столбцами (у нас по задумке 10 столбцов в справочнике плюс одно поле для индекса):



Жмём вперёд и прописываем параметры для полей таблицы:


Жмём сохранить и наблюдаем готовую таблицу:


Может кто-то спросить, а зачем делать тип «VARCHAR» там, где только цифры, а потому что база не принимала 10и значное число номера мобильного телефона как число. И тип «binary» для текста пришлось применить чтобы сортировка по команде «order by» была корректная. Нам главное передать символы в переменную.


Теперь самое время поработать с «php» страницами:
Весь список «php» файлов в моём случае получился такой:


Вот так выглядит содержимое файла «index.php»

Вот так выглядит содержимое файла «edit.php»

Вот так выглядит содержимое файла «add.php»
add.php – это код обработки запроса на добавление данных в базу данных.

Вот так выглядит содержимое файла «configDB.php»
configDB.php – это код, в котором мы прописываем авторизацию для подключения к БД.

Вот так выглядит содержимое файла «ordbyfirma.php»
ordbyfirma.php - это страничка, которая отображает справочник с упорядочиванием по алфавиту столбца «подразделение».

А это модифицированный «edit.php» в который добавлена возможность удалить запись, посредством кода из «delete.php».

Вот так выглядит содержимое файла «delete.php».

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


При работе были использованы материалы из данных источников:
Как настроить веб сервер на Ubuntu 18.04 - www.mytechnote.ru
Изучение PHP PDO (базы данных) за час! Создание приложения «Список дел» - Канал Гоша Дударь



UPD от 20.06.2023.
Дополнение внёс Савицкий Савелий Владимирович. За что ему боольшое спасибо! Добавляем возможность редактирования строки.

Правки к статье

В пункте про установку MariaDB стоит указать что с новыми версиями ПО во время установки СУБД больше не предлагается создать пароль для root пользователя, а поэтому требуется после установки пакета отдельно прописать sudo mysql_secure_installation. После этого нас спросят, есть ли у нас установленный пароль root пользователя, нужно нажать Enter (что значит нет пароля), так как речь идёт не про суперпользователя Linux, а про такового в СУБД. Затем нам предложат непосредственно обозначить этот самый пароль, что мы и делаем. Ещё будет много чего предлагаться, ну я везде «y» проставил, вроде ничего плохого не случилось (там MariaDB отключает анонимных пользователей, перезагружает таблицы привилегий и что-то ещё). Ещё могут посыпаться ошибки разных сортов из-за того, что СУБД не включается автоматически после установки, потому нужно всегда проверять её статус: sudo systemctl status mariadb и если там сказано, что она inactive(dead), то нужно её запустить: sudo service mysql start. Вроде какая-то дурацкая мелочь, но я на неё попался и долго разбирался из-за чего у меня ничего не выходит.


При добавлении некоторых репозиториев, указанных в статье, Linux почему-то ругался на отсутствие неких release files (или как-то так, не помню). Мне кажется, что пакетный менеджер и так нормально справляется своими силами с установкой ПО без добавления сторонних репозиториев в рамках данного проекта, но это на Ваше усмотрение.


После фрагмента про поднятие FTP-сервера в статье идёт вот такое выражение: “Ну а далее, если вы всё-таки поднимаете сайт с ноля, то консоль сервера можно пока отложить. Как это сделать я ещё не знаю, но будем разбираться вместе.” Между предложениями явно не хватает чего-то в роде «Сейчас время заняться вёрсткой сайта», а то получается, что «я не знаю, как отложить консоль сервера».


Типы данных в базе нужно ставить VARCHAR с кодировкой utf8mb4_general_ci, чтобы не возникло пресловутой проблемы с вопросами в ромбиках при выводе данных из базы.

Внедрение редактирования строк в таблице

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



Первый файл будет представлять из себя HTML-форму, в которую в качестве значений полей будут выводиться данные из базы, а после их редактирования по нажатии кнопки «Сохранить» они будут направляться во второй файл -roweditscript.php, где, уже будучи обновлёнными, будут вноситься в базу. Приступим к реализации.

Для начала сверстаем первый файл. Как, я уже сказал, он будет представлять из себя HTML-форму, поэтому не забываем про стандартные теги (стили, бутстрап по желанию).



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



Разберём построчно: первая строка запрашивает файл “configDB.php”, который отвечает за получение доступа к базе через PDO. Затем мы получаем id строки, которую нам нужно отредактировать (предварительно, конечно, его передав из основного edit-файла). После этого формируем sql-запрос: выбрать (прочесть) всё (*) из таблицы `teltable`, где id равняется ?. Запрос вполне понятен и логичен, но может ввести в заблуждение вопросительный знак в конце. Дело в том, что он выступает в sql-запросе в роли «переменной-заглушки», так как в базе у нас переменной нет, а формируем мы запрос именно в базу, нужно пока оставить так, а далее в скрипте при исполнении запроса передать значение этой самой переменной. Далее в коде вполне стандартные строки: мы подготавливаем запрос (pdo->prepare), а затем исполняем, не забыв передать значение id, полученное в начале скрипта. Последняя строка отвечает за внесение полученных данных в переменную $value, притом в формате ассоциативного массива (массив, состоящий из пар ключ-значение, что-то в роде словарей в Python или других языках).

Теперь создадим форму. Мы можем без проблем мешать html-код с php, главное обрамлять первый в конструкцию echo.



В атрибутах тега 'form' нужно обязательно указать действие (атрибут action, что мы будем делать с данными): наш, пока нетронутый файл roweditscript.php, а также метод (атрибут method, пишем “post”). По желанию можно указать принимаемую кодировку: UTF-8 (атрибут accept-charset). Теги 'input' отвечают за поля ввода информации в форме. Здесь, в атрибутах, нужно указать имя, id поля, тип (везде “text”, кроме первого, позже объясню почему),подсказку, что нужно писать в поле (атрибут “placeholder”),а также значение (атрибут “value”, в котором мы указываем наше значение из массива $value, строго соблюдая синтаксис: двойные кавычки атрибута, одинарные кавычки, а затем точка переменной php; ключ значения в квадратных скобках, а затем в одинарных кавычках). Функция htmlspecialchars() нужна для корректного отображения кавычек и текста в них, что актуально как раз в поле фирмы и, возможно, отдела. Стоит также сказать про поле id. В нём указан тип “hidden”, что отличает его от всех остальных полей. Данный тип делает поле нередактируемым и спрятанным. Это сделано для того, чтобы мы смогли получить id строки в базе, которую нужно изменить, но не видели самого поля и не могли его редактировать, так как id должно оставаться уникальным во избежание ошибок.

Отлично! Первый файл у нас готов. Если вы правильно указали в базе типы данных и кодировки, то проблем на этом этапе быть не должно. Если они возникают с выводом данных, ещё раз перепроверьте кодировки, везде должен быть Юникод (utf8mb4_general_ci или utf8mb3_general_ci). Скриншот всего кода:



Теперь очередь php-скрипта, отвечающего за внесение полученных в форме данных в базу. Здесь нам не понадобятся html-теги вообще, голый php-код.



В начале заносим в переменные данные, полученные из формы, при помощи $_POST. В квадратных скобках - имя поля, которое мы указывали в атрибуте “name” тега 'input'. В конце фрагмента кода получаем доступ в базу, как делали ранее.

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



Формируем sql-запрос. Так как мы обновляем уже существующую запись, нам понадобится оператор UPDATE, а не INSERT. Запрос у нас таков: обновить таблицу `teltable` установить значение `familia` на :pfamilia, `name` на :pname и так далее. Здесь переменные, начинающиеся на :p служат теми самыми «переменными-заглушками», уже описанными ранее. Далее подготавливаем запрос и запрашиваем исполнение, не забывая заменить «заглушки», на реальные переменные из начала скрипта. В конце указываем страницу, на которую нас перекинет после исполнения кода. Если вам будет удобнее, можете указать edit-файл, а не дефолтный. Вот скриншот всего скрипта:



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

Вот так выглядит содержимое файла «rowedit.php»

Вот так выглядит содержимое файла «roweditscript.php»


Навигация: