Статьи

Скелет PDS на примере: стандарт для структуры файлов и папок

Глядя на реестр Packagist , мы видим, что большинство пакетов следуют шаблону с некоторыми небольшими изменениями, чтобы соответствовать их потребностям, в то время как другие имеют странную структуру папок, которая требует времени, чтобы разобраться.

Эта проблема была решена по-разному разными людьми. Некоторые фреймворки имеют свои собственные рекомендации о том, как структурировать ваши классы и ресурсы, в то время как другие имеют скелет, который вы можете использовать в качестве отправной точки. В этой статье мы собираемся изучить php-pds / skeleton и использовать его для создания небольшого пакета в качестве демонстрации.

Примечание: PDS означает Стандарты разработки пакетов .

План дома сверху вниз, иллюстрация, с указанием каркаса для будущего проекта

Что мы строим

Идея состоит в том, чтобы иметь возможность сопоставить страницы часто задаваемых вопросов (или любую другую страницу) с исключениями, создаваемыми нашим приложением Laravel. Это послужит отправной точкой для наших пользователей, чтобы понять, что пошло не так.

Вы можете найти окончательный код на GitHub . Не стесняйтесь посылать запросы на извлечение, чтобы улучшить его или предложить исправления! (Если ваш Git ржавый, у нас есть хороший премиум курс для этого)

PDS Скелет

Скелет PDS признает, что уже есть некоторые распространенные практики, используемые разработчиками, которые публикуют на Packagist. После некоторого исследования с использованием API Packagist для изучения общих структур папок, автор предложил интересное резюме .

Когда мы публикуем что-то публично, оно должно придерживаться некоторых общих правил, таких как тестирование, документирование, форматирование и т. Д. Следующим шагом будет создание общей структуры папок, чтобы помочь разработчикам и участникам понять поток кода.

Конечно, вы слышали о лиге PHP раньше! Если вы хотите внести пакет в лигу, вы должны использовать их скелет вместе с некоторыми другими правилами, которые необходимо соблюдать. Я думаю, что то же самое для всего сообщества поможет улучшить читаемость и согласованность всех публично выпущенных пакетов.

Сборка пакета

Поскольку это пакет Laravel, я буду следить за этим рабочим процессом . Идите вперед и загрузите пакет скелета PDS.

cd vendor
mkdir whyounes # this is my author namespace
curl -LOk https://github.com/php-pds/skeleton/archive/1.0.0.zip # Download file
unzip 1.0.0.zip
mv 1.0.0 laravel-faq-exceptions
rm 1.0.0.zip

Нам нужно обновить наш файл composer.json Давайте пока будем проще!

 {
    "name": "Whyounes/laravel-faq-exceptions",
    "type": "library",
    "description": "Laravel package for mapping exception FAQ pages.",
    "homepage": "https://github.com/Whyounes/laravel-faq-exceptions",
    "license": "MIT",
    "require": {
        "laravel/framework": "~5.3"
    },
    "require-dev": {
        "pds/skeleton": "~1.0"
    },
    "autoload": {
        "psr-4": {
            "Whyounes\\FaqException\\": "src/"
        },
        "classmap": [
            "tests"
        ]
    },
    "autoload-dev": {},
    "bin": []
}

Возможно, вы заметили, что раздел require-devpds/skeleton Это имеет два преимущества.

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

Теперь, когда у нас есть отправная точка, мы можем запустить репо и добавить наш Git remote.

 git init
git add .
git commit -m "first commit"
git remote add origin [email protected]:Whyounes/laravel-faq-exceptions.git
git push -u origin master

Естественно, замените удаленный URL-адрес на свой собственный репо.

Скелет содержит некоторые классы по умолчанию в качестве демонстрации, так что идите и почистите каталоги.

Альтернативный вариант

Существует еще один способ создать скелет, не загружая zip-файл и не разархивируя его.

 composer require --dev pds/skeleton
./vendor/bin/pds-skeleton generate

Это создаст все недостающие файлы и папки.

конфиг

Обычно в пакете есть несколько файлов конфигурации, на которые можно положиться при принятии решения о том, что делать. Скелет PDS имеет каталог для этого называется config

Если пакет предоставляет каталог корневого уровня для файлов конфигурации, он ДОЛЖЕН называться config/
Эта публикация не определяет структуру и содержание каталога.

У нас есть только один файл конфигурации на данный момент. Мы можем поместить это туда, и мы будем ссылаться на это у нашего поставщика услуг (подробнее об этом позже).

