Представляю сайт галереи фотографий. Создан с использованием языка программирования РНР, системы управления базой данных MySQL, популярного шаблона проектирования MVC, концепций объектно-ориентированного проектирования. Сайт содержит основные файлы с программным функционалом без стилей. Простейшая галерея без базы данных - Фотогалерея на скриптах PHP.
Функционал галереи
Разработка данного сайта является итоговым заданием книги Д. Ляпина А. Никитина "РНР - это просто".
Сайт выполнен на основе уроков 10 "Работа с базой данных", 11 "Архитектура сайта", 12 "Основы ООП". Реализованы следующие возможности для пользователей сайта:
Загрузка картинок на сервер с типами файлов 'jpg', 'jpeg', 'png', 'gif'. Появление картинки в галерее после загрузки без дополнительных переходов.
При загрузке фотографии автоматически создается ее уменьшенная копия с размером не более 200 пикселей по наибольшей стороне, которая и отображается в галерее.
В случае неудачи при загрузке фото, выводится сообщение пользователю о виде ошибки.
Просмотр галереи уменьшенных фотографий на одной странице. Можно выбрать режим просмотра в виде таблицы или списка.
При клике на маленькое изображение, открывается изображение полного размера в этом же окне браузера.
С осуществлением данных задач успешно справляются методы класса ModelGallery. Об этом и структуре сайта, построенной с учетом концепций MVC и ООП рассказывается ниже.
Структура галереи
Сайт галереи фотографий имеет структуру согласно архитектуре MVC и состоит из трех компонентов: модель, представление, контроллер.
Рис. 1. Структура сайта галереи фотографий
Подробное описание структуры.
Для хранения оригинальных фото и их уменьшенных копий созданы два каталога: img_big и соответственно img_small.
Сайт имеет две точки входа: index.php - для просмотра галереи, photo.рhр - для просмотра полноразмерной фотографии. Эти два файла являются представителями компонента архитектуры MVC Контроллерами.
Компонент MVC Модель представлен каталогом model. Здесь имеется три класса: ControllerGallery.рhр, используемый в контроллере index.рhр; Databas.php для создания соединения с базой данных и работы с ней; ModelGallery.рhр содержит набор необходимых для работы всего сайта методов.
Третий компонент MVC - Представление, состоит из четырех шаблонов, расположенных в каталоге templates: main.рhр - общий каркас страницы, отображающей информацию пользователю в браузере; content_index_list.рhр и content_index_table.рhр - подставляются в общий каркас и выводят пользователю галерею в виде, соответственно, списка или таблицы; content_photo.рhр - также подставляется в общий каркас и выводит пользователю полноразмерное изображение.
В базе данных lyapin хранятся записи о типе файла картинки, имени и адреса фото. Она состоит из двух таблиц: для больших изображений - big, маленьких - small.
Файлы кодов
Для просмотра кода требуется нажать на ссылку "Развернуть/свернуть код".
Главная страница сайта index.php обрабатывает запрос пользователя, выбирает шаблон, подставляет в шаблон необходимые данные из модели:
<?php
//Подключение библиотек
require_once('model/ModelGallery.php');
require_once('model/ControllerGallery.php');
//Создадим модели.
$modelGalleryIcon = new ModelGallery('img_small'); //для загрузки уменьшенных фото
$controllerGallery = new ControllerGallery();
//Загружаем фотографию, если пользователь отправил файл.
$controllerGallery->AddPhoto();
//Подготовка данных.
$photos = $modelGalleryIcon->Listing();
//Заголовок страницы.
$title = 'Галерея фотографий';
//Выбор шаблона содержимого.
$content = ($_GET['view'] == 'list') ? 'templates/content_index_list.php' : 'templates/content_index_table.php';
//Вывод HTML.
include 'templates/main.php';
?>
Страница контроллера для представления картинки оригинального размера photo.php:
<?php
//Подключение библиотек
require_once('model/ModelGallery.php');
$modelGalleryImage = new ModelGallery('img_big');
//Подготовка данных.
$i = $_GET['id'];
//Заголовок страницы.
$title = 'Просмотр фотографии';
//Выбор шаблона содержимого.
$content = 'templates/content_photo.php';
//Вывод HTML.
include 'templates/main.php';
?>
Код ControllerGallery.php из папки model:
<?php
require_once('ModelGallery.php');
class ControllerGallery
{
private $modelGalleryIcon;
private $modelGalleryImage;
public function __construct()
{
$this->modelGalleryIcon = new ModelGallery('img_small');
$this->modelGalleryImage = new ModelGallery('img_big');
}
public function AddPhoto()
{
/*Загружаем фотографию, если пользователь отправил файл.*/
if (isset($_FILES['file']))
{
ini_set('max_file_uploads', '3'); /*Установить максимальное количество загружаемых на сервер файлов за один раз*/
$valid_extensions = ['jpg', 'jpeg', 'png', 'gif'];
$myfile_name = $_FILES["file"]["name"];
$file_size = $_FILES["file"]["size"];
$error_flag = $_FILES["file"]["error"];
/*Присваиваем идентификатор добавления новой фотографии и
добавляем фото в директории*/
$message = $this->modelGalleryImage->Add(1, $valid_extensions);
// Выводим сообщение если ошибка
if ($message['error'])
{
print("Имя файла на компьютере пользователя: " . $myfile_name . "<br>");
print("Размер файла: " . $file_size . ' bytes' . "<br>");
echo $message['error'] . "<br>";
}
// Если ошибок не было
elseif($error_flag == 0)
{
/*добавление записей в таблицы больших и уменьшенных фото базы данных*/
$this->modelGalleryImage->AddImage('big');
$this->modelGalleryIcon->AddImage('small');
header('Location: index.php');
exit();
}
}
}
}
?>
Файл работы с базой данных Databas.php:
<?php
class DataBas
{
private $link;
public function __construct($server, $user, $password, $dbName)
{
$this->link = mysqli_connect($server, $user, $password, $dbName); // Открывает новое соединение с сервером MySQL и базой данных.
if (!$this->link)
{
die('Ошибка подключения (' . mysqli_connect_errno() . ') '
. mysqli_connect_error());
}
}
public function Execute($sql)
{
/*запрос к базе данных на добавление записи*/
mysqli_query($this->link, $sql);
/* закрываем соединение */
mysqli_close($this->link);
}
}
Файл с методами ModelGallery.php:
<?php
require_once ('Databas.php');
class ModelGallery
{
private $db;
public $dir; //каталог фото
public function __construct($dir)
{
$this->dir = $dir;
$this->db = new DataBas('127.0.0.1', 'root', '', 'lyapin');
}
//Функция возвращает объект фотографии (ассоциативный массив)
public function Item($i)
{
$photos = $this->Listing(); // Получаем массив фоток
$photo = $photos[$i];
return ($photo);
}
//Функция возвращает список фотографий
public function Listing()
{
$photos = scandir($this->dir, SCANDIR_SORT_NONE); // Получаем список файлов из этой директории без сортировки
$photos = $this->Excess($photos); // Удаляем лишние файлы c '.' ...
return $photos;
}
/* Функция для удаления лишних файлов: Текущий каталог и родительский пропускаем, не выводим файлы Thumbs.db */
private function Excess($files)
{
$result = [];
for ($i = 0; $i < count($files); $i++)
{
if ($files[$i] != "." && $files[$i] != ".." && $files[$i] != "Thumbs.db")
$result[] = $files[$i];
}
return $result;
}
//Функция возвращает путь к уменьшенному изображению.
public function Icon($i)
{
$photos = $this->Listing();
$destination = 'img_small' . '/' . $photos[$i];
return $destination;
}
//Функция возвращает путь к полноразмерному изображению.
public function Image($i)
{
$photo = $this->Item($i);
$destination = 'img_big' . '/' . $photo;
return $destination;
}
//Функция добавляет в галерею новую фотографию
public function Add($max_file_size, $valid_extensions)
{
setlocale(LC_ALL, 'ru_RU . UTF8');
$error = null;
$info = null;
$max_file_size *= 1048576; // перевод размера файла в b
if ($_FILES['file']['error'] === UPLOAD_ERR_OK)
{
// проверяем расширение файла
$file_extension = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
if (in_array(strtolower($file_extension), $valid_extensions))
{
// проверяем размер файла
if ($_FILES['file']['size'] < $max_file_size)
{
$myfile_name = $_FILES["file"]["name"];
$destination = $this->dir . '/' . $myfile_name;
if (!move_uploaded_file($_FILES['file']['tmp_name'], $destination))
/*Перемещает загруженный файл в новое место. Файловая система почему-то? сортирует файлы в директории по возрастанию*/
$error = 'Не удалось загрузить файл';
}
else
$error = 'Размер файла больше допустимого 1 Mb';
}
else
$error = 'У файла недопустимое расширение';
}
else
{
// массив ошибок
$error_values = [
UPLOAD_ERR_INI_SIZE => 'Размер файла больше разрешенного директивой upload_max_filesize в php.ini',
UPLOAD_ERR_FORM_SIZE => 'Размер файла превышает указанное значение в MAX_FILE_SIZE',
UPLOAD_ERR_PARTIAL => 'Файл был загружен только частично',
UPLOAD_ERR_NO_FILE => 'Не был выбран файл для загрузки',
UPLOAD_ERR_NO_TMP_DIR => 'Не найдена папка для временных файлов',
UPLOAD_ERR_CANT_WRITE => 'Ошибка записи файла на диск'
];
$error_code = $_FILES['file']['error'];
if (!empty($error_values[$error_code]))
$error = $error_values[$error_code];
else
$error = 'Случилось что-то непонятное';
}
/* чтобы изменить размеры фото необходимо запустить функцию img_resize с нужными параметрами ширины и высоты нового изображения. Если нужен только один параметр, например ширина 200px, то высоту задаем равную 0 (ноль). При этом получим пропорциональное фото с шириной 200px.*/
$dest = 'img_small/' . $myfile_name;
$src = $destination;
$this->ImgResize($src, $dest, 200,0);
return ['info' => $info, 'error' => $error, 'destination'=>$destination];
}
/*
Функция уменьшения размера фотографии.
Параметры:
$src - имя исходного файла
$dest - имя генерируемого файла
$width, $height - ширина и высота генерируемого изображения, в пикселях
Необязательные параметры:
$rgb - цвет фона, по умолчанию - белый
$quality - качество генерируемого JPEG, по умолчанию - максимальное (100)
*/
private function ImgResize($src, $dest, $width, $height, $rgb = 0xFFFFFF, $quality = 100)
{
if (!file_exists($src)) // Проверить наличие указанного файла или каталога.
return false;
$size = getimagesize($src);
if ($size === false)
return false;
$format = strtolower(substr($size['mime'], strpos($size['mime'], '/') + 1));
$icfunc = 'imagecreatefrom' . $format;
if (!function_exists($icfunc))
return false;
$x_ratio = $width / $size[0];
$y_ratio = $height / $size[1];
if ($height == 0)
{
$y_ratio = $x_ratio;
$height = $y_ratio * $size[1];
}
elseif ($width == 0)
{
$x_ratio = $y_ratio;
$width = $x_ratio * $size[0];
}
$ratio = min($x_ratio, $y_ratio);
$use_x_ratio = ($x_ratio == $ratio);
$new_width = $use_x_ratio ? $width : floor($size[0] * $ratio);
$new_height = !$use_x_ratio ? $height : floor($size[1] * $ratio);
$new_left = $use_x_ratio ? 0 : floor(($width - $new_width) / 2);
$new_top = !$use_x_ratio ? 0 : floor(($height - $new_height) / 2);
// если не нужно увеличивать маленькую картинку до указанного размера
if ($size[0]<$new_width && $size[1]<$new_height)
{
$width = $new_width = $size[0];
$height = $new_height = $size[1];
}
$isrc = $icfunc($src);
$idest = imagecreatetruecolor($width, $height);
imagefill($idest, 0, 0, $rgb);
imagecopyresampled($idest, $isrc, $new_left, $new_top, 0, 0, $new_width, $new_height, $size[0], $size[1]);
$i = strrpos($dest,'.');
if (!$i) return '';
$l = strlen($dest) - $i;
$ext = substr($dest,$i+1,$l);
switch ($ext)
{
case 'jpeg':
case 'jpg':
imagejpeg($idest,$dest,$quality);
break;
case 'gif':
imagegif($idest,$dest);
break;
case 'png':
imagepng($idest,$dest);
break;
}
imagedestroy($isrc);
imagedestroy($idest);
return true;
}
/*Добавить запись в базу данных в таблицу больших или уменьшенных фото*/
public function AddImage($table_name)
{
$myfile_name = $_FILES["file"]["name"];
$file_type = substr($myfile_name, strrpos($myfile_name, '.')+1);
$destination = $this->dir . '/' . $myfile_name;
//Добавление записи в базу данных тип файла и временное имя файла на нашем сервере (во время запроса)
$sql = "INSERT INTO $table_name (typ, address, myfile_name) VALUES ('$file_type', '$destination', '$myfile_name')";
$this->db->Execute($sql);
}
}
?>
-- phpMyAdmin SQL Dump
-- version 4.4.15.7
-- http://www.phpmyadmin.net
--
-- Хост: 127.0.0.1:3306
-- Время создания: Окт 01 2017 г., 19:17
-- Версия сервера: 5.5.50
-- Версия PHP: 5.4.45
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
--
-- База данных: `lyapin`
--
-- --------------------------------------------------------
--
-- Структура таблицы `big`
--
CREATE TABLE IF NOT EXISTS `big` (
`id` int(6) unsigned NOT NULL,
`typ` varchar(5) NOT NULL,
`thum_des` varchar(200) NOT NULL,
`designation` varchar(32) NOT NULL,
`myfile_name` varchar(50) NOT NULL,
`address` varchar(50) NOT NULL,
`click` smallint(3) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Структура таблицы `small`
--
CREATE TABLE IF NOT EXISTS `small` (
`id` int(6) unsigned NOT NULL,
`typ` varchar(5) NOT NULL,
`designation` varchar(32) NOT NULL,
`myfile_name` varchar(50) NOT NULL,
`address` varchar(60) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Индексы сохранённых таблиц
--
--
-- Индексы таблицы `big`
--
ALTER TABLE `big`
ADD PRIMARY KEY (`id`);
--
-- Индексы таблицы `small`
--
ALTER TABLE `small`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT для сохранённых таблиц
--
--
-- AUTO_INCREMENT для таблицы `big`
--
ALTER TABLE `big`
MODIFY `id` int(6) unsigned NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT для таблицы `small`
--
ALTER TABLE `small`
MODIFY `id` int(6) unsigned NOT NULL AUTO_INCREMENT;
Открыть галереею фотографий в отдельном окне браузера. Галерея представлена без дизайна, отсутствует CSS, JS. Работает только функционал на основе РНР.