Build a Laravel PHP Package that Seeds the Database with Fake Data

February 07, 2020
Written by
Dotun Jolaoso
Contributor
Opinions expressed by Twilio contributors are their own

How to Build a Laravel PHP Package that Seeds Fake Data

Packages primarily provide a way to add functionality to your Laravel applications and can serve as a great way of decoupling your application. The great thing about building packages is that they can easily be reused. In this tutorial, we’ll be looking at how to get started with building a Laravel package. We’ll be building a package that allows you to generate random fake data specifically in the first names, last names and email fields for a user; a simpler version of the popular Faker PHP Library. Interestingly, down the line we will make use of the same Faker Library to generate seed data.

Technical Requirements

To follow along, you’ll need the following:

  • PHP Development Environment
  • Composer globally installed

Setting up a New Package

To get started setting up a new Laravel package, we’ll be using Composer. From the terminal, cd into your project’s directory and run the following command:

$ mkdir mypackage && cd mypackage && composer init

This will prompt you with a series of questions to answer. For the first question, you’ll be prompted to pick a name for your package. This is important, as it is needed to make your package installable. Composer has a naming convention to follow when naming your projects.

vendor/package-name

vendor is usually your Github username while package-name is the name of the package you’re creating. E.g. mine will be  dotunj/randomable. dotunj is my Github username and randomable is the name of the package that we will be creating in this tutorial. For the rest of the questions asked, the default options are suitable. Once the setup is done, a composer.json file will be generated for you in the root of your project’s directory.

Autoloading the Configuration

We need to provide a namespace that all classes within our package will reference. Head over to the composer.json file and add an autoload object:

 "autoload": {
        "psr-4": {
            "Dotunj\\Randomable\\":"src/"
        }
    }

Using the psr-4 standard for autoloading, we map a namespace to a src directory we’ll be creating shortly. It’s good practice for the namespace to follow the same naming convention used for the package’s name i.e vendor/package-name.

Tip: You can read more about Autoloading here.

Generating the Package Configuration File

Our package will generate a table that will contain all of the fields and random data that we plan on supporting. The table will have a default name, however, we also need to make the table name customizable so that users of our package can provide a name they find suitable for the table.

This is where config files come in handy during package development. They allow users of your package to easily override your default configuration options.

In the root of your package directory, create a src directory.

$ mkdir src

Next run the following command from your terminal:

$ mkdir config && touch config/randomable.php

NOTE: Your package is located in the vendor folder

This will create a new config directory and subsequently create a randomable.php file inside the directory. Add the following code to the randomable.php file that was just created:

<?php

return [
    'table_name' => 'randomables',
];

Here we’ve simply defined an array with a key of table_name and a default value of randomables.

Create the Laravel Migration and Eloquent Model

Next, we need to create a migration for our database table. This is similar to how migrations typically work in a Laravel project. Inside the root of your project folder, run the following command:

$ mkdir database && mkdir database/migrations && touch database/migrations/create_randomables_table.php

This will create a new migration file for us in the database/migrations directory. Add the following code to the file:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateRandomablesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create($this->getTableName(), function (Blueprint $table) {
            $table->increments('id');
            $table->string('first_name');
            $table->string('last_name');
            $table->string('email');
            $table->timestamps();
        });
    }

    public function getTableName()
    {
        return config('randomable.table_name');
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists($this->getTableName());
    }
}

The getTableName() function returns the table name that was specified in the config file we created earlier.

Head over to the src directory and create a Models directory. Inside the Models directory, create a Randomable.php file and edit the file with the following code:

<?php

namespace Dotunj\Randomable\Models;

use Illuminate\Database\Eloquent\Model;

class Randomable extends Model
{
    protected $guarded = [];

    public function getTable()
    {
        return config('randomable.table_name');
    }

    public static function getRandomRow()
    {
        return self::inRandomOrder()->first();
    }