Ресурсы

Наш пакет должен иметь некоторый доступ к БД, чтобы иметь возможность отображать исключения на страницах FAQ. Это означает, что нам нужно создать миграцию для этой цели.

PDS Skeleton имеет каталог resources

Если пакет предоставляет каталог корневого уровня для других файлов ресурсов, он ДОЛЖЕН называться resources/
Эта публикация не определяет структуру и содержание каталога.

Правила не определяют, как должна выглядеть базовая структура. В настоящее время мы будем использовать его для хранения наших migrationsviews Его также можно использовать для хранения сеялок, языковых файлов и т. Д.

 // resources/migrations/2014_10_12_000000_create_faq_table.php

class CreateFaqTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('whyounes_faq', function (Blueprint $table) {
            $table->increments('id');
            $table->text('exception');
            $table->string('codes');
            $table->text('url');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('whyounes_faq');
    }
}

Нам также понадобится файл представления для отображения сгенерированного исключения:

 // resources/views/faq.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Laravel</title>

    <!-- Fonts -->
    <link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">

    <!-- Styles -->
    <style>
        html, body {
            background-color: #fff;
            color: #636b6f;
            font-family: 'Raleway', sans-serif;
            font-weight: 100;
            height: 100vh;
            margin: 0;
        }
    </style>
</head>
<body>
<div class="flex-center position-ref full-height">
    <div class="content">
        <div class="links">
            An error has occured: {{ $exception->getMessage() }}
            @if(!is_null($faq))
                <br>You can get more details about the problem <a href="{{ $faq->url }}">here</a>.
            @endif
        </div>
    </div>
</div>
</body>
</html>

Исходные файлы

Хорошо, теперь мы переходим к реальной логике пакета. Скелет имеет каталог src

Если пакет предоставляет каталог корневого уровня для файлов исходного кода PHP, он ДОЛЖЕН быть назван src/
Эта публикация не определяет структуру и содержание каталога.

Каталог src

структура каталогов

Фактический исходный код находится в репозитории, но давайте кратко обсудим эти классы.

  • src/Models/Faq.php Мы группируем модели в одном каталоге здесь.
  • src/Providers/FaqProvider.php Мы используем его для публикации ресурсов (таких как представления, миграции, конфигурации), регистрации привязок IoC, маршрутов и т. Д.
  • src/Repositories/FaqRepository.php Я предпочитаю держать их отдельно от каталога моделей.

У нас также есть несколько классов в корне каталога src Это не нарушает никаких правил скелета. Фактически, для некоторых классов имеет смысл находиться в корне пространства имен.

Как работает пакет?

Пользователь будет использовать один из средств визуализации в зависимости от типа приложения. Класс WebRendererfaq.blade.php ApiRenderer

Типичное использование будет выглядеть так:

 // app/Exceptions/Handler.php

class Handler extends ExceptionHandler
{
    // ...
    public function render($request, Exception $exception)
    {
        if ($request->expectsJson()) {
            $renderer = App::make(ApiRenderer::class);
        } else {
            $renderer = App::make(WebRenderer::class);
        }

        return $renderer->render($exception);
    }
    // ...
}

тесты

Скелет также содержит папку tests

Если пакет предоставляет каталог корневого уровня для тестовых файлов, он ДОЛЖЕН называться tests/
Эта публикация не определяет структуру и содержание каталога.

Классы, которые мы должны протестировать, это WebRendererApiRendererModels/Faq Несмотря на то, что в спецификации не указана базовая структура папки testssrc

Я думаю, что это должно быть РЕКОМЕНДУЕТСЯ спецификацией скелета как лучшая практика. Большинство пакетов делают это, и это кажется логичным.

Вы можете проверить репозиторий на GitHub, чтобы увидеть реальный тестовый код.

общественного

Наш пакет не имеет общедоступных ресурсов, к которым пользователь должен получить доступ. Но если у вас есть некоторые из них, не забудьте поместить их здесь.

Если пакет предоставляет каталог корневого уровня для файлов веб-сервера, он ДОЛЖЕН быть назван public/
Эта публикация не определяет структуру и содержание каталога.

Запутанная часть здесь заключается в том, использовать ли каталог /resources/public Ответ здесь «это зависит». Если мы создаем пакет для фреймворка, такого как Laravel, мы имеем право указывать ресурсы, которые будут публиковаться фреймворком, в собственную /public Однако, если мы используем скелет для полного приложения, мы можем использовать папку /public

