This article is intended for those who have never done package projects in bare PHP for their needs before.
I want to share with you my experience, which I encountered, and provide a template that I wrote for packages/projects.:
https://github.com/deniskorbakov/skeleton-php-docker
I will be very glad to receive an asterisk on GitHub and feedback after reading the article!
How to build a project
Project structure
Classic construction of projects written in php
Example
,── src # Directory of your package
,── Dir1 # Directory for internal logic
│ └── PackageClass.php # A class for external use
,── tests # Directory for tests
│ ├─ Fixtures
│ ├─ Unit
This format is followed in almost all projects — these are key directories. However, you can create additional folders to bring the logic of individual parts of the application into your layers.
Folder names can be any, but it's better to follow generally accepted practices to make it easier for other developers to navigate your code.
Example of possible directories:
-
scripts/
— scripts for assembly, deployment, or other tasks. -
assets/
— static files (styles, scripts, images). -
.docker/
— Docker configuration (Dockerfile, Docker Compose). -
public/
is the entry point for the web server (if the package includes a web interface). -
config/
— application configuration files.
Composer
Basic composer structure
You can read more about the setup here.
Key parameters when creating a package:
name/description/keywords:
Example
"name": "deniskorbakov/skeleton-php-docker",
"description": "A skeleton php libs with docker",
"keywords": ["php", "skeleton", "package", "docker"],
-
name' is the package name in the
vendor/package` format. -
description
— a brief description of the functionality. - `keywords' — tags for searching in Packagist.
require:
Example
"require": {
"php": ">=8.2"
},
Specifies the minimum PHP version and dependencies, without which the package does not work.
require-dev:
Example
"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"
},
Dependencies for development (testing, static analysis).
autoload
Example
"autoload": {
"psr-4": {
"DenisKorbakov\\SkeletonPhpDocker\\": "src/"
}
},
Configure auto-upload for your package.
Useful commands and scripts
Commands:
-
composer validate
— validating the validity of `composer.json'. - `composer outdated' — search for outdated dependencies.
Example scripts:
Example
"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"
},
Usage: `composer tests' — running tests.
Static analyzers and linters
Why are they needed
Each of us wants to stick to good quality from the code, but endless reviews pointing out the same formatting errors can annoy people with each other, and at least linters have become the solution to this problem.
Linter is a tool for automatic code analysis for compliance with design standards.
Static analyzers help to find errors before running the code, improving its reliability.
Static Analyzer is a tool that checks code for errors, vulnerabilities, and antipatterns without executing it.
Implementing these tools in older projects can be difficult, so sometimes it's wise to apply them only to modified files.
PHPstan
One of the most popular analyzers for PHP. Its main advantage is strictness levels (from 0 to 9). The higher the level, the more thorough the check.
Useful plugins:
-
cognitive-complexity — evaluates the complexity of the code.
Code complexity is a metric that shows how difficult the code is to understand and maintain.
PHP_CodeSniffer (PHPCS)
Checks the code for compliance with the standards (PSR-12, PSR-2). You can set up your own rules.
Rector
A tool for automatic refactoring. For example, it can update the syntax from PHP 7.4 to 8.2.
Testing
You should never trust yourself, much less your code
Tests help to make sure that the code is working as expected.
Pest
I chose Pest instead of PHPUnit because of the more concise syntax. However, it has a disadvantage: syntax highlighting only works with the official plugin.
GitHub Actions
Templates for issue
It is also a very good practice to make templates for which the clients of your application package will be able to compile a bug report or ask about its work.
Since it is possible to specify the inputs that they should fill in.:
- Package version
- Dependency version
- A checkbox to confirm familiarization with other issues
There may be many examples, but the most important thing is that there will be no answers from you that the user has provided you with the necessary information to help him
At the output, we will get this form in the issue:
An example is a photo
Release on pakagist
Description of the process
- Go to Packagist.
- Provide a link to the repository.
- Wait for moderation.
The package will be automatically updated when you push it to main
. For instant updates, use Packagist Update.
An example is a photo
Output
I have described the key points of creating the package. I hope this article will help those who have not done this before.
Project Template - you can also improve it by sending PR to it.
GitHub - I will be glad to receive your subscription to me and in github
Thank you for reading this article.
Top comments (3)
I think you will turn people people off creating packages, with all the optional thing you see as necessary.
Making a codebase a package is nothing more than running
composer init
, answer some questions, generate composer.json, push the code to Github/BitBucket/GitLab, log in to packagist, link the repository.The autoload ps4 section in composer.json is not needed. You could have just a package with namespaced functions.
Testing frameworks and static analytics tools are a good practice, but not needed.
Github actions are useless if you pick another git service.
side node:
| Pest instead of PHPUnit
Pest uses PHPUnit.
you are absolutely right, in this article I simply described my process of creating a package
thanks for the feedback
Nice posting, could you share your email address? I'd like to talk to you