    public static function getRandomFirstName()
    {
        return self::getRandomRow()->first_name;
    }

    public static function getRandomLastName()
    {
        return self::getRandomRow()->last_name;
    }

    public static function getRandomEmail()
    {
        return self::getRandomRow()->email;
    }
    
}

NOTE: Don’t forget to replace the namespace with your own namespace.

Let’s go over what’s happening in this file:

  • getTable() is a method provided by Laravel that specifies the table to associate with the Model. In our case, this is what was specified in the randomable.php config file we created earlier.
  • getRandomRow() returns a random row from our table.
  • getRandomFirstName(), getRandomLastName(), getRandomEmail() all make use of the getRandomRow() function to return a random first name, last name and email respectively.

Writing Seeds for the Database

We need a way to allow users of our package to be able to seed random data once the database table has been created. To handle the generation of fake data, we’ll be using Faker. To install Faker in our package, return to the project’s root directory and run the following command:

$ composer require fzaninotto/faker

Next, create a RandomableTableSeeder.php file in the database/seeds directory and add the following code to the file:

<?php

use Faker\Factory as Faker;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class RandomableTableSeeder extends Seeder
{
    public function run()
    {
        $faker = Faker::create();

        for ($i = 1; $i < 30; $i++) {
            DB::table(config('randomable.table_name'))->insert([
                'first_name' => $faker->firstName,
                'last_name' => $faker->lastName,
                'email' => $faker->safeEmail,
            ]);
        }
    }
}

Using Faker, we generate fake data for the different fields and insert 30 records into the database using a for loop.

Facades

Facades are a common design pattern when it comes to building Laravel applications. They typically provide a static interface to classes available in the service container and a memorable syntax thereby removing the need to remember a long class name. To learn more about Facades, you can read the documentation here.

In the src directory, run the following command:

$ mkdir Facades && touch Facades/RandomableFacade.php

This will create a RandomableFacade.php file in the Facades folder. Edit the file with the following code:

<?php

namespace Dotunj\Randomable\Facades;

use Illuminate\Support\Facades\Facade;

class RandomableFacade extends Facade
{
    public static function getFacadeAccessor()
    {
        return 'randomable';
    }
}

This Facade class extends Laravel’s base Facade class and then implements the getFacadeAccessor() method which returns a string that will be resolved out of the service container.

Create the Randomable Class

This class will serve as the public interface for our package and will act as a wrapper around the Randomable model we created earlier. In the src directory, create a Randomable.php file and add the following code to the file:

<?php

namespace Dotunj\Randomable;

use Dotunj\Randomable\Models\Randomable as RandomableModel;

class Randomable
{
    public function firstName()
    {
        return RandomableModel::getRandomFirstName();
    }

    public function lastName()
    {
        return RandomableModel::getRandomLastName();
    }

    public function email()
    {
        return RandomableModel::getRandomEmail();
    }
}

Generate a Custom Service Provider

Service providers are very important when it comes to package development with Laravel. They usually serve as the entry point between your package and the Laravel application making use of your package. They are also responsible for binding classes into the service container and informing Laravel how to load package resources such as config files, views, and migrations.

Head over to the src directory and create a RandomableServiceProvider.php file. Edit the file with the following code:

<?php

namespace Dotunj\Randomable;

use Illuminate\Support\ServiceProvider;

class RandomableServiceProvider extends ServiceProvider
{
    public function boot()
    {
        if ($this->app->runningInConsole()) {
            $this->publishResources();
        }
    }

    public function register()
    {
        $this->mergeConfigFrom(__DIR__ . '/../config/randomable.php', 'randomable');

        $this->app->bind('randomable', function () {
            return new Randomable();
        });
    }

