Laravel UK

The most exciting coding group in the UK

Writing Your First Laravel Package!

By Steve Popoola

Laravel is an elegant and powerful framework that give you the tools you need to build your PHP applications.

There are sometimes however, when you need specific functionality which you cannot get out of the box or where you have to solve a problem while implementing a feature common across a number of applications you have created. Rather than copy across this piece of functionality into all these applications, a better solution will be to create a package.

What Is a Laravel Package?

Simply put, a package is a bundle of code implementing a feature or functionality that can be used within an application. A stand-alone package can be installed and used in any PHP application while a Laravel-based package is created specifically for Laravel applications which enables the package to leverage on the resources and services that the framework provides. This tutorial will be focusing on the latter.

Starting Point

Before creating a package, it would be a good idea to check Packagists composer repository, to see if someone has created a package that already solves the problem or has implemented the feature you want to build. If someone has done the heavy-lifting for you, why re-invent the wheel?

Once you are sure that there is no such package or maybe the ones available do not really fit your use case, then it’s time to roll up your sleeves and build one.

The Task

We have been tasked by the management of our fictitious company to come up with the top tech quotes in 2016. In this tutorial, we will be creating a package to fetch these quotes from a fictitious api specialising in storing all quotes recorded in 2016. 


We will borrow our logic from Laravel’s artisan inspire command and our package will be named LaraQuotes.

Laravel manual defined Service providers as, “the connection points between your package and Laravel. A service provider is responsible for binding things into Laravel's service container and informing Laravel where to load package resources such as views, configuration, and localization files.”.

Understanding Service providers is therefore key to building your own package. You can read more on Service Providers at the link below; https://laravel.com/docs/5.4/providers

Let’s Begin

First we will be creating a new Laravel project. If you have installed Laravel globally, you can create a new project with the command;

laravel new laraquotes

The next thing to do is to create a folder for our package. This will live in the root directory. We have to do this for now because packages in the vendor folder are those that have been published.

Packages are created with the folder structure ‘vendor/package’. In this demo I will create my package as stevepop/laraquotes Now that we have created a home for our package, the next task is to create a composer.json for our package. From the application root, go to the package folder and run composer init.

cd packages/stevepop/laraquotes
stevepop/laraquotes » composer init

Composer will pop up with interactive prompts to help you initialise your composer.json file.

Package name (<vendor>/<name>) [steve/laraquotes]:  
stevepop/laraquotes`
Description []: A package to generate inspiring quotes
Author [Steve Popoola <stevepop@gmail.com>]
Minimum Stability []: dev
Package Type (e.g. library, project, metapackage, composer-plugin) []: - Accept default
License []: - Accept default

We do not have any dependencies, so enter ‘no’ for dependencies option. After generation, my composer.json looks like this;

"name": "stevepop/laraquotes",
    "description": "A package to generate inspiring quotes",
    "authors": [
        {
            "name": "Steve Popoola",
            "email": "stevepop@gmail.com"
        }
     ],
     "minimum-stability": "dev",
     "require": {}
}

Autoloading

For the main application to use our newly created package, we need to autoload it in the application’s own composer.json file. Within the composer.json file, there is an autoload block and within it, the psr-4 block. This is where we will add our package, so let’s do that now;

"psr-4": {
    "App\\": "app/",
    "Stevepop\\Laraquotes\\":
        "packages/stevepop/laraquotes/src"
 }

We need to do one more thing before composer autoloads our package. We need to execute composer's dump-autoload command.

stevepop/laraquotes » composer dump-autoload

Your package classes are now available for use within the application.

Service Provider

We will now create our package’s Service Provider. As earlier mentioned, the service provider is the entry point for our package. It is where our package is loaded into the application.

Laravel makes creating service providers a breeze by providing an artisan command for us to generate it.

From the root of your application run the following command;

php artisan make:provider LaraQuotesServiceProvider

By default, this would create LaraQuotesServiceProvider.php in the app\Providers folder. Since this provider is specifically for our package, we will need to copy it to our package’s src folder. Remember to change the namespace after copying the file. The namespace should be in the format Vendor\Packagename which in our case here is Stevepop\Laraquotes.

The Service Provider class contains two main methods. The boot method is used to add other services providing within the Laravel Framework. The method is called after all other service providers have been registered.

The register method is used to bind things into the service container. The manual discourages attempting to register event listeners, routes, or any other piece of functionality within this method.

Now that we have created our package’s Service Provider, we need to introduce the package to our application. This is done by adding the package in the $providers array within the config\app.php file.

'providers' => [
    …
    Stevepop\Laraquotes\LaraQuotesServiceProvider::class
 ]

Yay! Our packages’s Service provider is now loaded and we are now ready to focus on the inner workings of our amazing functionality!

Create the Command Class

The feature we are building will make use of Laravel’s console command.

Let us now generate a new command class;

  php artisan make:console QuotesCommand

This will result in the following class being generated; app/Console/Commands/QuotesCommand.php

Copy this class to the package’s src folder;

cp  app/Console/Commands/QuotesCommand.php packages/stevepop/laraquotes/src/

Updating the Command Class

Now that we have our command class, let us now start adding the relevant code. Command console classes should extend Laravel's Illuminate\Console\Command class and this has been done for us when Laravel created the class for us. Make sure that you update the namespace to our package directory, in this case by adding the following to the top of the php file containing the class.

<?php

namespace Stevepop\Laraquotes;

use Illuminate\Console\Command;

class QuotesCommand extends Command {

}

Next, we add the command name. This is the value assigned to the $name property of the class.

/**
     * The console command name.
     *
     * @var string
     */
    protected $name = 'laraquote:fetch';

Update the description property with the text describing what the command does and this is shown when php artisan is run to show all available commands.

/**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Fetch an Inspiring quote';

When our command is run at the console, Laravel will execute the code in the handle method. To see if our package is working, let us try it out by adding the following to the handle() method.

/**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle() {
        echo "I am working!";`
    }

