Search
Write a publication
Pull to refresh

Создаем свой пакет на PHP

Level of difficultyMedium
Reading time5 min
Views1.9K

Данная статья рассчитана на тех, кто до этого ни разу не делал пакетов — проектов на голом PHP для своих нужд.

Хочу поделиться с вами своим опытом, с которым столкнулся, и предоставить шаблон, который написал для пакетов/проектов:
https://github.com/deniskorbakov/skeleton-php-docker

Буду очень рад звёздочке на GitHub и обратной связи после прочтения статьи!

Предыстория

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

Недавно у меня возникла потребность в написании пакета. До этого я этим не занимался, поэтому начал исследовать тему: изучил информацию на Хабре и других форумах о том, как оформлять Composer и базово описывать пакет.

Как строиться проект

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

Классическое построение проектов написанных на php

Пример
├── src                  # Директория вашего пакета              
└── Dir1                 # Директория для внутрений логики
│   └── PackageClass.php # Класс для внешнего использования
├── tests                # Директория для тестов
│   ├─ Fixtures
│   ├─ Unit  

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

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

Пример возможных директорий:

  • scripts/ — скрипты для сборки, деплоя или других задач.

  • assets/ — статические файлы (стили, скрипты, изображения).

  • .docker/ — конфигурация Docker (Dockerfile, Docker Compose).

  • public/ — точка входа для веб-сервера (если пакет включает веб-интерфейс).

  • config/ — файлы конфигурации приложения.

Composer

Базовая структура composer

Подробнее о настройке можно прочитать здесь.

Ключевые параметры при создании пакета:

name/description/keywords:

Пример
"name": "deniskorbakov/skeleton-php-docker",  
"description": "A skeleton php libs with docker",  
"keywords": ["php", "skeleton", "package", "docker"],
  • name — имя пакета в формате vendor/package.

  • description — краткое описание функциональности.

  • keywords — теги для поиска в Packagist.

require:

Пример
"require": {  
    "php": ">=8.2"  
},

Указывает минимальную версию PHP и зависимости, без которых пакет не работает.

require-dev:

Пример
"require-dev": {  
    "pestphp/pest": "^3.8",  
    "phpstan/phpstan": "^2.1",  
    "rector/rector": "*",  
    "squizlabs/php_codesniffer": "^3.13",  
    "slevomat/coding-standard": "^8.20",  
    "orchestra/testbench": "^10.4"  
},

Зависимости для разработки (тестирование, статический анализ).

autoload

Пример
"autoload": {  
    "psr-4": {  
        "DenisKorbakov\\SkeletonPhpDocker\\": "src/"  
    }  
},

Настройка автозагрузку для вашего пакета.

Полезные команды и скрипты

Команды:

  • composer validate — проверка корректности composer.json.

  • composer outdated — поиск устаревших зависимостей.

Пример скриптов:

Пример
"scripts": {  
    "tests": "pest --stop-on-failure --colors",  
    "tests-coverage": "pest --coverage --min=90",  
    "tests-mutation": "pest --mutate",  
    "lint": [  
        "@phpstan",  
        "@cs",  
        "@rector"  
    ],  
    "phpstan": "phpstan analyse --memory-limit=2G",  
    "rector": "rector",  
    "cs": "phpcs"  
},

Использование: composer tests — запуск тестов.

Статические анализаторы и линтеры

Зачем они нужны

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

Линтер — инструмент для автоматического анализа кода на соответствие стандартам оформления.

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

Статический анализатор — инструмент, который проверяет код на ошибки, уязвимости и антипаттерны без его выполнения.

Внедрение этих инструментов в старые проекты может быть сложным, поэтому иногда разумно применять их только к изменённым файлам.

PHPstan

📖 Подробная статья

Один из самых популярных анализаторов для PHP. Его главное преимущество — уровни строгости (от 0 до 9). Чем выше уровень, тем тщательнее проверка.

Полезные плагины:

  • cognitive-complexity — оценивает сложность кода.

    Сложность кода — метрика, показывающая, насколько код труден для понимания и поддержки.

PHP_CodeSniffer (PHPCS)

Проверяет код на соответствие стандартам (PSR-12, PSR-2). Можно настроить собственные правила.