    protected function publishResources()
    {
        $this->publishes([
            __DIR__ . '/../config/randomable.php' => config_path('randomable.php'),
        ], 'randomable-config');

        $this->publishes([
            __DIR__ . '/../database/migrations/create_randomables_table.php' => database_path('migrations/' . date('Y_m_d_His', time()) . '_create_randomables_table.php'),
        ], 'randomable-migrations');

        $this->publishes([
            __DIR__ . '/../database/seeds/RandomableTableSeeder.php' => database_path('seeds/RandomableTableSeeder.php'),
        ], 'randomable-seeds');
    }
}

Typically, Service Providers in Laravel implement two methods, the boot() and register() methods. The boot() method is used to load resources such as migrations and views, while the register() method is used to bind things into the container. You can read more about Service Providers here.

In our case here, the boot() method is used to publish all our package resources such as migrations, seeders, and config file, if it is loaded via the console. The register() method calls the mergeConfigFrom() method which allows us to merge our package’s config file with the application’s config file so that values can be overridden. Then it informs Laravel that everytime the randomable string needs to be resolved out of the container, an instance of the Randomable class should be returned.

Making Your Package Discoverable in Laravel

To automatically register the facades and service provider when our package has been installed, we need to define the provider and facade in the extra section of our composer.json file. Head over to the composer.json file and add the extra section.

  "extra": {
        "laravel": {
            "providers": [
                "Dotunj\\Randomable\\RandomableServiceProvider"
            ],
            "aliases": {
                "Randomable": "Dotunj\\Randomable\\Facades\\RandomableFacade"
            }
        }
    }

Testing

To test our package, we’ll need to set up a new Laravel project and pull in the package locally. From the terminal, run the following command:

$ composer create-project --prefer-dist laravel/laravel laravel-randomable

This will set up a new project for you in the laravel-randomable directory. Since our Package isn’t currently on Packagist, we’ll have to pull it in locally. To do that, add the following code to the  composer.json file:

  "repositories": [
        {
            "type": "path",
            "url" : "../randomable"
        }
    ]

The url key is the relative path to the folder where the randomable package resides. Next, run the following command to install the package:

$ composer require dotunj/randomable

NOTE: Don’t forget to replace dotunj/randomable with the name of your package.

Publishing Configurations

To publish the config file of our package, run the following command:

$ php artisan vendor:publish --tag=randomable-config

This will add a new randomable.php file in the config directory.

Publishing Migrations and Seeds

To publish the migration file, run the following command:

$  php artisan vendor:publish --tag=randomable-migrations

To publish the seeder file, run the following command:

$ php artisan vendor:publish --tag=randomable-seeds

Next, edit the .env file with your database credentials and run the following command to execute the migrations:

$ php artisan migrate

Run the command to seed the database with some random data:

$  php artisan db:seed --class=RandomableTableSeeder

Creating the Controller

From the command line, to generate a RandomableController, run the following command:

`$ php artisan make:controller RandomableController`

This will add a new RandomableController file for us in the App\Http\Controllers directory. Edit the file with the following code:

<?php

namespace App\Http\Controllers;

use Dotunj\Randomable\Facades\RandomableFacade as Randomable;

class RandomableController extends Controller
{
    public function seedRandomData()
    {
        $firstName = Randomable::firstName();

        $lastName = Randomable::lastName();

        $email = Randomable::email();

        $result = [
            'first_name' => $firstName,
            'last_name' => $lastName,
            'email' => $email
        ];

        return response()->json($result);
    }
}

Next, add the following route to the routes/web.php file:

Route::get('/seed/random/data', 'RandomableController@seedRandomData');

Visit your app in a browser and you should see an array containing random data.

Conclusion

In this tutorial, we’ve seen how we can get started with creating a Laravel Package. From creating our custom config files, to migrations, seeders as well as Facades. We’ve covered the basic fundamentals with everything involved in building a package that can be used in any Laravel application. The code, as well as the installation instructions, are available on Github.

Name: Dotun Jolaoso

Website: https://dotunj.dev/
Github: https://github.com/Dotunj
Twitter: https://twitter.com/Dotunj_

To learn more about PHP development and Twilio, check out the following docs: