ВСЕ СТАТЬИ
Блог начинающего программиста
Регистрация

Создать фотогалерею

Опубликовано:

Представляю сайт галереи фотографий. Создан с использованием языка программирования РНР, системы управления базой данных 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);
    }
}

?>
        

Файл представления - основной шаблон main.php:


<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title><?=$title?></title>
</head>
<body>
    <h1><?=$title?></h1>
    <?php include $content; ?>
</body>
</html>
        

Файл представления - контент в виде списка content_index_list.php:


<a href="index.php">Таблица</a> | <strong>Список</strong>
<br>
<?php $i = 0;?>
<?php foreach ($photos as $photo): ?>
    <p>
        <a href="photo.php?id=<?= $i ?>">
            <img src="<?=$modelGalleryIcon->Icon($i)?>" alt="Фото">
        </a>
    </p>
    <?php $i++; ?>
<?php endforeach ?>

<form method="post" enctype="multipart/form-data">
    <p><input type="file" name="file"></p>
    <p><input type="submit" value="Загрузить файл!"></p>
</form>
        

Файл представления - контент в виде таблицыcontent_index_table.php:


<strong>Таблица</strong> | <a href="index.php?view=list">Список</a>
<table>
    <tr>
        <?php $i = 0;?>
        <?php foreach ($photos as $photo): ?>

            <?php if (($i - 1) % 3 == 2): ?>
                </tr><tr>
            <?php endif; ?>
            <td>
                <a href="photo.php?id=<?= $i ?>">
                    <img src="<?=$modelGalleryIcon->Icon($i)?>" alt="Фото">
                </a>
            </td>
            <?php $i++; ?>

        <?php endforeach ?>
    </tr>
</table>
<br>
<form method="post" enctype="multipart/form-data">
    <p><input type="file" name="file"></p>
    <p><input type="submit" value="Загрузить файл!"></p>
</form>
        

Код для просмотра фотографии content_photo.php


<a href="<?php echo $_SERVER['HTTP_REFERER'];?>">Назад</a>
<p><img src="<?=$modelGalleryImage->Image($i)?>" alt="Фото крупное"></p>
        

Код SQL для создания базы данных lyapin:


-- 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. Работает только функционал на основе РНР.


Комментарии

Пока комментарий нет

Оставить свой комментарий:

Зарегистрироваться
Имя:
Электронная почта:
Текст комментария:
Введите код с картинки:
картинка