CMS – content management system, обычно переводится как "система управления содержимым (сайта)". Возможно, вы слышали о таких широко распросранённых CMS, как Joomla, Битрикс. Создав собственную CMS, вы сможете понять, как работают другие, научитесь видеть их внутренние достоинства и недостатки. А несложные сайты (вроде блога с комментариями) вы сможете создавать прямо на своей CMS, которая позволит вам легко редактировать содержимое сайта, делать резервные копии, переносить файлы сайта и базу данных (БД) с одного хостинга на другой.
Для работы вам понадобятся следующие инструменты:
Notepad++ (на Windows), Kate или Geany (на Linux, MaxOS);Apache с подключенным в виде модуля PHP;mysql;Firefox.Вам не нужна будет громоздкая система разработки (IDE), весь код вашей CMS не превысит 100 килобайт (несколько файлов php, css, js).
Веб-сервер и ), а для Linux набор пакетов LAMP (MAMP, XAMP для MacOS). Если вы не сможете это сделать самостоятельно, используя компьютер и Интернет, вам, скорее всего, пока рано изучать данный курс.
Курс рассчитан на людей, знакомых со спецификациями HTML5, CSS2 и с основами программирования на PHP, Javascript, с работой в phpMyAdmin и составлением простых sql-запросов. Нужны также будут начальные знания английского языка – чтобы с помощью словаря разбирать, что значит "affected rows", "deprecated", или "alter table files add primary key ...".
В мире веб существуют сотни CMS, фреймворков и прочих "библиотек", и число их постоянно растёт. Потому что каждый человек, создавший хоть один сайт, обязательно задумается: нельзя ли в следующий раз избежать многочисленных трудов и создать новый сайт, взяв из старого сайта нечто существенное и слегка подправив?
Что общего у блога, сайта доставки суши и сайта школьного расписания? Обнаружив это общее, мы сможем значительно ускорить создание следующего сайта (например, landing-page для продажи воздушных шариков).
Любой сайт состоит из ):
<!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Астрология</title> <link rel="stylesheet" href="site.css" type="text/css"> <script type="text/javascript" src="site.js"></script> </head> <body> <p><img src="files/img1.jpg" />Гадание по кофейной гуще</p> <p><img src="files/img2.jpg" />Оптом, в розницу и на экспорт</p> </body>
– и использовать его для создания любой страницы любого сайта, подставляя вместо слов "Астрология" и "Гадание по кофейной гуще" другие слова (и копируя на место картинок img1.jpg и img2.jpg другие файлы). В этом случае каждая страница сайта будет реально существующим html-файлом, и вы сможете менять этот текст, редактировать его. То есть это уже будет что-то вроде системы управления содержанием.
Но работать в такой системе не очень удобно:
Notepad++);html-тэги;html-файл к себе на комьютер, отредактировать его, а потом загрузить обратно на сервер по ftp-протоколу (то есть не через браузер, а с помощью отдельной специальной программы).Идея CMS как раз в том и состоит, чтобы вы могли менять содержимое своего сайта, используя только браузер, без дополнительных программ и сложных манипуляций с файлами.
Здесь возникает две разные задачи:
html-код.Для загрузки файлов на сервер используют html-формы. Браузер передаёт с помощью такой формы запрос, к которому присоединяет выбранный вами (на вашем компьютере) файл. Запрос в соответствии с протоколом HTTP должен быть "POST". Сервер без помощи специальных языков программирования (php, java, python) не сможет поместить отправленный вами файл в нужную папку.
Теоретически существует ещё возможность отправлять на веб-сервер файлы методом PUT (которые, например, http-сервер Nginx может получать и распеределять по папкам самостоятельно, без использования Php), но такой возможности (отправлять файлы методом PUT) пока нет у самих html-форм, поэтому мы будем исходить только из использования метода POST.
Это значит, что у работы на "чистом html" нет перспектив и нам сразу же понадобится php. А чтобы соединять разные тексты с одним и тем же повторяющимся фрагментом html, нужно будет хранить тексты отдельно от фрагментов html (называемых обычно шаблонами). Хранить тексты можно просто в отдельных файлах, но база данных (Mysql) намного удобнее.
Листинг 1.1 был достаточно прост, но дальше вам понадобится проверять работу каждого фрагмента кода в реальных условиях, отлаживать программу. Поэтому сразу создадим эти реальные условия (или убедимся, что они созданы). Если вы работаете на (либо http://localhost:8080/), а файлы для работы сайта (php, js, css) вы должны будете копировать в папку c:/usbws/root (или другую папку, в которую вы установили USBWebserver). Вместе с USBWebserver, кстати, должен сразу установиться phpMyAdmin.
Если вы работаете под Линуксом, папка для вашего сайта, скорее всего, будет расположена по адресу /home/bitrix/www (хотя, возможно, и в домашней директории пользователя – это будет зависеть от настроек веб-сервера), а phpMyAdmin вы должны будете установить самостоятельно (например, командой консоли sudo apt-get install phpmyadmin).
Вся дальнейшая работа технически будет выглядеть так:
php, js, css в папке вашего сайта;index3.php) и смотрите, какие изменения произошли на сайте вследствие вашей работы с кодом;От этих двух добавлений ():
<?php
$title = 'Астрология';
$img1 = 'img1.jpg';
$html1 = 'Гадание по кофейной гуще';
$img2 = 'img2.jpg';
$html2 = 'Гадание по кофейной гуще';
$page = <<<PAGE
<!DOCTYPE html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>{$title}</title>
<link rel="stylesheet" href="site.css" type="text/css">
<script type="text/javascript" src="site.js"></script>
</head>
<body>
<p><img src="files/{$img1}" />{$html1}</p>
<p><img src="files/{$img2}" />{$html1}</p>
</body>
PAGE;
print $page;
?>
А если использовать базу данных, тогда ещё сложнее (листинг 1.3 ):
<?php
$id = $_GET['id'];
$link = mysqli_connect("localhost", "unsinn", "go68dbs", "unsinn");
$sql = "SELECT * FROM `mypages` where id = " . (int) $id;
$result = mysqli_query($link, $sql);
$row = mysqli_fetch_assoc($result);
$page = <<<PAGE
<!DOCTYPE html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>{$row['title']}</title>
<link rel="stylesheet" href="site.css" type="text/css">
<script type="text/javascript" src="site.js"></script>
</head>
<body>
<p><img src="files/{$row['img1']}" />{$row['html1']}</p>
<p><img src="files/{$row['img2']}" />{$row['html2']}</p>
</body>
PAGE;
print $page;
?>
Создайте в Папке сайта файл с именем index0.php и сохраните в этом файле приведённый код. На нашем учебном хостинге он выглядит так: index0.php?code. Обратите внимание на строчку:
$link = mysqli_connect("localhost", "unsinn", "go68dbs", "unsinn");
Слово "), найдите там раздел для выполнения ):
CREATE DATABASE IF NOT EXISTS `unsinn` ; GRANT ALL PRIVILEGES ON `unsinn` . * TO 'unsinn'@'localhost' IDENTIFIED BY 'go68dbs'; flush PRIVILEGES;
И ещё мы должны создать в базе данных ):
CREATE TABLE IF NOT EXISTS `mypages` ( `id` int(7) NOT NULL AUTO_INCREMENT, `title` text NOT NULL, `html1` text NOT NULL, `html2` text NOT NULL, `img1` varchar(99) NOT NULL, `img2` varchar(99) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; insert ignore into `mypages` (`id`, `title`, `html1`, `html2`, `img1`, `img2`) values (1, 'Астрология', 'Гадание по кофейной гуще', 'Оптом, в розницу и на экспорт', 'img1.jpg', 'img2.jpg'), (2, 'Воздушные шарики', 'Синие, белые и зелёные', 'Круглые, квадратные, треугольные', 'img1.jpg', 'img2.jpg');
Этот код надо также вставить в поле для sql-запросов в phpMyAdmin и выполнить запрос. Сохраним этот код в файл source1.sql, чтобы потом не писать каждый раз код, а просто ссылаться на этот файл (и вы тоже сохраните его у себя на компьютере).
Обратите внимание на строчку , а мы на сервере извлечём этот параметр ("3") и используем его для получения нужной строчки таблицы с помощью sql-запроса ("SELECT * FROM `mypages` where id = 3"). То есть мы именно так пока организуем связь запросов клиента и ответов сервера – через параметр id.
Размер нашего кода по сравнению с первоначальным чистым , http://localhost/index0.php?id=19. Налицо явная экономия, казалось бы.
Но вот с этого места и начинается "экспонента" сложностей. Наш Код в файле index0.php в таком виде попросту не будет работать. Вам это утверждение может показаться слишком сильным. Проверим.
Notice: Undefined index: id in /home/bitrix/www/index0.php on line 2.mypages 20 строк, как планировали) – возможно, это будут "кракозябры" или вопросики из-за несоответствия кодировки.php не очень древний).Вот с последнего и начнём. В работе сайта желательно предусмотреть два состояния: рабочее (для пользователей) и режим отладки. Пользователи не должны видеть всякие ):
<?php
$debug = true;
error_reporting(E_ALL);
ini_set('log_errors', true);
ini_set('display_errors', $debug);
date_default_timezone_set('Asia/Yakutsk');
//...
?>
Добавьте этот код к первоначальному . Чтобы при добавлении параметра "code" можно было видеть php-код файла (вместо результата работы программы) мы использовали дальше следующий фрагмент:
<?php
//...
if (array_key_exists('code', $_GET)) {
header('Content-Type: text/html; charset=UTF-8');
$code = file_get_contents(__FILE__);
highlight_string($code);
exit;
}
//...
?>
Это было самое простое. Дальше будет всё хуже и хуже. Каждый раз, когда вы обращаетесь к переменной по её имени (например, к переменной $debug в конструкции ini_set('display_errors', $debug);), вы должны ожидать неприятностей разного рода:
Все эти случаи надо предусматривать и "обрабатывать" – закладывать в программу возможность исправить ситуацию до такой степени, чтобы обычный пользователь ничего не заподозрил (а думал, что так оно и планировалось), или доводить ситуацию хотя бы до внятного сообщения об ошибке (в режиме debug).
Проблема 2 – одна из самых неприятных: в php действует "незаметное" приведение типов к нужному (в данном месте кода), и программист быстро привыкает особо не обращать внимания на типы, что иногда внезапно вылезает боком (например, при попытке обратиться к элементу массива по индексу – $arr[1] – когда переменная $arr не является массивом).
Проблема 1 уже встретилась нам при обращении к странице index1.php без параметра ("Notice: Undefined index: id..."). Проблема 3 – при попытке вызвать страницу с id > 20. Решение этих проблем не является тривиальным, так как зависит совсем не от программиста. Как именно следует их решать, должен сказать владелец сайта, но он не подозревает об этих проблемах, и возникает замкнутый круг, разорвать который можно только путём долгих и мучительных переговоров – поэтому на большинстве сайтов эти проблемы вообще не решаются никак (либо решаются путём банального отключения сообщения об ошибках).
Проблему 1 мы решим с помощью следующей конструкции (листинг 1.7 ):
<?php $id = isset($_GET['id']) ? $_GET['id'] : 1; ?>
Если посетитель сайта не обращается к нашей таблице явно по id, нам всё равно нужно выдать ему какие-то значения по умолчанию, введённые владельцем сайта в таблицу под тем номером, который он сообщит программисту. Мы делаем допущение, что этот номер – 1, то есть обратившись к адресу index1.php без параметра id, пользователь увидит запись с id = 1.
До сих пор мы неявно исходили из того, что и файлы php, и данные в Mysql, и обмен данными между Php и Mysql используют одну и ту же кодировку символов – utf-8. Вряд ли на самом деле это так (особенно если вы работаете под Windows). Поэтому вы вполне можете видеть в своих файлах вопросики вместо русских букв (или "кракозябры").
Мы указали в мета-тэге html-страницы кодировку UTF-8 явно. То же самое надо сделать ещё в трёх местах:
Mysql ($link = mysqli_connect("localhost", "admin", "adminadmin@", "unsinn");): $sql = 'set names utf8'; mysqli_query($link, $sql); (для Mysql надо писать именно так, без дефиса: 'utf8');Php: setlocale(LC_ALL, 'ru_RU.UTF-8', 'ru_RU'); (надо указать в начале файла php);http-ответа сервера для браузера: header('Content-Type: text/html; charset=UTF-8');И ещё одна деталь: вы пишете php-код в текстовом редакторе, и надо сохранять ваши файлы тоже с использованием кодировки utf-8.
Это не строгое требование: вы вполне можете вместо utf-8 использовать национальную кодировку (например, cp1251), но тогда обязательно нужно проследить, чтобы во всех перечисленных местах была указана именно эта кодировка.
Примерно так: .
Тогда вместо вопросиков вы сможете увидеть русские буквы:
Мы пытаемся создать универсальный фрагмент кода (для будущей CMS), который можно было бы использовать для создания новых сайтов. Это значит, достаточно типична будет ситуация, когда нужной нам таблицы Mysql ещё не существует (или она пуста). Создателю нового сайта (кто бы он ни был – программист или астролог) будет не очень приятно видеть малопонятное сообщение mysqli_connect_error или вовсе пустую страницу. Мы должны обработать эту ситуацию и либо сообщить пользователям, что это новый сайт, либо (в режиме debug) дать подсказку программисту.
1. Мы берём данные из массива :
<?php
//...
$row = !$debug
? array(
'title' => 'Новый сайт',
'html1' => 'Это новый сайт',
'html2' => 'Его содержание coming soon',
'img1' => 'img1.jpg',
'img2' => 'img2.jpg',
)
: array(
'title' => 'Новый сайт',
'html1' => 'Если вы видите эту надпись, значит, вам нужно
а) ввести правильные значения для Пользователя (вместо unsinn),
Пароля (вместо go68dbs) и БД (вместо второго unsinn) для подключения mysql
в строке кода mysqli_connect("localhost", "unsinn", "go68dbs", "unsinn");',
'html2' => 'б) в выбранной базе данных вам нужно создать таблицу
и наполнить её данными, выполнив sql-запрос из файла
<a href="source1.sql">source1.sql</a>,
'img1' => 'img1.jpg',
'img2' => 'img2.jpg',
);
$link = mysqli_connect("localhost", "my_user", "my_password", "my_bd");
if (mysqli_connect_errno()) {
if ($debug) print('Соединение не удалось: ' . mysqli_connect_error());
}
else {
$sql = "SELECT * FROM `mypages` where id = " . (int) $id;
if ($result = mysqli_query($link, $sql)) {
$row = mysqli_fetch_assoc($result);
}
}
//...
?>
Не забудьте убедиться, что в папке вашего сайта есть файл .
Выше мы привели код запроса Mysql для создания нужной нам базы данных ("unsinn"). Но мы живём в реальном мире; для веб-программиста это означает: мы зависим от особенностей конкретного хостинга – не всегда можем создать БД с нужным нам именем, и иногда должны использовать то, что есть. Поэтому мы даём рекомендацию программисту ввести другие имя пользователя mysql и пароль (предполагая, что он не смог выполнить приведённую выше инструкцию по созданию собственной БД).
2. Мы добрались до ошибки (п. 4 : в коде всё корректно, mysql работает, таблица mypages есть, но в ней нет записи с номером 21. Что в этом случае выдаст наш код? Пустую страницу. Казалось бы, ничего страшного. Откуда вообще пользователь возьмёт число 21 (или 221)?
В вебе как нигде действует принцип Мэрфи: если неприятность может случиться, она случается. Вы глазом моргнуть не успеете, как анализатор сайта webmaster.yandex.ru покажет, что у вас на сайте не 20, а 20000 страниц с одинаковым содержанием. Потому что вы нарушили протокол. Это тоже не вопрос программиста, а совершенно уже непонятно чей вопрос, поэтому протокол HTTP нарушается на сайтах сплошь и рядом.
В самом начале рассуждений о "фрагменте общего кода" мы упустили из виду одну очень важную деталь – общими для большинства сайтов являются не только doctype, но и так называемые "заголовки HTTP". Вы легко можете увидеть их в отладчике любого современного браузера. Когда наш сайт состоял из файлов html, нам можно было не думать о заголовках, так как их автоматически отправляет веб-сервер Apache: если файл index.html существует, Apache вместе с содержимым этого файла отправляет заголовок "HTTP/1.1 200 OK", если файл не существует, Apache отправляет заголовок "HTTP/1.1 404 Not Found".
Наша ситуация с id > 20 как бы говорит нам, что "файл не существует", нет таких данных. Но реальный-то файл index1.php есть, и Apache всё равно отправляет заголовок "HTTP/1.1 200 OK" – и так для всех 20000 пустых страниц, которые поисковики исправно пытаются индексировать, а потом заносят ваш сайт в чёрный список.
Решение: мы должны проверить, существует ли запись с номером 21, не пуста ли она; и если существует, заполнить массив $row её значениями, а если она пуста, так и сказать об этом пользователю – дескать, 404 not found, извини:
<?php
//...
if ($result = mysqli_query($link, $sql)) { //проверяем ошибки sql
if ($result->num_rows)
$row = mysqli_fetch_assoc($result);
else {
header('HTTP/1.1 404 Not Found'); //требуется протоколом
exit('404 Not Found'); //чтоб пользователь тоже видел
}
}
//...
?>
У объекта . Перепишите код в Папку вашего сайта, назовите его (чтобы убедиться, что получите ответ 404 not found).
Конечно, и в этом случае ничто не помешает вашему конкуренту отправить на Яндекс кучу ссылок, ведущих на несуществующие страницы вашего сайта. Но разница будет в том, что ваш сайт теперь будет давать правильные ответы (404 – "Страница не существует"), и Яндекс не будет пытаться индексировать их содержание.
Наш фрагмент-шаблон вроде бы готов к размножению сайтов с невероятной скоростью. Осталась сущая мелочь – что делать, если владелец сайта всё-таки захочет поменять "гадание на кофейной гуще" на "гадание по картам Таро"? Предложить ему править ячейки таблиц в phpMyAdmin'е? или напрямую – писать sql-запросы? Вот с этого момента и начинается настоящая работа над CMS – создание редактора, в котором владелец сайта (неквалифицированный пользователь) мог бы редактировать тексты и добавлять и удалять страницы (т.е. строки в таблице mysql).
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.