RayMefise
@RayMefise
Java, PHP, C, C++, C#, .NET, QT

PSR-0 или PSR-4, и как правильно построить структуру проекта?

Всем привет. Недавно познакомился со стандартами написания кода и если честно немного запутался в их описании.

Первый вопрос который меня интересует это PSR-0 или PSR-4. На сколько я понял по состоянию на 21 октября 2014 года PSR-0 был помечен как устаревший. В настоящее время рекомендуется использовать PSR-4 в качестве замены, но PSR-1 и PSR-2 ссылаются на PSR-0, а про PSR-3 я вообще как-то не нашел русскоязычной информации, словно такого стандарта нет.

Второй вопрос связан с иерархией по стандарту PSR-0 или PSR-4.

В примерах приводят следующее:
\Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php

\Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php

\Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php

\Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php


насколько я понимаю
/path/to/project/ это путь к проекту и данный путь нигде не фигурирует, это та директория из которой запускается основной index.php
./lib/ это папка в которой я должен хранить свои библиотеки
./vendor/ это папка назначение которой я не понимаю, так как поставщик насколько я понимаю идет дальше
в итоге насколько я понял путь строится так
<путь к проекту>/lib/vendor/<Наименование производителя>/(<Пространство имен>/)<Название класса>.php

это соответствует пространству имен
<Наименование производителя>\(<Пространство имен>\)<Название класса>


но в других примерах я встречал следующее:
вместо "lib" используют "src" а каталога vendor попросту нет.
или подобного рода структуру
vendor/
    vendor_name/
        package_name/
            src/
                Vendor_Name/
                    Package_Name/
                        ClassName.php       # Vendor_Name\Package_Name\ClassName
            tests/
                Vendor_Name/
                    Package_Name/
                        ClassNameTest.php   # Vendor_Name\Package_Name\ClassNameTest


в итоге честно говоря я запутался в том как правильно надо строить свои каталоги, какие папки обязательные какие нет, когда использовать src, когда lib, когда tests, почему в некоторых структурах приходится дважды указывать имя поставщика и имя пкета и т.д.

Скорее всего тут все очень просто, но у меня почему-то вызывает диссонанс в примерах с разных источников.

На всякий случай приведу пример иерархии своей CMS системы которую я разрабатываю:
./ROOT/ - ядро системы
./ROOT/classes/ - системные классы для работы ядра системы и дающие доступ к ядру из сторонних пакетов
./ROOT/configure/ - тут хранится все что связано с настройкой cms системы
./ROOT/kernel/ - тут лежат файлы самого ядра
./localization/ - тут лежат файлы локализации для системы и ее компонент и модулей. У них своя внутренняя иерархия.
./resources/ - тут лежат файлы ресурсов для работы компонент и модулей, а также все что получает cms система из вне или создает по средством работы самой системы, попадает сюда. Внутри каталога своя строгая иерархия.
./templates/ - тут лежат файлы с шаблонами страниц. к каждой странице сайта привязан один из этих шаблонов.
./components/ -компоненты. 
./components/<имя компоненты>/ - По сути это программа которая имеет выходной класс обязательно унаследованный от системного. Обеспечивает подключение к странице основного контента. Грубо говоря это то что отображается в зоне контента на странице. Может быть настроен для разных страниц по своему. Имеет закрепленный за ним набор обязательных и необязательных параметров и позволяет выбирать шаблон для отображения. Обязателен для страницы и может быть только один на странице.
./modules/ - модули
./modules/<имя модуля>/ - по сути схож с компонентами, за исключением того что располагается в определенных блоках шаблона для каждой страницы.
./plugins/ - плагины
./plugins/<имя плагина>/ - по сути это код который в явном виде не используется в системе, но добавляет ей дополнительные возможности, как например плагин который подключает на странице нужную библиотеку jqwery
./utilities/ - тут лежат утилиты для работы с системой, например утилита обновления, миграции данных, проверки на ошибки и т.д.
./lib/ - тут лежат библиотеки которые используются в модулях, компонентах и плагинах.
./lib/<имя поставщика>/<пространство имен>/<имя файла>.php (соответствует пространству имен <имя поставщика>\<пространство имен>\<имя файла>)
./index.php - основной файл который запускается при обращении к сайту. Он является обработчиком запросов, запускает ядро и возвращает результат.
  • Вопрос задан
  • 7840 просмотров
Решения вопроса 2
27cm
@27cm
TODO: Написать статус
Первый вопрос который меня интересует это PSR-0 или PSR-4. На сколько я понял по состоянию на 21 октября 2014 года PSR-0 был помечен как устаревший.

PSR-4 не замена PSR-0, а дополнением к нему.
github.com/php-fig/fig-standards/blob/master/accep...


про PSR-3 я вообще как-то не нашел русскоязычной информации, словно такого стандарта нет

Видать, не перевели. Читайте в оригинале:
github.com/php-fig/fig-standards/blob/master/accep...


/path/to/project/ это путь к проекту и данный путь нигде не фигурирует, это та директория из которой запускается основной index.php

