Этот урок связан с проектом Строим свою CMS на PHP и MySQL

Строим свою CMS на PHP и MySQL. Часть 5

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

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

soursedemo

loginForm.php

Создаем папку с именем admin в каталоге нашего проекта  templates. В папке admin создаем файл loginForm.php:

<?php include "templates/include/header.php" ?>
 
      <form action="admin.php?action=login" method="post" style="width: 50%;">
        <input type="hidden" name="login" value="true" />
 
<?php if ( isset( $results['errorMessage'] ) ) { ?>
        <div class="errorMessage"><?php echo $results['errorMessage'] ?></div>
<?php } ?>
 
        <ul>
 
          <li>
            <label for="username">Username</label>
            <input type="text" name="username" id="username" placeholder="Your admin username" required autofocus maxlength="20" />
          </li>
 
          <li>
            <label for="password">Password</label>
            <input type="password" name="password" id="password" placeholder="Your admin password" required maxlength="20" />
          </li>
 
        </ul>
 
        <div class="buttons">
          <input type="submit" name="login" value="Login" />
        </div>
 
      </form>
 
<?php include "templates/include/footer.php" ?>

Эта страница содержит форму регистрации администратора, которая отправлет к admin.php?action=login. Форма содержит скрытое поле login, которое используетcя в функции login() для проверки факта отправки формы. Также здесь имеется область для любых сообщений об ошибках (таких, как неправильное имя пользователя или неправильный пароль) и поля для имени пользователя и пароля, и кнопка отправки формы.

Мы использовали некоторые атрибуты HTML5, такие как placeholder, required, autofocus и date для полей в наших формах. Такие атрибуты делают формы более удобными для использования, а также  сохраняют возможность для проверки необходимых значений в нашем коде PHP. Так как не все браузеры сейчас поддерживают данные атрибуты HTML5, то вы,       возможно, будете применять  JavaScript и/или PHP функции для проверки необходимых значений в серверной части.

 

listArticles.php

Сейчас создадим второй администраторский шаблон в вашей папке admin. Он называется listArticles.php:

<?php include "templates/include/header.php" ?>
 
      <div id="adminHeader">
        <h2>Widget News Admin</h2>
        <p>You are logged in as <b><?php echo htmlspecialchars( $_SESSION['username']) ?></b>. <a href="admin.php?action=logout"?>Log out</a></p>
      </div>
 
      <h1>All Articles</h1>
 
<?php if ( isset( $results['errorMessage'] ) ) { ?>
        <div class="errorMessage"><?php echo $results['errorMessage'] ?></div>
<?php } ?>
 
 
<?php if ( isset( $results['statusMessage'] ) ) { ?>
        <div class="statusMessage"><?php echo $results['statusMessage'] ?></div>
<?php } ?>
 
      <table>
        <tr>
          <th>Publication Date</th>
          <th>Article</th>
        </tr>
 
<?php foreach ( $results['articles'] as $article ) { ?>
 
        <tr onclick="location='admin.php?action=editArticle&amp;articleId=<?php echo $article->id?>'">
          <td><?php echo date('j M Y', $article->publicationDate)?></td>
          <td>
            <?php echo $article->title?>
          </td>
        </tr>
 
<?php } ?>
 
      </table>
 
      <p><?php echo $results['totalRows']?> article<?php echo ( $results['totalRows'] != 1 ) ? 's' : '' ?> in total.</p>
 
      <p><a href="admin.php?action=newArticle">Add a New Article</a></p>
 
<?php include "templates/include/footer.php" ?>

Этот шаблон выводит список статей для редактирования администратором. После отображения любых сообщений об ошибке или статусе мы проходим циклом по массиву объектов Article, который содержится в $results['articles'], и выводим на экран дату и название для каждой статьи в таблицу. К каждой строке таблицы добавляем событие JavaScript onclick, чтобы администратор мог щелчком мыши открыть статью для редактирования.

Шаблон также выводит общее количество всех статей и ссылку для добавления нового материала.

 

editArticle.php

Теперь создадим последний шаблон для администраторской части editArticle.php в папке нашего проекта admin:

<?php include "templates/include/header.php" ?>
 
      <div id="adminHeader">
        <h2>Widget News Admin</h2>
        <p>You are logged in as <b><?php echo htmlspecialchars( $_SESSION['username']) ?></b>. <a href="admin.php?action=logout"?>Log out</a></p>
      </div>
 
      <h1><?php echo $results['pageTitle']?></h1>
 
      <form action="admin.php?action=<?php echo $results['formAction']?>" method="post">
        <input type="hidden" name="articleId" value="<?php echo $results['article']->id ?>"/>
 
