Для выполнения задания нужно: иметь представление о HTML/CSS (так как мы делаем сайт на фреймворке, а страницы сайтов пишутся на HTML), иметь представление о SQL-запросах или желание в них разобраться (так как мы будем работать с базой данных), иметь представление об ООП (так как все популярные фреймворки используют ООП).
Нужно иметь установленные и настроенные Апач/PHP/MySQL (или денвер/XAMPP но лучше бы установить компоненты по отдельности, дает полезные навыки).
Если есть пробелы в знаниях, у меня есть паста про установку Апача и пара уроков по ООП.
Задание поможет: разобраться в MVC, научиться использовать один из фреймворков, использовать современные подходы к разработке, писать более правильный код.
Задание: сделать сайт uppu.ru, аналог rghost.ru, который позволяет загружать картинки и файлы и делиться ссылочкой. Насчет дизайна, можешь сделать как на rghost (там используется Twitter bootstrap), там должно быть 3 страницы:
- Главная страница, она же страница загрузки файла, содержит поле выбора файла для загрузки
- Страница просмотра файла. Если это картинка, выводится информация о файле (имя, размер, время зазрузки, комментарий автора), уменьшенная копия и ссылка «скачать». Если это не-картинка, то только информация и ссылка скачать.
- Страница со списком последних 100 загруженных файлов, дата, ссылка скачать, название и размер.
Информацию о загруженных файлах удобно хранить в базе данных. Если ты не работал с Бд и SQL, я могу дать краткие ссылочки, для этого задания каких-то крутых знаний не нужно, достаточно знать запросы SELECT, INSERT, CREATE TABLE и все.
В качестве фремйворка лучше всего брать Slim, так как это современный микрофреймворк, но по нему трудно найти информацию на русском (на английском доккументация подробная), или Silex, он тоже современный да еще и основан на компонентах Symfony, а если ты не дружишь с английским, то придется взять F3. Но лучше бы взять Slim или Silex.
F3, Silex и Slim — микрофреймворки, то есть простые фреймворки с небольшим числом классов и функций.
Ознакомительная статья:
- про Silex: сайт http://silex.sensiolabs.org/ (англ), статья так-себе качества http://habrahabr.ru/post/118011/ (рус.)
- про F3: http://habrahabr.ru/post/135619/ (рус.)
- про Slim: docs.slimframework.com (англ.)
- про Yii2: https://github.com/yiisoft/yii2/tree/master/docs/guide-ru (рус.) http://www.yiiframework.com/doc-2.0/guide-index.html (англ)
В качестве шаблонизатора стоит использовать twig, он современный, удобный и интегрируется с Slim.
Естественно, тебя никто не бросает один на один с фреймворком. Ты всегда можешь задать вопрос, а также периодически постишь свой код, а я его буду смотреть и давать советы и замечания и предупреждать о подвохах. Код удобнее всего постить на гитхаб (умение пользоваться гитом тебе все равно пригодится, если ты хочешь работать программистом, так как сейчас везде его используют), но для начала можно постить сюда: https://gist.github.com/ или на какой-нибудь pastebin или zip-архивом.
Если ты быстро справишься с заданием, то я могу придумать дополнительные задачи: поиск по файлам, организация альбомов, загрузка перетаскиванием с рабочего стола, модерирование, комментарии.
Алсо, если ты не умрешь в процессе изготовления uppu.ru, вот что планируется сделать:
- загрузка файлов на сервер
- страница скачивания
- для картинок, выводить информацию и превьюшку
- для медиафайлов (аудио/видео), выводить информацию (ее можно получить с помощью библиотеки вроде gitId3, не руками же файлы расковыривать)
- добавить плеер для аудио/видео
- прикрутить поиск по файлам с помощью sphinx (чтобы это работало, нужно хранить данные в базе данных — ну я надеюсь, к этому моменту ты это осилишь)
- прикрутить загрузку файлов простым перетаскиванием на страницу с помощью jQuery плагина (конечно по хоршему надо бы заставить написать тебя загрузчик с нуля, чтобы разобраться в яваскрипте и DOM, но это наверно сложовато)
- комментарии к файлам
- древовидные комментарии к файлам
Делать в принципе можно в любом порядке.
Там изучать-то нечего, это микрофреймворк, весь его исходный код наверно можно за пару часов прочесть.
Небольшая подстава в том, что на русском ничего почти нету, так что либо через гуглотранслейт придется разбираться, либо можешь тут непонятные вопросы задавать, я подскажу.
Документация тут: http://docs.slimframework.com/ — не знаешь английского, посмотри хотя бы примеры кода или в гуглотранслейт попробуй засунуть.
Еще вот ссылка http://hashcode.ru/questions/234843/php-slim-framework-как-подключать
Слим из коробки дает тут роутер (штуку, которая разбирает URL на части и вызывает нужную функцию). Вот пример кода:
$app = new \Slim\Slim();
// Define a HTTP GET route:
$app->get('/hello/:name', function ($name) {
echo "Hello, $name";
});
// Run the Slim application:
$app->run();
При обращении по удресу http://mysite/hello/lalala выведет нужный текст.
Для работы с ним нужно установить Апач + Php, у меня есть ободряющая (инфы-то там не очень много) паста на тему установки Апача: http://gist.github.com/anonymous/946f4f1830be3955fe17
Затем скачай slim и добейся, чтобы пример с hello world работал.
Затем можешь попробовать сделать страничку загрузки файла например.
Удобнее всего завести себе аккаунт на гитхабе, изучить основы git (книга на русском: http://git-scm.com/book/ru ) и коммитить туда. Там можно будет не только посмотреть сам код, но и историю изменений — очень удобно.
В ходе разработки ты будешь ставить дополнительные библиотеки (ну как минимум сам Slim, а может что-то еще). Ставить их руками. скачивая с сайта и распаковывая — каменный век. Есть гораздо более удобная штука — менеджер пакетов composer. Подробнее: http://habrahabr.ru/post/145946/
Ты всего лишь пишешь имена и версии пакетов, которые надо установить, в файлик — а он сам их скачивает и ставит. Соответственно, ты не занимаешься ручной работой, и не забиваешь репозиторий библиотеками (папку композера под названием vendor, как ты надеюсь догадался, надо добавить в .gitignore — что это за файл, описано в книге по git).
Композер ставит пакеты из репозитория. Основной репозиторий называется packagist.org — ты можешь открыть его и сам посмотреть сколько там разных пакетов собрано.
Композер также умеет генерировать код для автозагрузки классов — что опять же, облегчает тебе жизнь. Подробнее про автозагрузку:
- http://php.net/manual/ru/language.oop5.autoload.php
- http://php.net/manual/ru/function.spl-autoload-register.php
Если ты разрешаешь людям из интернета загружать на свой сервер файлы, то сам понимаешь, найдется какой-нибудь нехороший человек который попробует загрузить на твой сервер что-то нехорошее. Вот какие есть векторы атаки при загрузке файлов:
- злоумышленник загружает свой php-скрипт, вызывает его через браузер (http://example.com/uploads/script.php) и получает контроль над сервером
- если загрузка PHP-файлов запрещена или не работает, злоумышленник загружает свой
.htaccessфайл на сервер. Этот файл меняет настройки веб-сервера Апач в текущей папке и позволяет обойти например запрет на выполнение php-кода. - (гораздо менее опасно) злоумышленник загружает тебе на сервер свой HTML-файл с яваскрипт-кодом. Яваскрипт выполняется в браузере, так что серверу ничего не грозит. Но так как файл загружается с твоего домена (т.е. имеет адрес вроде
http://files.example.com/uploads/file.html) то яваскрипт на нем имеет доступ к кукам пользователей, а также может отправлять запросы от их имени. Злоумышленник уговаривает пользователей открыть эту ссылку, они открывают, скрипт на странице ворует их куки, загружает от их имени файлы, пишет от их имени спамные комментарии на твоем сайте.
Какие есть средства борьбы?
- ограничение на расширения загружаемых файлов (например только
.jpg,.png,.gif). Это не годится для файлообменника, так как мы хотим иметь возможность передавать любые файлы - запрет на выполнение php-скриптов в папке загруженных файлов: http://habrahabr.ru/post/61842/ . Подвохи: на некоторых хостингах опция
php_flagотключена и игнорируется (запрет не сработает), злоумышленник может попытаться загрузить.htaccessфайл, отменяющий действие этой опции, если вместо Апача использовать другой веб-сервер (например nginx), то он не читает файлы.htaccessи не выполняет записанные там команды - загружать файлы на отдельный сервер, где нет или отключен интерпретатор php (подходит для тех, у кого много серверов)
- борьба с загрузкой HTML-файла: можно загружать файлы на отдельный от основного домен, можно при скачивании выставлять правильные заголовки, которые заставят браузер скачать файл, а не открыть его как веб-страницу (
Content-Disposition: attachment,Content-Typeне содержащийtext/html) - переименовывание файлов при загрузке с безопасным расширением вроде
.txt, так что файл не будет выполняться как php-код. Пожалуй один из самых надежных вариантов.
Также, если ты складываешь файлы в одну папку, то 2 файла с одинаковыми именами могут перезаписать друг друга. Метод борьбы - переименование или добавление в имя какого-то уникального не повторяющегося идентификатора, например id файла из базы данных.
Во многих ОС есть ограничение на длину полного пути к файлу. Специально или намеренно тебе могут загрузить файл с очень длинным именем так, что например после сохранения с ним не смогут работать какие-то программы. Стоит сделать ограничение на длину имени файла. При этом надо «обрезать» имя так, чтобы в итоге не получился файл с расширением вроде .php.
Имя файла может содержать любые символы, в том числе иероглифы или хитрые пробелы. Хотя это не несет особого риска, но возможно имятакого файла будет неудобно читать администратору.
Если ты складываешь все файлы в одну папку, со временем их там будет очень много. Современные линуксовые файловые системы могут хранить миллионы файлов в одной папке, но удобно ли будет администратору просматривать такую папку? Некоторые программы также не смогут отобразить такое число файлов. Потому стоит раскладывать файлы по папкам из расчета не более 500-1000 файлов на папку. Можно это делать по первым цифрам id файла (uploads/13/13012-file.txt), можно по дате (год + месяц, например uploads/2015/11/13012-file.txt).
Также, в имени файла пришедшем от пользователя, могут быть любые символы, например китайские иероглифы. Если потом администратор захочет удалить или что-то сделать с файлом, возможно он не сможет ввести его название. Некоторые программы для работы с файлами тоже могут некорректно работать с такими символами в именах файлов. Для защиты от этого можно переименовывать файлы в латинницу.
Полезно иногда смотреть чужой код. Можно подметить какие-то интересные вещи, которые ты не знал. Однако, я советую тебе сначала попробовать написать код самому (или хотя бы спроектировать), а только потом смотреть чужие работы, чтобы сравнить результат. Иначе может получиться, что вместо того, чтобы придумать что-то свое, ты будешь подсознательно копировать ранее увиденное. Примеры разных файлообменников на PHP (не обязательно имеющих отношение к этой задаче) можно увидеть, сделав поиск на гитхабе: https://github.com/search?l=PHP&q=file+sharing+&ref=searchresults&type=Repositories&utf8=%E2%9C%93
(Если ты хочешь чтобы твоя работа тоже попала в список, добавь в описание репозитория слова file sharing app).
Ты заметишь, что некоторые приложения по ссылке устроены намного проще: например, они не используют ООП, или даже состоят из единственного файла. Если приложение маленькое (до 500-1000 строк), его действительно можно сделать и без ООП. Но в реальности все приложения, с которыми тебе придется работать, будут большие, и тебе понадобится и ООП, и MVC.
А если тебе хочется собрать все в один файл, то незачем делать это руками. Напиши или найди готовый склейщик, например https://github.com/codeless/jugglecode
Из соображений безопасности нам, может быть, придется переименовывать файлы при сохранении. Но как сделать, чтобы при скачивании они сохранялись бы под исходным именем? Браузер при скачивании берет имя файла из последнего сегмента URL (то, что идет после последнего слеша). Ну например, при скачивании по URL http://example.com/files/123/example.txt?a=1 браузер сохранит файл под именем example.txt?a=1.
Таким образом, нам надо чтобы последним сегментов в URL было исходное имя файла. Надо помнить, что в URL нельзя использовать некоторые символы вроде пробела, потому имя надо закодировать процентной кодировкой.
Первый подход - это использовать правила переписывания в .htaccess. Этот файл позволяет менять настройки Апача в отдельно взятой папке. С помощью модуля Апача mod_rewrite мы можем определить, что при обращении по определенному URL мы должны сделать замены в этом URL, чтобы получить реальное имя файла. При таком подходе мы можем сделать так, чтобы URL
http://example.com/download/stored-name.txt/имя%20для%20скачивания.php
Переписывался бы на /download/stored-name.txt. Таким образом, в нашем URL заложено как реальное имя файла на диске, так и дополнительное, которое предназначено для браузера. %20 - это символ пробела, закодированный процентной кодировкой.
Ссылки:
- http://httpd.apache.org/docs/current/mod/mod_rewrite.html (англ)
- http://onedev.net/post/284
- https://habrahabr.ru/company/sprinthost/blog/129560/
- http://www.egoroff.spb.ru/portfolio/mod_rewrite.html
Второй подход - использовать расширение Апача mod_xsendfile. Этот модуль позволяет отдавать без участия PHP произвольный файл, в том числе и не из публичной папки. Оно может использовать например для скачивания файла с проверкой доступа, учетом числа скачиваний или каких-то других условий.
При этом подходе сначала запускается PHP скрипт, который анализирует URL, определяет по нему id файла и находит имя, под которым он сохранен на диске. А затем он выдает специальный заголовок вроде X-SendFile: /download/real-name.txt и завершается. Модуль mod_xsendfile видит этот заголовок и без участия PHP отдает пользователю указанный файл.
Разумеется, URL в этом случае должен содержать id файла, а также имя для браузера в конце, например, http://example.com/123/имя%20для%20сохранения.txt.
Этот модуль позволяет отдавать файлы из непубличных папок, и таким образом, скачать файл в обход php-скрипта, по прямой ссылке, нельзя.
Ссылки: