Composer Local Packages for Dummies

This is the simplest way to start using /packages directory in your application, that leads to cleaner code, maintainable architecture and is the best to start testing.

I wrote about pros and cons of local packages before. After year of using this in practice and mentorings I polished this approach to even simpler version that is easy to start with.

Do You Have?

Do You Want to?


There is no need to use Github, love open-source, understand package design or understand composer beyond PSR-4. No symlink issues, no forgotten composer update. Anyone can start using this!

4 Steps to first Dummy Local Package

Your application now looks similar to this:

/app
/temp
/vendor
composer.json

1. Create Packages directory

/app
/temp
+/packages
/vendor
composer.json

2. Create First Package

Start with something simple like filesystem or string utils.

/app
/temp
/packages
+   /file-system
+       /src
/vendor
composer.json

3. Move first Class to new package directory

/app
/temp
/packages
    /file-system
        /src
+           FileSystem.php
/vendor
composer.json

The best practise is to use your company or application name as namespace, e.g. EntryDo. Second part of namespace will be package name (file-system) in CamelCaps format.

namespace EntryDo\FileSystem;

final class FileSystem
{
    public function readFile(string $filePath): string
    {
        // is file or directory?
        // is readable?
        // ...
    }
}

You're awesome! Congratulations, you've just made your first local packages and you're definitely not a dummy anymore.

4. Autoload with Composer

The class is now decoupled. Now we have to tell composer where to find it!

This is your composer.json:

{
    "require": {
        "favorite/framework": "^4.0"
    },
    "autoload": {
        "classmap": "app"
    }
}

Maybe your already have PSR-4 structure (great job if you do!), but let's say you maintain an old application.


Add our new package:

{
    "require": {
        "favorite/framework": "^4.0"
    },
    "autoload": {
        "classmap": "app",
+       "psr-4": {
+           "EntryDo\FileSystem\": "packages/file-system/src
+       }
    }
}

And now the answer to most questions on StackOverflow around this topic- rebuild the composer autoload file (/vendor/autoload.php) from CLI:

composer dump
# which is shortcut for:
# composer dump-autoload

That's it. You are ready to go!

5. Bonus: Add Your First Test

Add test for a class was never easier. Create Test file for FileSystem class:

/app
/temp
/packages
    /file-system
        /src
            FileSystem.php
+       /tests
+           FileSystemTest.php
/vendor
composer.json

Add \Tests to EntryDo\FileSystem namespace:

namespace EntryDo\FileSystem\Tests;

use PHPUnit\Framework\TestCase;

final class FileSystemTest extends TestCase
{
    public function testReadFile(): void
    {
        // test readFile() method
    }
}

Update phpunit.xml to cover all tests of local packages:

<phpunit bootstrap="vendor/autoload.php" colors="true">
   <testsuite>
       <directory>packages/*/tests</directory>
   </testsuite>
</phpunit>

And run tests:

vendor/bin/phpunit

So this is the easiest way how to use composer local packages in 2018. I hope you enjoy it the same way your application does.


Happy packaging!




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!