I found myself in the need to create a Laravel package. Even when I'm familiar with the stack I never had to do this. Well there is always a first time for everything, right?


My first step was to research how to do such a thing, fortunately Laravel has very good documentation for this. So after reading the basics I needed to set up the development environment.

Composer

I alway start my journey of creating a new php repository initializing Composer running composer init. After running the wizard it will generate something like:

{
  "name": "adro/package",
  "description": "An awesome package",
  "type": "library",
  "license": "MIT",
  "authors": [
    {
      "name": "Adro Rocker",
      "email": "me@adro.rocks"
    }
  ],
  "require": {}
}

After that you need to choose the right namespace for your package. An example would be:

"autoload": {
    "psr-4": {
        "Adro\\MyAwesomePackage\\": "src/"
    }
}

Now you are good to start coding following the Laravel documentation.

Testing code

Wait, but how do I know my code is working? Right! for that we need to set up the test suite. In my use case I chose this tools:


  • testbench, A Laravel Testing Helper for Packages Development.
  • canvas, Code Generators for Laravel Applications and Packages.
  • PHP_CodeSniffer, tokenizes PHP files and detects violations of a defined set of coding standards.


Testbench extends PHPUnit to help you test Laravel packages, so it was one of the most obvious dev dependencies to add. Since I wanted to integrate some artisan make:* commands to scaffold some stuff in my package I used Canvas. According to the documentation Canvas replicates all of the make artisan commands available in your basic Laravel application. And since I have suffer in the past reading really bad indented code I always like to set code standards for that I use PHP_CodeSniffer.

Setting up PHPUnit/Testbench

PHPUnit by default looks for a config file, normally called phpunit.xml[.dist]. This is how mine looks:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true">
  <coverage processUncoveredFiles="true">
    <include>
      <directory suffix=".php">./src</directory>
    </include>
  </coverage>
  <php>
    <env name="APP_ENV" value="testing"/>
  </php>
  <testsuites>
    <testsuite name="Adro\\MyAwesomePackage\\Tests">
      <directory>./tests</directory>
    </testsuite>
  </testsuites>
</phpunit>

The <php><env name="APP_ENV" value="testing"/></php> section is used to load environmental variables, in this case is loading the APP_ENV with the value testing

Setting up PHP_CodeSniffer

<?xml version="1.0"?>
<ruleset name="Adro coding standard">
    <description>Adro coding standard</description>

    <!-- display progress -->
    <arg value="p"/>
    <arg name="colors"/>

    <!-- inherit rules from: -->
    <rule ref="PSR12"/>
    <rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
    <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace">
        <properties>
            <property name="ignoreBlankLines" value="false"/>
        </properties>
    </rule>

    <!-- Paths to check -->
    <file>src</file>
</ruleset>

For more on how to configure CS you can read the wiki

Seeing code in action locally?

You can require a local package in a local Laravel project by defining a custom "repository" in the composer.json file.


Add the following repositories key section in composer.json file of your Laravel app. Update the "url" with the directory where your package lives:

{
  "repositories": [
    {
      "type": "path",
      "url": "../path/to/my/packages/my-awesome-package"
    }
  ]
}

You can now require your local package in the Laravel application using your chosen namespace of the package. In our example, this would be:

composer require adro/package