The first public idea about local packages was published over 3 years ago after 1 year of internal testing.
How do they stand in 2020? How people use it wrong? Are they still the best option to keep low complexity in huge projects?
Just a reminder: what are local packages?
Local packages are decoupled parts of code, located in own packages/<package-name>
directory:
/app
/packages
/file-system
/src
FileSystem.php
/tests
FileSystemTest.php
/vendor
composer.json
And loaded in composer.json
with its PSR-4 namespace:
{
"require": {
"favorite/framework": "^5.0"
},
"autoload": {
"psr-4": {
"App\\FileSystem\\": "packages/file-system/src"
}
},
"autoload-dev": {
"psr-4": {
"App\\FileSystem\\Tests\\": "packages/file-system/tests"
}
}
}
Simple.
Do you want to know more? Look at Composer Local Packages for Dummies.
/src
Directory/packages
/file-system
FileSystem.php
❌
/packages
/file-system
/src
FileSystem.php
✅
{
"autoload": {
"psr-4": {
"Packages\\": "packages"
}
}
}
❌
{
"autoload": {
"psr-4": {
"Packages\\SpecificPackage\\": "packages/specific-package/src"
}
}
}
✅
/packages
/FileSystem
/src
FileSystem.php
❌
/packages
/file-system
/src
FileSystem.php
✅
composer.json
in Packages/packages
/file-system
/src
FileSystem.php
composer.json
❌
/packages
/file-system
/src
FileSystem.php
This is only useful in case of monorepo that splits packages, e.g. Symfony, Symplify. Not for local packages.
✅
composer.json
:{
"autoload": {
"psr-4": {
"App\\FileSystem\\": "packages/file-system/src",
"App\\Auth\\": "packages/auth/src"
}
}
}
/app
separated.dash-format
for directory paths.CamelCase
for namespaces.packages/<package-name>/src
and packages/<package-name>/tests
directory convention.composer.json
to autoload them all.phpunit.xml
to run test on them all.<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
>
<testsuites>
<testsuite name="main">
<directory>tests</directory>
<directory>packages/*/tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist addUncoveredFilesFromWhitelist="false">
<directory>src</directory>
<directory suffix=".php">packages/*/src</directory>
</whitelist>
</filter>
</phpunit>
I've started to test this in Lekarna.cz, 6 years old project, where they still use it. Elasticr and Recruit.is adopted local packages in ~2018, still using it.
The code is much cleaner, comfortable to dive in, and refactor.
If you're careful about all the issues above, there is nothing to stop you from making it work! Give it a try, your future team will thank you.
Happy coding!
Do you learn from my contents or use open-souce packages like Rector every day?
Consider supporting it on GitHub Sponsors.
I'd really appreciate it!