Composer Local Packages for Dummies

Found a typo? Edit me

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!


Have you find this post useful? Do you want more?

Follow me on Twitter, RSS or support me on GitHub Sponsors.