Before Laravel can recognise our QuotesCommand class, we need to provide an entry point and you guessed right, through the Service Provider! So let us head to our LaraQuotesServiceProvider class and make this happen.

In the register method of the ServiceProvider, we add the following;

 public function register() {
    $this->commands([
            QuotesCommand::class,
         ]);
     }

In plain English, we are giving the following instruction to Laravel; “When you load my package through my Service Provider, I want you to make this class available to the application”. Now that we have that in place, Let’s just give it a try to see if everything works as it should. Run php artisan. You should see a list of artisan commands and one of them should appear as follows;

 laraquote:fetch      Fetch an Inspiring quote

If you can see that, then the service provider successfully loaded our Command class. Now when we run the command laraquote:fetch we should see the text "I am working!"

Cool! Our package works as expected. So it is time to start creating the functionality that we set out to accomplish.

Let us now create our Quote class. In real life, this class' fetch() method will be responsible for fetching quotes data from a file, database or api but for the purpose of this demo, we will create a collection of quotes from which we will fetch one at random every time the command is executed.

This class should be created in our packages's src folder. In larger packages, it is recommended to organise the folder structure in the same structure of a Laravel application. For instance if you have controllers, they should be in the package/src/controllers directory. For this tutorial however, we are placing our classes in the src folder.

<?php

  namespace Stevepop\Laraquotes;
  use Illuminate\Support\Collection;

  class Quote {
      public static function fetch() {
          return Collection::make([
                ‘Technology is a word that describes something that doesn’t work yet. - Douglas Adams’,
               ‘All this modern technology just makes people try to do everything at once. - Bill Watterson’,
          ])->random();
      }
  }

Our Quote class has a single static method fetch(). This method returns a collection of quotes chained to the random method which enables us to return one item from the collection.

Finally, we will update our QuotesCommand’s handle() method which will fire once our console command is executed by the Service Provider.

public function handle() {
     $this->comment(PHP_EOL.Quote::fetch() . PHP_EOL);
}

When you run the command again, you should see a randomly selected quote from the collection being returned to the console. Your package is now ready for use!

Publication

Your brand new shinning package cannot be used outside of your application unless you publish it. How to do that is beyond the scope of this writing however it is a trivial thing to do. All it requires is for you to push your package to your Github repository and register the package in Packagist. Once this is done, your package will be available to anyone who includes it in a composer.json file and runs composer install

Source code here: https://github.com/stevepop/laraquotes

Now go build your own amazing packages!

Learn more about package development from Laravel website https://laravel.com/docs/5.4/packages#introduction