Да, это пусть к PHP файлам проекта. Но index.php обычно выносят в отдельный каталог (например, /public), а все классы проекта хранятся, например, в /src (или /lib или ещё как угодно). В конфигурации веб-сервера запрещают отправлять запросы к любым файлам, не лежащим в /public, благодаря этому /public/index.php является единственной точкой входа для внешних запросов.


./vendor это папка назначение которой я не понимаю

Это папка для сторонних библиотек, используемых в вашем проекте. Используется composer'ом. Внутрь лезть особо причин нет, composer сам решит как ему там всё разложить. Свои классы вы туда тоже не должны писать.


в итоге честно говоря я запутался в том как правильно надо строить свои каталоги, какие папки обязательные какие нет, когда использовать src, когда lib, когда tests, почему в некоторых структурах приходится дважды указывать имя поставщика и имя пкета и т.д.

src и lib - скажем так, синонимы. Кому как больше нравится. Главное, что внутри лежат сами PHP файлы проекта, следующие стандарту PSR-4. Лежат там только файлы, написанные авторами проекта. Поэтому нет смысла класть vendor внутрь src (или lib).
test - каталог для тестов проекта.
В папке vendor имя поставщика и имя проекта могут совпадать, вот они и дублируются.

Так как вы изобретаете свой велосипед, то и структуру каталогов делайте свою, или посмотрите на популярные CMS/фреймворки, но везде будет по-разному. Joomla, WordPress, Yii, Zend Framework, Symfony.

Я придерживаюсь такой структуры:
/config                     Глобальные настройки проекта.
/data                       Временные файлы. Например:
/data/cache	            Файлы кеша.
/data/logs	            Логи.
/data/tmp	            Прочие временные файлы.
/module                     Модули проекта. Например:
/module/Backend	        
/module/Backend/config      Настройки модуля.
/module/Backend/src	    Файлы PHP модуля. Например:
/module/Backend/src/Backend/Path/To/ExampleClass.php
/module/Backend/test	    Unit-тесты модуля.
/module/Backend/view	    Шаблоны модуля.
/module/Frontend/...
/public/index.php
/public/css
/public/font
/public/img
/public/js
/vendor


Возможно, я ошибаюсь, но самая главная ваша беда в том, что вы решили разрабатывать собственную CMS, не поработав с существующими, не выявив достоинства и недостатки их архитектур и структур каталогов.
Ответ написан
delphinpro
@delphinpro
frontend developer
/path/to/project/ это путь к проекту и данный путь нигде не фигурирует, это та директория из которой запускается основной index.php

Нет. Этот корневая директория проекта. Из нее запускается композер. В ней же обычно лежит DOCUMENT_ROOT каталог, в котором уже и находится точка входа index.php. Также здесь лежат директории vendor (для сторонних пакетов) какой нибудь application/ для ваших файлов.

Давайте попробую объяснить на примере.

Пусть будет такая структура, например.
20151206-170857.png
в vendor - вам ничего самому писать не нужно. Этот папка для композера.
public_html - в ней только index.php и все ваши css, images, js. Это папка на которую указывает DOCUMENT__ROOT в настройках домена вашего сервера. Только эти файлы доступны "по интернету".
application - здесь все ваши самописные php файлы.
(На остальные каталоги не обращаем внимания, в корне проекта можно располагать все что вам удобно, это не будет доступно из web)

Под такую структуру написан подобный composer.sjon
{
  "require": {
    "php": ">=5.5.9",
    "slim/slim": "2.*",
    "twig/twig": "~1.18",
    "slim/views": "^0.1.3",
    "robmorgan/phinx": "^0.4.4",
    "illuminate/database": "^5.1"
  },
  "minimum-stability": "stable",
  "autoload": {
    "psr-4": {
      "MyName\\MyProject\\": "application"
    }
  }
}

Тут вроде бы все просто. В require перечислены используемые пакеты. Поясню только autoload. Автозагрузка по стандарту PSR-4. Указано пространство имен ваших файлов и папка в которой они лежат.
Если ваш класс MyClass лежит в папке application - то у него должно быть пространство имен \MyName\MyProject (полное имя класса получается \MyName\MyProject\MyClass). Если ваш класс MyController лежит в папке application/Mvc/Controllers, то, соответственно \MyName\MyProject\Mvc\Controllers\MyController.

При этом вам не нужно заморачиваться и писать автозагрузчик. Просто выполните команду php composer.phar install (или php composer.phar dumpautoload для пересборки аавтозагрузчика) и подключите файл автозагрузчика в index.php
include '../vendor/autoload.php';

Не использовать композер не имеет смысла, т.к. это очень просто. Просто скачайте файл https://getcomposer.org/composer.phar в корень проекта и пользуйтесь (см выше).
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
от 15 000 до 30 000 руб.
HTML Academy Санкт-Петербург
от 110 000 до 130 000 руб.
Aitarget Санкт-Петербург
от 100 000 руб.
25 авг. 2019, в 09:23
3000 руб./за проект
25 авг. 2019, в 08:28
3000 руб./за проект
25 авг. 2019, в 08:15
5000 руб./за проект