<?php if ( isset( $results['errorMessage'] ) ) { ?>
        <div class="errorMessage"><?php echo $results['errorMessage'] ?></div>
<?php } ?>
 
        <ul>
 
          <li>
            <label for="title">Article Title</label>
            <input type="text" name="title" id="title" placeholder="Name of the article" required autofocus maxlength="255" value="<?php echo htmlspecialchars( $results['article']->title )?>" />
          </li>
 
          <li>
            <label for="summary">Article Summary</label>
            <textarea name="summary" id="summary" placeholder="Brief description of the article" required maxlength="1000" style="height: 5em;"><?php echo htmlspecialchars( $results['article']->summary )?></textarea>
          </li>
 
          <li>
            <label for="content">Article Content</label>
            <textarea name="content" id="content" placeholder="The HTML content of the article" required maxlength="100000" style="height: 30em;"><?php echo htmlspecialchars( $results['article']->content )?></textarea>
          </li>
 
          <li>
            <label for="publicationDate">Publication Date</label>
            <input type="date" name="publicationDate" id="publicationDate" placeholder="YYYY-MM-DD" required maxlength="10" value="<?php echo $results['article']->publicationDate ? date( "Y-m-d", $results['article']->publicationDate ) : "" ?>" />
          </li>
 
 
        </ul>
 
        <div class="buttons">
          <input type="submit" name="saveChanges" value="Save Changes" />
          <input type="submit" formnovalidate name="cancel" value="Cancel" />
        </div>
 
      </form>
 
<?php if ( $results['article']->id ) { ?>
      <p><a href="admin.php?action=deleteArticle&amp;articleId=<?php echo $results['article']->id ?>" onclick="return confirm('Delete This Article?')">Delete This Article</a></p>
<?php } ?>
 
<?php include "templates/include/footer.php" ?>

Здесь выводится форма редактирования, которая используется как для создания новых статей, так и для редактирования существующих. Она отправляет к admin.php?action=newArticle, или к admin.php?action=editArticle, в зависимости от значения переменной $results['formAction']. Шаблон содержит также скрытое поле articleId, для отслеживания ID редактируемой статьи (если он есть).

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

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

Обратите внимание, что мы используем атрибут HTML5 formnovalidate для кнопки "Cancel". Данный атрибут указывает браузеру не проводить проверку формы, если пользователь нажал кнопку "Cancel".

 

Стили и логотип

Наша CMS практически готова, но для лучшего внешнего вида мы создаем набор правил CSS и сохраняем их в файле style.css в папке cms:

/* Стили для body and внешнего контейнера */

body {
  margin: 0;
  color: #333;
  background-color: #00a0b0;
  font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
  line-height: 1.5em;
}

#container {
  width: 960px;
  background: #fff;
  margin: 20px auto;
  padding: 20px;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  border-radius: 5px;
}


/* Логотип и нижний колонтитул */

#logo {
  display: block;
  width: 300px;
  padding: 0 660px 20px 0;
  border: none;
  border-bottom: 1px solid #00a0b0;
  margin-bottom: 40px;
}

#footer {
  border-top: 1px solid #00a0b0;
  margin-top: 40px;
  padding: 20px 0 0 0;
  font-size: .8em;
}


/* Заголвки */

h1 {
  color: #eb6841;
  margin-bottom: 30px;
  line-height: 1.2em;
}

h2, h2 a {
  color: #edc951;
}

h2 a {
  text-decoration: none;
}


/* Заголовки статей */

#headlines {
  list-style: none;
  padding-left: 0;
  width: 75%;
}

#headlines li {
  margin-bottom: 2em;
}

.pubDate {
  font-size: .8em;
  color: #eb6841;
  text-transform: uppercase;
}

#headlines .pubDate {
  display: inline-block;
  width: 100px;
  font-size: .5em;
  vertical-align: middle;
}

#headlines.archive .pubDate {
  width: 130px;
}

.summary {
  padding-left: 100px;
}

#headlines.archive .summary {
  padding-left: 130px;
}


/* Заголовок для страницы администратора */

#adminHeader {
  width: 940px;
  padding: 0 10px;
  border-bottom: 1px solid #00a0b0;
  margin: -30px 0 40px 0;
  font-size: 0.8em;
}


/* Стили для формы с цветным фоном, скругленными углами и тенью */

form {
  margin: 20px auto;
  padding: 40px 20px;
  overflow: auto;
  background: #fff4cf;
  border: 1px solid #666;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;  
  border-radius: 5px;
  -moz-box-shadow: 0 0 .5em rgba(0, 0, 0, .8);
  -webkit-box-shadow: 0 0 .5em rgba(0, 0, 0, .8);
  box-shadow: 0 0 .5em rgba(0, 0, 0, .8);
}


/* Задаем для элементов формы согласованные поля, отступы, и высоту строки */

form ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

form ul li {
  margin: .9em 0 0 0;
  padding: 0;
}

form * {
  line-height: 1em;
}


/* Метки полей */

label {
  display: block;
  float: left;
  clear: left;
  text-align: right;
  width: 15%;
  padding: .4em 0 0 0;
  margin: .15em .5em 0 0;
}


/* Поля */

input, select, textarea {
  display: block;
  margin: 0;
  padding: .4em;
  width: 80%;
}

input, textarea, .date {
  border: 2px solid #666;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;    
  border-radius: 5px;
  background: #fff;
}

input {
  font-size: .9em;
}

select {
  padding: 0;
  margin-bottom: 2.5em;
  position: relative;
  top: .7em;
}

textarea {
  font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
  font-size: .9em;
  height: 5em;
  line-height: 1.5em;
}

textarea#content {
  font-family: "Courier New", courier, fixed;
}
  

/* Рамка вокруг поля с фокусом ввода */

form *:focus {
  border: 2px solid #7c412b;
  outline: none;
}


/* Правильно заполненное поле имеет зеленый фон */

input:valid, textarea:valid {
  background: #efe;
}


/* Кнопки отправки */

.buttons {
  text-align: center;
  margin: 40px 0 0 0;
}

input[type="submit"] {
  display: inline;
  margin: 0 20px;
  width: 12em;
  padding: 10px;
  border: 2px solid #7c412b;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;  
  border-radius: 5px;
  -moz-box-shadow: 0 0 .5em rgba(0, 0, 0, .8);
  -webkit-box-shadow: 0 0 .5em rgba(0, 0, 0, .8);
  box-shadow: 0 0 .5em rgba(0, 0, 0, .8);
  color: #fff;
  background: #ef7d50;
  font-weight: bold;
  -webkit-appearance: none;
}

input[type="submit"]:hover, input[type="submit"]:active {
  cursor: pointer;
  background: #fff;
  color: #ef7d50;
}

input[type="submit"]:active {
  background: #eee;
  -moz-box-shadow: 0 0 .5em rgba(0, 0, 0, .8) inset;
  -webkit-box-shadow: 0 0 .5em rgba(0, 0, 0, .8) inset;
  box-shadow: 0 0 .5em rgba(0, 0, 0, .8) inset;
}


/* Таблицы */

table {
  width: 100%;
  border-collapse: collapse;
}

tr, th, td {
  padding: 10px;
  margin: 0;
  text-align: left;
}

table, th {
  border: 1px solid #00a0b0;
}

th {
  border-left: none;
  border-right: none;
  background: #ef7d50;
  color: #fff;
  cursor: default;
}

tr:nth-child(odd) {
  background: #fff4cf;
}

tr:nth-child(even) {
  background: #fff;
}

tr:hover {
  background: #ddd;
  cursor: pointer;
}


/* Окна для вывода статуса и сообщений об ошибках */

.statusMessage, .errorMessage {
  font-size: .8em;
  padding: .5em;
  margin: 2em 0;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  border-radius: 5px; 
  -moz-box-shadow: 0 0 .5em rgba(0, 0, 0, .8);
  -webkit-box-shadow: 0 0 .5em rgba(0, 0, 0, .8);
  -box-shadow: 0 0 .5em rgba(0, 0, 0, .8);
}

.statusMessage {
  background-color: #2b2;
  border: 1px solid #080;
  color: #fff;
}

.errorMessage {
  background-color: #f22;
  border: 1px solid #800;
  color: #fff;
}

Детального разбора кода CSS  мы делать не будем, так как наши уроки посвящены PHP и MySQL.

А в папке images в каталоге нашего проекта cms размещаем файл изображения logo.jpg :

Логотип

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

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: www.elated.com/articles/cms-in-an-afternoon-php-mysql/#step9
Перевел: Сергей Фастунов
Урок создан: 5 Декабря 2012
Просмотров: 39837
Правила перепечатки


5 последних уроков рубрики "PHP"

  • Фильтрация данных с помощью zend-filter

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

  • Контекстное экранирование с помощью zend-escaper

    Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак. В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.

  • Подключение Zend модулей к Expressive

    Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение. В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.

  • Совет: отправка информации в Google Analytics через API

    Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.

  • Подборка PHP песочниц

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

