PLATFORM
  • Tails

    Create websites with TailwindCSS

  • Blocks

    Design blocks for your website

  • Wave

    Start building the next great SAAS

  • Pines

    Alpine & Tailwind UI Library

  • Auth

    Plug'n Play Authentication for Laravel

  • Designer comingsoon

    Create website designs with AI

  • DevBlog comingsoon

    Blog platform for developers

  • Static

    Build a simple static website

  • SaaS Adventure

    21-day program to build a SAAS

Question By
Solved

Updated article? - How to create a Laravel Package

Solved
chrisd

Jul 21st, 2024 03:12 PM

Hi, Is there an updated article/video/guide for "How to create a Laravel Package"

I'm not sure if I'm doing something wrong, or if some of the steps and details are no longer accurate.

Thanks, Chris

bobbyiliev

Jul 22nd, 2024 01:31 AM

Best Answer

Hey Chris!

What I've been doing lately is to use the Spatie Laravel Package toolkit repo:

https://github.com/spatie/laravel-package-tools

But in general, here is a guide on how to do this from scratch:

Prerequisites:

  • PHP 8.2 or higher
  • Composer
  • Git
  • Basic knowledge of Laravel and PHP
  • A code editor (e.g., Visual Studio Code, PhpStorm)

Step 1 — Setting Up the Development Environment

First, ensure you have the necessary tools installed:

  1. Install PHP 8.2 or higher:

    sudo apt update
    sudo apt install php8.2 php8.2-cli php8.2-mbstring php8.2-curl php8.2-mysql php8.2-xml
    
  2. Install Composer:

    curl -sS https://getcomposer.org/installer | php
    sudo mv composer.phar /usr/local/bin/composer
    
  3. Install Git:

    sudo apt install git
    

To test your package, create a new Laravel project:

composer create-project laravel/laravel example-app
cd example-app

Step 2 — Creating the Package Structure

Choose a name for your package following the vendor-name/package-name convention. We'll use acme/blog-package.

Create the package directory structure:

mkdir -p ~/packages/acme/blog-package/{src,config,database,resources,tests}
cd ~/packages/acme/blog-package

This creates the following structure:

acme/blog-package/
├── src/
├── config/
├── database/
├── resources/
└── tests/

Step 3 — Initializing the Package

Initialize Composer for your package:

composer init

Follow the prompts to set up your composer.json. Here's a detailed example:

{
    "name": "acme/blog-package",
    "description": "A comprehensive blog package for Laravel",
    "type": "library",
    "license": "MIT",
    "autoload": {
        "psr-4": {
            "Acme\\BlogPackage\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Acme\\BlogPackage\\Tests\\": "tests/"
        }
    },
    "authors": [
        {
            "name": "Your Name",
            "email": "[email protected]"
        }
    ],
    "require": {
        "php": "^8.2",
        "illuminate/support": "^11.0"
    },
    "require-dev": {
        "orchestra/testbench": "^9.0",
        "phpunit/phpunit": "^10.0"
    },
    "extra": {
        "laravel": {
            "providers": [
                "Acme\\BlogPackage\\BlogPackageServiceProvider"
            ]
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true
}

After creating the composer.json, run:

composer update

Step 4 — Creating the Service Provider

Create a new file src/BlogPackageServiceProvider.php:

<?php

namespace Acme\BlogPackage;

use Illuminate\Support\ServiceProvider;

class BlogPackageServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->mergeConfigFrom(__DIR__.'/../config/blog-package.php', 'blog-package');
    }

    public function boot()
    {
        // Publish configuration
        $this->publishes([
            __DIR__.'/../config/blog-package.php' => config_path('blog-package.php'),
        ], 'config');

        // Load migrations
        $this->loadMigrationsFrom(__DIR__.'/../database/migrations');

        // Load routes
        $this->loadRoutesFrom(__DIR__.'/../routes/web.php');

        // Load views
        $this->loadViewsFrom(__DIR__.'/../resources/views', 'blog-package');
    }
}

Step 5 — Developing Package Features

Let's add core functionality to our blog package:

  1. Create a Post model in src/Models/Post.php:
<?php