Rector

Инструмент для автоматического рефакторинга. Например, может обновлять синтаксис с PHP 7.4 на 8.2.

Тестирование

Никогда нельзя доверять себя, а тем более своему коду

Тесты помогают убедиться, что код работает как ожидается.

Pest

Я выбрал Pest вместо PHPUnit из-за более лаконичного синтаксиса. Однако у него есть минус: подсветка синтаксиса работает только с официальным плагином.

Пример теста:

Пример
test('sum', function () {    
  expect(1 + 1)->toBe(2);
});

GitHub Actions

Автоматизация тестов и линтеров

Пример workflow для линтинга:

Пример
name: LINT  
  
on: ['push']  
  
jobs:  
  coding-standard:  
    name: Coding Standard  
    runs-on: ubuntu-latest  
    steps:  
      - uses: actions/checkout@v3  
      - name: Setup PHP 8.4  
        uses: shivammathur/setup-php@v2  
        with:  
          php-version: '8.4'  
          coverage: none 
  
      - name: Cache composer dependencies  
        uses: actions/cache@v4  
        with:  
          path: vendor  
          key: composer-${{ hashFiles('composer.lock') }}  
  
      - name: Install dependencies  
        run: composer install  
  
      - name: Run lint code  
        run: composer lint

Пример тестов:

Пример
name: TESTS  
  
on: ['push']  
  
jobs:  
  test:  
    runs-on: ubuntu-latest  
    strategy:  
      fail-fast: false  
      matrix:  
        php:  
          - '8.4'  
          - '8.3'  
          - '8.2'  
  
    name: Tests (PHP ${{ matrix.php }} - ${{ matrix.deps }})  
  
    steps:  
      - uses: actions/checkout@v3  
      - name: Setup PHP ${{ matrix.php }}  
        uses: shivammathur/setup-php@v2  
        with:  
          php-version: ${{ matrix.php }}  
  
      - name: Install dependencies  
        run: composer update  
  
      - name: Test code  
        run: composer tests  
  
      - name: Test coverage  
        run: composer tests-coverage  
  
      - name: Test coverage  
        run: composer tests-mutation

Шаблоны для issue

Так же очень хорошая практика делать шаблоны по которому клиенты вашего пакета - приложения смогу составить баг репорт или спросить про его работу

Так как в нем можно указывать инпуты которые они должны заполнить:

  • Версия пакета

  • Версия зависимости

  • Чекбокс для того чтобы подтвердить ознакомление с другими issue

Примеров может быть много но самое главное что не будет от вас ответов о том что пользователь предоставил вам нужную информацию чтобы ему помочь

Пример шаблона:

Пример
name: Bug report  
description: |  
  Something didn't work as expected? Create a report to help us improve.  
labels: [ "bug", "triage" ]  
assignees: [ ]  
body:  
  - type: markdown  
    attributes:  
      value: |  
        Example description  
  - type: input  
    id: pkg_version  
    attributes:  
      label: Package name version  
      description: Run `composer show -v | grep package/name`.  
      placeholder: "example: 1.0.0"  
    validations:  
      required: true  
  - type: input  
    id: php_version  
    attributes:  
      label: PHP version  
      description: Run `php -v`.  
      placeholder: "example: 8.4"  
    validations:  
      required: true  
  - type: textarea  
    id: what-happened  
    attributes:  
      label: What happened?  
      description: |  
        Example description  
      placeholder: I ran `php artisan migration:fresh` on prod, and then...  
    validations:  
      required: true

На выходе мы получим вот такую форму в issue:

Пример - фото

Релиз на pakagist

Описание процесса

  1. Перейдите на Packagist.

  2. Укажите ссылку на репозиторий.

  3. Дождитесь модерации.

Пакет будет автоматически обновляться при пуше в main. Для мгновенных обновлений используйте Packagist Update.

Пример - фото

Вывод

Я описал ключевые моменты создания пакета. Надеюсь, статья поможет тем, кто раньше не занимался этим.

Шаблон проекта - вы так же можете его улучшать отправив в него PR
GitHub - буду рад вашей подписки на меня и в гитхабе

Благодарю вас, что прочитали данную статью.

Tags:
Hubs:
+12
Comments6

Articles