или авторизуйтесь, чтобы добавлять комментарии, оценивать уроки и сохранять их в личном кабинете
  • 5 Декабря 2012 19:30
    biohazardo
    Ну почему надо делать эти инклуды. Почему нельзя проводить все вызовы через index.php, и направлять запрос на другие части проекта из него? Почему нельзя сделать один общий шаблон, в центре которого выводить $content, который будет готовиться из других более мелких шаблонов? Почему нельзя сделать эту маленькую CMS по-человечески, а не лить кровавые слезы от удобства такого кода... Или вообще взять фреймворк, и показать как пишется серверная часть данной CMS за 15 минут.
    • 6 Декабря 2012 16:28
      gaparchi
      biohazardo, показали бы что нибудь, как оно делается правильно по MVC!!! За материал спасибо, Сайт визитку на такой CMS вполне можно реализовать, а главное спасибо за пояснение элементарных, но очень важных для понимания новичков основ. Сразу в фреймоврках Joomla или Wordpress не так еще и просто разобраться.
      • 10 Декабря 2012 10:44
        biohazardo
        Да просто изучить любой MVC-фреймворк, и понимание об этом подходе сразу придет.
  • 6 Декабря 2012 14:05
    Septor
    С общей точки зрения как обучающий материал по общим принципам, в общем не плохо, но само построение движка, "звиняйте хлопче", это..., не буду выражаться. :) Кто хочет научиться свои движки строить, лучше возьмите на вооружение Yii, Code Igniter, Kohana, Symfony или Zend фреймворк, или какой другой мини... Под них написана куча всяких статей вроде этой серии. Это будет не ещё одно изобретение велосипеда, и учиться программировать на них тоже можно без проблем, даже думаю будет легче и правильней.
  • 6 Декабря 2012 18:17
    andmak
    этому туториалу скоро три года исполнится :) такое старье стыдно выкладывать ....
  • 6 Декабря 2012 19:11
    creo_leader
    Спасибо за статью. Сделайте пожалуйста статью про безопасность в разработке движка, или дайте ссылки?
  • 7 Декабря 2012 02:33
    sew960i
    Вы не поняли...)) Это просто урок о том как НЕ нужно писать CMS)))
  • 7 Декабря 2012 12:32
    Septor
    Ещё один сайт, где с честной критикой борются. Стоило написать про кривые руки в подходе построения движка и шаблона, и комент потёрли. Автор..., я с 2005 года занимаюсь веб дизайном и вёрсткой, насмотрелся на разные движки и то как они сделаны, и если я говорю что вордпресовский стиль вёрстки шаблонов, это занятие мазахизмом, то это так и есть. ИМХО! Для примера возьмём стандартный шаблон вордпрес, где лежит 30 файлов-кусков, которые нужно открыть в редакторе и прыгать с файла на файл, в каждом из которых по несколько строк, что бы поправить что то. Это нормально? Сомневаюсь, особенно если учесть что всё это можно было свести максимум в 10 файлов, и основную вёрстку легко и просто править в одном файле а не в 5-10-и. А теперь мне скажи, как легче будет сверстать шаблон для твоего примера движка, если имеется готовый HTML шаблон. Мне что, этот шаблон из одного index.html резать на 20-30 кусков, что бы потом все их снова в index.php проинклюдить? Не старческий ли это маразм? Не проще ли все прописать в одном файле, учитывая что все нормальные редакторы сворачивают блоки вёрстки(кода), и всё удобно доступно?
  • 6 Января 2013 09:36
    Serg444
    Ребята, ключевое слово рубрики - уроки, а не "для профи", я когда, например, смог "улучшить" код с уроков Жени Попова испытал огромное удовлетворение и как следствие еще большее желание учиться. Вооот). Критикуйте не здесь битте. ps А так-то, Самохваловы, ВашЫ кодЫ идеальнЫ???
  • 20 Ноября 2013 23:56
    ever
    Как прикреплять изображения в статьи?)
  • 12 Декабря 2013 13:47
    niki_543
    Всем критикам могу сказать лишь одно! Критиковать без конкретных примерах просто и легко! Если уж вы такие умные и все знаете, напишите хоть одну полную обучающую статью и выложите на суд народа, а так болтать каждый "дурак" может! Автору же огромное спасибо! Единственный полный и доступный материал который получилось найти на просторах интернета, который доступно объясняет как все строится и делается! Огромное Вам спасибо!
  • Комментарий удален
    • 7 Декабря 2012 02:41
      sew960i
      та в мусорку такой кривой код... в черный список))
^ Наверх ^