Step by step guide to Laravel package development
Tags: php, laravel, packagedevelopment
Published: 2018-05-25 13:20:55

---
title: Step by step guide to Laravel package development
published: true
description: Are you curious how open-source Laravel packages are developed from scratch? This is a tutorial to answer the question and help you develop one with a real example.
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/9uvr9bsjn1ml5q3rtjqz.png
tags: PHP,laravel,packagedevelopment
canonical_url: https://blog.freshbits.in/step-by-step-guide-to-laravel-package-development
---

Are you curious how open-source Laravel packages are developed from scratch? Or are you unsure whether any specific functionality makes a good use case to be a Laravel package?

Let’s talk about these and other related questions today.

We all are fans of Laravel and its ecosystem for its simplicity and extensibility. Packages have been playing a major role in moving it forward. Especially official packages by Laravel,  [Spatie](https://spatie.be/en/opensource)  ,  [Barry vd.](https://github.com/barryvdh/) , and others have made our lives and code better.

### Why you should build a Laravel Package


**Better coding skills**

Open-source is magical. Putting your code out into the public makes you a bit vulnerable at the beginning but brings out the best of you. The fear of doing something wrong prevents every bit of you from doing the  `git push origin master`  but it’s always worth it. Laracasts’ series on  [open source project management](https://laracasts.com/series/how-to-manage-an-open-source-project) can help a lot if you’re not well-versed with GitHub.

**More (and better) work**

You will build you brand leading to more work.

> "Talk is cheap. Show me the code." - Linus Torvalds (creator of Linux and Git)

As developers and clients see your code and benefit from it, you will get more recognition.

**Save time**

You will save yourself considerable amount of time when you convert a piece of code, that you are using in more than one projects, into a package. “DRY” approach isn’t a new thing. We know its benefits.

In short, open-source package development makes your developer life better.

Now that we have a better idea about the need to go ahead with package development, let’s make one together now.

On a side note, contributing to an existing solution is also a great way to start if there is already an open-source package/library of your choice.

#### A new Laravel package from scratch

`Note:`  I had said we will be building a real package. While thinking about an example, the only good option I could come up with was one of my own packages -  [Laravel Log Enhancer](https://github.com/freshbitsweb/laravel-log-enhancer). It is short enough to cover quickly as well as plays with important parts of package development to learn the basics properly.

{% youtube DQnUyQEcs_A %}

If you haven’t created any Laravel package before, I insist you to do this with me.  _It’ll be fun_. Even if you make the same package, you’ll have more confidence and will be inspired to make changes or create a new one instantly. All the steps are undoable - you’ve nothing to lose. And true learning is all about doing the things practically. Our requirements are basic. If you’re already running any Laravel app locally, you’ve it all.

Let’s start.

**1. New package directory**

Create a directory with a name of the package. I will call it  `laravel-log-enhancer`.

```
mkdir laravel-log-enhancer && cd laravel-log-enhancer 
```

**2. Love for git**

Initialize a git repository. We’ll need GitHub repo to put the package online.

```
git init
```

**3. composer.json**

Every package starts with a  `composer.json`  file. Let’s create it. The easiest way to create it is to fire the  `init`  command.

```
composer init
```

Or you can just copy it from  [this stub](https://gist.github.com/gauravmak/04badd41d58d8f27648532e93876a634) and make changes accordingly.

![Package Composer json file](https://dev-to-uploads.s3.amazonaws.com/i/t4kxstetmqwseoh7rkcf.png)

Commit the change. Not compulsory but we will do it after each unique step as a good habit.

**4. Namespace and autoloading**

We will put the main code of our package in  `src`  directory.

```
mkdir src && cd src
```

By the way, just like Laravel web app development, there are no hard rules about directory structure here but a helpful convention to follow.

We will update our  `composer.json`  file for 2 important things.

-   When a Laravel project uses our package, we can inform it about the location of the files of the package to be loaded by putting the path in PSR-4 autoloading part of  `composer.json`.
-   To make the installation easy for the developer, we will put the location of the service provider, that should be automatically detected by Laravel, in  `extra`  section of the file.

```
...
"autoload": {
    "psr-4": {
        "Freshbitsweb\\LaravelLogEnhancer\\": "src/"
    }
},
"extra": {
    "laravel": {
        "providers": [
            "Freshbitsweb\\LaravelLogEnhancer\\LaravelLogEnhancerServiceProvider"
        ]
    }
}
...
```

By  _autoload_, the parent Laravel web app knows about our base namespace i.e.  `Freshbitsweb\LaravelLogEnhancer`  and the files location which is the  `src`  directory. And Laravel’s awesome  [package discovery](https://laravel-news.com/package-auto-discovery) feature helps us remove a step from package installation process.

**5. The service provider dilemma:**

Many beginners stuck at this stage. Don’t worry. Let’s try to simplify this. A service provider is a file that can tell the parent Laravel application about various offerings of the package.

Common belief is that we always need a service provider for a package. That’s not the case. If your package doesn’t need to  _autoload_  [any resources](https://laravel.com/docs/packages#resources) in advance, it can skip the service provider. But in most of the cases, for a package to be useful enough, service provider is required.

We will use it in our case to load the default configuration options of the package as well as offer an option to export those config options to the parent Laravel web app.

```
<?php

namespace Freshbitsweb\LaravelLogEnhancer;

use Illuminate\Support\ServiceProvider;

class LaravelLogEnhancerServiceProvider extends ServiceProvider
{
    /**
     * Publishes configuration file.
     *
     * @return  void
     */
    public function boot()
    {
        $this->publishes([
            __DIR__.'/../config/laravel_log_enhancer.php' => config_path('laravel_log_enhancer.php'),
        ], 'laravel-log-enhancer-config');
    }

    /**
     * Make config publishment optional by merging the config from the package.
     *
     * @return  void
     */
    public function register()
    {
        $this->mergeConfigFrom(
            __DIR__.'/../config/laravel_log_enhancer.php',
            'laravel_log_enhancer'
        );
    }
}
```

The code is quite simple here. In the  `boot`  method, we put the code to allow the developer to export the config options by simply writing:

```
php artisan vendor:publish -tag=laravel-log-enhancer-config
```

And in the  `register`  method, we tell the Laravel app to add the config options from our file into the web app config. Commit the update and let’s create our config file next.

**6. Config options:**

As a part of the convention, we will put our config file in  `config`  directory inside root folder next to src directory.

```
mkdir config && cd config && touch laravel_log_enhancer.php 
```

Put the following code in the file.

```
<?php

return [
    'log_request_details' => true,

    'log_input_data' => true,

    'log_request_headers' => false,

    'log_session_data' => true,

    'log_memory_usage' => false,

    'log_git_data' => false,

    // You can specify the inputs from the user that should not be logged
    'ignore_input_fields' => ['password', 'confirm_password'],
];
```

This file contains few configuration options just like a regular Laravel config file. Commit.

**7. Package classes**

Final piece of code, for actual enhancement of Laravel logs, is the  `LogEnhancer.php`  file. To keep the length of the article digestible, I will directly link you to  [the actual class](https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/src/LogEnhancer.php) that you can copy. We also have  [`RequestDataProcessor.php`](https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/src/RequestDataProcessor.php) in the package. Put both of them in the  `src`  directory and you should be good to go.

**8. Other important files**

There are few other files that we need to add finally.

-   [.gitignore](https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/.gitignore)
-   [LICENSE](https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/LICENSE)
-   [README.md](https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/README.md)

README file needs a special mention here. It is the face of the package. You should be writing detailed installation steps and other notes with proper flow in this file. Go through this  [GitHub guide](https://guides.github.com/features/wikis/) for more.

Commit this change and now our package is ready to use.

What next? It’s time to release it.

#### How to release the package

If you haven’t pushed the package code to GitHub, do it first. If you don’t know how,  [this article](https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/) can help.

Then, head over to  [Packagist](https://packagist.org/) , create an account or sign in, Click on Submit, specify the GitHub repo URL, … Steps are quite easy and self-explanatory. You should also enable Auto update of the package and consider  [Semantic versioning](https://semver.org/) and  [releasing](https://help.github.com/articles/creating-releases/) .

![Packagist screenshot](https://dev-to-uploads.s3.amazonaws.com/i/euf25jnzvbbh3hlziyty.png)

**Congrats.**  We’re done. Breath for a few minutes. There’s more.

Next, there are many other things are not part of the package development but are important for the development lifecycle and maintenance. Let’s go through them quickly.

#### How to use the package locally

We don’t have to push the updates online before testing it locally. Composer repositories path to the rescue.

Not just the package, we can do it with any repository. Here’s a  [great article](https://tighten.co/blog/testing-laravel-framework-changes-locally-before-submitting-a-pull-request) explaining the details.

Let’s do it. Install a fresh Laravel app next to your package directory.

```
laravel new laravel-with-package
```

Make changes in it’s  `composer.json`  file

```
...
"repositories": [
    {
        "type": "path",
        "url": "../laravel-log-enhancer"
    }
],
...
```

Install the package by firing the following command.

```
composer require gauravmak/laravel-log-enhancer
```

Complete the  [installation steps](https://github.com/freshbitsweb/laravel-log-enhancer#installation) and you can use the package now.

#### Testing

> “I find that weeks of coding and testing can save me hours of planning.” -
 Unknown

They say - do not use a package without tests. They’re right. As the package gets bigger in size and more contributors enter the scene, some random commit can break the code functionality somewhere down the line. And we never want it to happen, right?

And it’ not hard. All we need to do it to check if the package is doing what it is supposed to do after every change/commit. In this package, we are adding processors to the Monolog handlers so that more data can be logged.

Unfortunately, as of now, Monolog doesn’t provide a method to fetch the processors of a handler so we are limited but let’s create a base of the testing for this package so that you know how to add tests to your custom package.

To start, we will add requirements to the  `composer.json`  file.

```
...
"require-dev": {
    "phpunit/phpunit": "^7.0",
    "orchestra/testbench": "~3.6.0"
 },
 "autoload-dev": {
    "psr-4": {
        "Freshbitsweb\\LaravelLogEnhancer\\Test\\": "tests"
    }
 },
 ...
```

We are basically testing a package which is outside a Laravel app.  [orchestral/testbench](https://github.com/orchestral/testbench) is a great package which can add the necessary dependencies so that we can test it as if we have all the Laravel goodies.

I have also added the following files to make the base of testing for our app.

-   [phpunit.xml.dist](https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/phpunit.xml.dist)
-   [LogEnhancerTest.php](https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/tests/LogEnhancerTest.php)
-   [TestCase.php](https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/tests/TestCase.php)

Go through the README file of the testbench package for all details about how we can interact with Laravel while testing our package.

#### Integrations

There are so many helpful tools that integrate with GitHub repo and help us maintain the packages/libraries easily.

I suggest  [Travis CI](https://github.com/marketplace/travis-ci) for testing the package after each update and  [StyleCI](https://github.com/marketplace/styleci) for maintaing the code style.

I have integrated StyleCI in the package already. You should also consider  [adding badges](https://poser.pugx.org/) to the README file.

![Package Badges](https://dev-to-uploads.s3.amazonaws.com/i/kujka3mxmuct6g7x38u2.png)

#### Secret sauce of a successful package

You reap the benefits of making the package when more and more developers use it. And for that, there are so many factors starting from the basic idea behind the package to the stability and age of the package (stars).

If I were to decide on most important point for that, it would be the  _developer friendliness_  of the package. Yes, the exact reason why Laravel is popular.

Try to minimize the installation steps and the code that is required to use the package. Plus, it has to be  **readable enough**  that it doen’t need to annotated with long comments.

For example,

```
$users = User::with('roles')->get();
```

So simple, we know this operation involves join queries and other stuff. Still, you like to write it and read it. Do things on a similar level.

#### Final notes

That’s it for the day. We learned why package development is good for everyone and how to do it step-by-step using a real example. If you have any questions or get stuck anywhere, just add a comment below, I would be happy to help.

And If you think this can help other Laravel developers in your online network, I’d be happy to see you  [sharing](https://twitter.com/intent/tweet?text=%F0%9F%94%A5Checkout%20step%20by%20step%20guide%20to%20Laravel%20package%20development%20%F0%9F%93%A6%20with%20a%20real%20example.&url=https://dev.to/gauravmak/step-by-step-guide-to-laravel-package-development-4nj1&via=gauravmakhecha&related=laravelphp&hashtags=laravel) this with them. Thanks.