namespace Acme\BlogPackage\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $fillable = ['title', 'content'];
}
  1. Create a PostController in src/Http/Controllers/PostController.php:
<?php

namespace Acme\BlogPackage\Http\Controllers;

use Acme\BlogPackage\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::all();
        return view('blog-package::posts.index', compact('posts'));
    }

    public function store(Request $request)
    {
        $validatedData = $request->validate([
            'title' => 'required|max:255',
            'content' => 'required',
        ]);

        Post::create($validatedData);

        return redirect()->route('posts.index');
    }

    // Add other CRUD methods as needed
}
  1. Create routes in routes/web.php:
<?php

use Acme\BlogPackage\Http\Controllers\PostController;
use Illuminate\Support\Facades\Route;

Route::group(['middleware' => ['web']], function () {
    Route::resource('posts', PostController::class);
});

Step 6 — Adding Configuration

Create a config file config/blog-package.php:

<?php

return [
    'posts_table' => 'posts',
    'posts_per_page' => 10,
    'admin_email' => '[email protected]',
];

Step 7 — Creating Database Migrations

Create a migration for the posts table:

mkdir -p database/migrations
touch database/migrations/2024_07_22_000000_create_posts_table.php

Edit the migration file:

<?php

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

class CreatePostsTable extends Migration
{
    public function up()
    {
        Schema::create(config('blog-package.posts_table'), function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('content');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists(config('blog-package.posts_table'));
    }
}

Step 8 — Creating Views

Create views for your package:

mkdir -p resources/views/posts
touch resources/views/posts/index.blade.php

Edit resources/views/posts/index.blade.php:

@extends('layouts.app')

@section('content')
    <h1>Blog Posts</h1>
    @foreach($posts as $post)
        <div>
            <h2>{{ $post->title }}</h2>
            <p>{{ Str::limit($post->content, 100) }}</p>
        </div>
    @endforeach
@endsection

Step 9 — Writing Tests

Create a test file tests/Feature/PostTest.php:

<?php

namespace Acme\BlogPackage\Tests\Feature;

use Acme\BlogPackage\Models\Post;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Orchestra\Testbench\TestCase;

class PostTest extends TestCase
{
    use RefreshDatabase;

    protected function getPackageProviders($app)
    {
        return ['Acme\BlogPackage\BlogPackageServiceProvider'];
    }

    /** @test */
    public function it_can_create_a_post()
    {
        $post = Post::create([
            'title' => 'Test Post',
            'content' => 'This is a test post.',
        ]);

        $this->assertDatabaseHas('posts', [
            'title' => 'Test Post',
            'content' => 'This is a test post.',
        ]);
    }

    // Add more tests as needed
}

To run tests:

./vendor/bin/phpunit

Step 10 — Documentation

Create a comprehensive README.md file in your package root. Include:

  1. Package description
  2. Installation instructions
  3. Configuration options
  4. Usage examples
  5. Testing instructions
  6. Contribution guidelines
  7. License information

Step 11 — Publishing Your Package

  1. Initialize a Git repository:

    git init
    git add .
    git commit -m "Initial commit"
    
  2. Create a GitHub repository and push your code:

    git remote add origin https://github.com/yourusername/blog-package.git
    git push -u origin main
    
  3. Tag a release:

    git tag 1.0.0
    git push --tags
    
  4. Submit your package to Packagist:

    • Sign up for a Packagist account
    • Click "Submit Package"
    • Enter your GitHub repository URL

Step 12 — Using Your Package

To use your package in a Laravel project:

  1. Add it to composer.json:

    "require": {
        "acme/blog-package": "^1.0"
    }
    
  2. Run composer update

  3. Publish the package assets:

    php artisan vendor:publish --provider="Acme\BlogPackage\BlogPackageServiceProvider"
    
  4. Run migrations:

    php artisan migrate
    
  5. Use the package features in your Laravel application.

Conclusion

You've now created a comprehensive Laravel package with models, controllers, views, migrations, and tests. Remember to:

  • Keep your package well-documented
  • Write thorough tests
  • Follow Laravel's coding standards
  • Regularly update your package for new Laravel versions
Report
1