Introducing Leapfrog for Laravel

I thought I’d write a short blog post to introduce a little project that I’ve been working on recently in my spare time. I’ve called the project “LeapFrog”, and basically it’s a UI-based tool which helps you generate basic CRUD (Create-Read-Update-Delete) boilerplate for your Laravel 5.4+ application (will be updating soon for Laravel 5.5).

LeapFrog Generator View

The Idea

The idea for the project came from looking at another fantastic tool which already helps you generate migration files more easily: Jeffrey Way’s Laravel 5 Generators. Even though this works great, I still couldn’t shake the fact that the command line seems like an awkard place to be defining model fields, table schemas, etc. I feel like as developers we’re already forced to memorize so many different commands, and I usually think long and hard before adding any new ones to my standard repertoire. So I thought: wouldn’t it be nice if there was a UI-based approach to CRUD generation?

Enter: LeapFrog.

Being the first open-source package I’ve ever created, the development process was definitely a bit of a learning curve. At the beginning I had little clue what I was doing. But after reading through the documentation on the Laravel website and various posts on Laracasts.com I decided to take the plunge.

The End Goal: To be able to point my browser to project.dev/leapfrog on a fresh Laravel install and immediately hit the ground running with CRUD!

The Source Code

The UI component was written primarly using VueJs and the CRUD generation logic using PHP and (of course) Laravel. The end result is being able to create the following screens for any entity you choose (e.g. a Person):

LeapFrog List View

LeapFrog Create View

The list/create/update views are created for you. The code which handles the actual POST/PATCH/DELETE form submissions follows a Controller-Service-Model pattern. For example, there will be a PersonController, PersonService and Person model created in this example.

Features

The views will be created along with the form HTML using YAB Inc’s FormMaker package:

<form method="post" action="{!! route('people.store') !!}">           
    {!! csrf_field() !!}
    @form_maker_table("people", config('forms.person'))
</form>

The migrations will be created depending on the fields and options that you selected, using Jeffrey Way’s Laravel 5 Generators package:

public function up()
{
    Schema::create('people', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name')->unique();
        $table->text('biography')->nullable();
        $table->integer('age')->nullable();
        $table->date('signup_date')->nullable();
        $table->boolean('is_active')->default(false);
        $table->timestamps();
    });
}

Fields marked as hidden or fillable will be automatically added to your model:

/**
 * The attributes that are mass assignable.
 *
 * @var array
 */
protected $fillable = [
    'name',
    'biography',
    'age',
    'signup_date',
    'is_active'
];

Relationship boilerplate will be automatically added to your model:

/**
 * Address
 *
 * @return Relationship
 */
public function address()
{
    return $this->belongsTo(Address::class);
}

Custom request objects will be automatically created & injected into your controller:

public function store(PersonCreateRequest $request)
{
    $result = $this->personService->create($request->all());

    ...

The service class will be automatically created (extends a BaseService class which is published by this package) with your model already injected:

class PersonService extends BaseService
{
	/**
	 * The Person model class
	 *
	 * @var App\Models\Person
	 */
	protected $model;

	/**
	 * Construct the service class
	 *
	 * @param App\Models\Person $model
	 */
	public function __construct(Person $model)
	{
	    $this->model = $model;
	}

}

Disclaimer

Click here for the full disclaimer (the usual stuff).

Thoughts?

That’s it for now. The project is still in a very early stage so I’m sure there will be bugs and other issues that need to be ironed out.

Please check out the GitHub and Packagist pages for more info.

Feel free to leave a comment or feedback and let me know what you think!

comments powered by Disqus