Learn how to create and distribute Laravel packages
Basic package setup and organization
my-package/
├── src/
│ ├── MyPackageServiceProvider.php
│ ├── Facades/
│ │ └── MyPackage.php
│ └── MyPackage.php
├── config/
│ └── my-package.php
├── database/
│ ├── migrations/
│ └── factories/
├── resources/
│ ├── views/
│ └── lang/
├── routes/
│ └── web.php
├── tests/
│ ├── TestCase.php
│ └── Feature/
├── composer.json
├── phpunit.xml
└── README.md
{
"name": "vendor/my-package",
"description": "My awesome Laravel package",
"type": "library",
"license": "MIT",
"autoload": {
"psr-4": {
"Vendor\\MyPackage\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Vendor\\MyPackage\\Tests\\": "tests/"
}
},
"extra": {
"laravel": {
"providers": [
"Vendor\\MyPackage\\MyPackageServiceProvider"
],
"aliases": {
"MyPackage": "Vendor\\MyPackage\\Facades\\MyPackage"
}
}
},
"require": {
"php": "^8.1",
"illuminate/support": "^10.0"
},
"require-dev": {
"orchestra/testbench": "^8.0",
"phpunit/phpunit": "^10.0"
}
}
Package registration and bootstrapping
namespace Vendor\MyPackage;
use Illuminate\Support\ServiceProvider;
class MyPackageServiceProvider extends ServiceProvider
{
public function register()
{
// Register the main class to use with the facade
$this->app->singleton('my-package', function () {
return new MyPackage();
});
// Register config
$this->mergeConfigFrom(
__DIR__.'/../config/my-package.php', 'my-package'
);
}
public function boot()
{
// Publish configuration
$this->publishes([
__DIR__.'/../config/my-package.php' => config_path('my-package.php'),
], 'config');
// Load routes
$this->loadRoutesFrom(__DIR__.'/../routes/web.php');
// Load views
$this->loadViewsFrom(__DIR__.'/../resources/views', 'my-package');
$this->publishes([
__DIR__.'/../resources/views' => resource_path('views/vendor/my-package'),
], 'views');
// Load migrations
$this->loadMigrationsFrom(__DIR__.'/../database/migrations');
$this->publishes([
__DIR__.'/../database/migrations/' => database_path('migrations')
], 'migrations');
// Load translations
$this->loadTranslationsFrom(__DIR__.'/../resources/lang', 'my-package');
$this->publishes([
__DIR__.'/../resources/lang' => resource_path('lang/vendor/my-package'),
], 'lang');
}
}
# Publish all assets
php artisan vendor:publish --provider="Vendor\MyPackage\MyPackageServiceProvider"
# Publish specific tags
php artisan vendor:publish --provider="Vendor\MyPackage\MyPackageServiceProvider" --tag="config"
php artisan vendor:publish --provider="Vendor\MyPackage\MyPackageServiceProvider" --tag="views"
Package API and settings
namespace Vendor\MyPackage\Facades;
use Illuminate\Support\Facades\Facade;
class MyPackage extends Facade
{
protected static function getFacadeAccessor()
{
return 'my-package';
}
}
// config/my-package.php
return [
'api_key' => env('MY_PACKAGE_API_KEY'),
'default_options' => [
'timeout' => 30,
'retries' => 3,
],
'cache' => [
'enabled' => true,
'ttl' => 3600,
],
];
Testing package functionality
namespace Vendor\MyPackage\Tests;
use Orchestra\Testbench\TestCase as Orchestra;
use Vendor\MyPackage\MyPackageServiceProvider;
class TestCase extends Orchestra
{
protected function getPackageProviders($app)
{
return [
MyPackageServiceProvider::class,
];
}
protected function getPackageAliases($app)
{
return [
'MyPackage' => MyPackage::class,
];
}
protected function defineEnvironment($app)
{
// Setup default configuration
$app['config']->set('my-package.api_key', 'test-key');
}
}