мусорное ведро

Некоторые пакеты предоставляют исполняемые файлы для выполнения задачи. В таких случаях может быть полезен каталог /bin Например, пакеты, такие как PHP Code Sniffer, являются идеальными кандидатами для этого (но разработчик в этом случае решил назвать scripts

Документация

Документация является неотъемлемой частью каждого приложения / пакета. Потребителям и разработчикам программного обеспечения лучше всего понять, как все работает и что они делают неправильно.

Если пакет предоставляет каталог корневого уровня для файлов документации, он ДОЛЖЕН называться docs/
Эта публикация не определяет структуру и содержание каталога.

Скелет PDS предоставляет отдельный каталог для документации, которую мы можем структурировать по своему желанию. На мой взгляд, лучший подход — разделить его на темы и разместить в отдельных каталогах. В случае API мы можем разделить его на конечные точки.

ПРОЧТИ МЕНЯ

Файл README очень важен, но официально не является частью /docs Он дает пользователям обзор того, как установить и интегрировать ваш код, а также некоторые другие общие детали. Наш файл README выглядит следующим образом .

Вы можете видеть, что файл содержит только несколько деталей о пакете; это просто обзор, не нужно делать это слишком долго. Каталог docs

Лицензия

Не многие из нас заботятся о лицензии пакета, но это все еще важный шаг перед публикацией чего-либо. Кто-то может захотеть использовать пакет неожиданным образом, и им нужно знать, разрешено ли это действие или нет.

Этот сайт имеет очень хороший обзор различных доступных лицензий. Для нашего пакета мы будем использовать лицензию MIT.

Содействие

Другая часть, которую разработчики часто игнорируют, — это руководство по вкладу. Приложение должно иметь четкий процесс, чтобы другие разработчики могли вносить изменения и исправления.

Примечание: GitHub автоматически связывается с этим файлом, когда кто-то делает новый запрос на получение.

Нам не нужно создавать его с нуля. Мы можем выбрать тот, который соответствует нашим потребностям, и скопировать его. Файл должен включать:

  • как отправлять сообщения об ошибках и исправления.
  • как отправить исправления безопасности.
  • какой стиль кодирования используется.

Другие вещи могут быть включены, но этого должно быть достаточно, чтобы начать вкладчиков.

 Thanks for choosing to contribute to this package.

## Bug Fixes

Bug fixes for a specific release should be sent to the branch containing the bug. You can also submit a failing test showing where the bug occurs.

## Security Fixes

Security fixes may be sent as a PR or via email to [email protected]

## Coding Standard

This package follows the PSR-2 coding standard and the PSR-4 autoloading standard.

Изменения

Файл изменений используется для отслеживания изменений и исправлений ошибок между выпусками. Проще посмотреть файл, чем пролистать коммиты Git, чтобы увидеть, что произошло. Примером может быть что-то вроде этого:

 # Changelog

## 1.0.37 - 2017-03-22

### Fixed

* Space escaping for Pure-FTPd in the FTP adapter.

## 1.0.36 - 2017-03-18

### Fixed

* Ensure an FTP connection is still a resource before closing it.
* Made return values of some internal adapters consistent.
* Made 0 a valid FTP username.
* Docblock class reference fixes.
* Created a more specific exception for when a mount manage is not found (with BC).

## 1.0.35 - 2017-02-09

### Fixed 

* Creating a directory in FTP checked whether a directory already existed, the check was not strict enough.

## 1.0.34 - 2017-01-30

### Fixed

* Account for a Finfo buffer error which causes an array to string conversion.
* Simplified path handling for Windows.

// ...

Приведенный выше фрагмент взят из пакета flysystem PHPLeague.

Проверка

Мы можем использовать команду validate

 ./vendor/bin/pds-skeleton validate

Подтвердить скелет

Вывод

Использование документированного скелета не только поможет вам организовать ваши файлы, но и поможет другим предсказать, где что находится или должно быть. Скелет PDS не единственный, который существует, но другие, такие как скелет PHPLeague , уже были приняты большим количеством разработчиков, и по умолчанию он совместим с PDS. Это означает, что он соблюдает те же правила и считается действительным при проверке с помощью валидатора.

Используете ли вы скелет при создании нового приложения или пакета? Как вы думаете, мы должны иметь широкий стандарт для этого тоже? Дайте нам знать об этом в комментариях!