PHP
Router Link Example In VueJs.
Router Link is a technique which helps user to switch among the pages without page refresh. It is an important aspect of building single page application(SPA). So in this post we are going to explain Read more…
Router Link is a technique which helps user to switch among the pages without page refresh. It is an important aspect of building single page application(SPA). So in this post we are going to explain Read more…
[AdSense-A]
In almost every Laravel package, there is a ServiceProvider
class responsible for registering bindings package resources such as config files, views, migrations, ...
While preparing a workshop that I gave on package development, I watched some videos of our own Laravel package training video course again. While watching the videos on using the service provider again, I had the idea to simplify how resources can be registered.
Meanwhile, I've fleshed out the idea and release it as a new package called laravel-package-tools. In this blog post, I'd like to introduce the package to you.
PackageServiceProvider
#Let's look at a service provider that registers a config file, migrations, views, translations, and a command. It uses several functions that are explained in Laravel's package development docs.
namespace YourVendorYourAwesomePackage;
use Illuminate<span class="hljs-title">Support<span class="hljs-title">ServiceProvider;
use YourVendor<span class="hljs-title">YourAwesomePackage<span class="hljs-title">Commands<span class="hljs-title">YourAwesomeCommand;
class YourAwesomePackageServiceProvider extends ServiceProvider
{
public function boot()
{
if ($this->app->runningInConsole()) {
$this->publishes([
DIR . '/../config/laravel-awesome-package.php' => config_path('laravel-awesome-package.php'),
], 'config');
<span class="hljs-keyword">$this</span>->publishes([
<span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/../resources/views'</span> => base_path(<span class="hljs-string">'resources/views/vendor/laravel-awesome-package'</span>),
], <span class="hljs-string">'views'</span>);
$migrationFileName = <span class="hljs-string">'create_package_table.php'</span>;
<span class="hljs-keyword">if</span> (! <span class="hljs-keyword">$this</span>->migrationFileExists($migrationFileName)) {
<span class="hljs-keyword">$this</span>->publishes([
<span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">"/../database/migrations/{$migrationFileName}.stub"</span> => database_path(<span class="hljs-string">'migrations/'</span> . date(<span class="hljs-string">'Y_m_d_His'</span>, time()) . <span class="hljs-string">'_'</span> . $migrationFileName),
], <span class="hljs-string">'migrations'</span>);
}
<span class="hljs-keyword">$this</span>->commands([
YourAwesomeCommand::class,
]);
}
<span class="hljs-keyword">$this</span>->loadViewsFrom(<span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/../resources/views'</span>, <span class="hljs-string">'laravel-awesome-package'</span>);
}
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">register</span><span class="hljs-params">()</span>
</span>{
<span class="hljs-keyword">$this</span>->mergeConfigFrom(<span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/../config/laravel-awesome-package.php'</span>, <span class="hljs-string">'laravel-awesome-package'</span>);
}
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">migrationFileExists</span><span class="hljs-params">(string $migrationFileName)</span>: <span class="hljs-title">bool</span>
</span>{
$len = strlen($migrationFileName);
<span class="hljs-keyword">foreach</span> (glob(database_path(<span class="hljs-string">"migrations/*.php"</span>)) <span class="hljs-keyword">as</span> $filename) {
<span class="hljs-keyword">if</span> ((substr($filename, -$len) === $migrationFileName)) {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
}
}
<span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
}
}
Our laravel-package-tools package contains a PackageServiceProvider
class .
Let extend that PackageServiceProvider
to vastly simplify the code above. The class below is equivalent to class in the previous code snippet.
namespace YourVendor<span class="hljs-title">YourAwesomePackage;
use OriginalVendor<span class="hljs-title">LaravelPackageTools<span class="hljs-title">Package;
use OriginalVendor<span class="hljs-title">LaravelPackageTools<span class="hljs-title">PackageServiceProvider;
use YourVendor<span class="hljs-title">YourAwesomePackage<span class="hljs-title">Commands<span class="hljs-title">YourAwesomeCommand;
class SkeletonServiceProvider extends PackageServiceProvider
{
public function configurePackage(Package $package): void
{
$package
->name('your-awesome-package')
->hasConfigFile()
->hasViews()
->hasMigration('create_package_table')
->hasCommand(YourAwesomeCommand::class);
}
}
That is way cleaner, right? I've already updated some of our packages to make use of our PackageServiceProvider
. Here's the service provider from laravel-backup.
namespace Spatie<span class="hljs-title">Backup;
// import statements omitted for brevity
class BackupServiceProvider extends PackageServiceProvider
{
public function configurePackage(Package $package): void
{
$package
->name('laravel-backup')
->hasConfigFile()
->hasTranslations()
->hasCommands([
BackupCommand::class,
CleanupCommand::class,
ListCommand::class,
MonitorCommand::class,
]);
}
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">packageRegistered</span><span class="hljs-params">()</span>
</span>{
<span class="hljs-keyword">$this</span>->app[<span class="hljs-string">'events'</span>]->subscribe(EventHandler::class);
<span class="hljs-keyword">$this</span>->app->singleton(ConsoleOutput::class);
<span class="hljs-keyword">$this</span>->app->bind(CleanupStrategy::class, config(<span class="hljs-string">'backup.cleanup.strategy'</span>));
}
}
To know more about the PackageServiceProvider
header over to the readme of laravel-package-tools on GitHub.
I've not PRed these changes to Laravel because the functions provided by PackageServiceProvider
assume an opinionated package structure.
To kickstart your next Laravel package, you could consider using our Laravel package skeleton, which already uses the shiny new PackageServiceProvider
out of the box. Here's a video that explains how to use the Laravel package skeleton (spoiler: it's very easy).
Be sure to take a look at this list of Laravel and PHP packages our team has released previously. I'm pretty sure there's something there for your next project.
(more…)Last week, I started using a M1 powered MacBook Air as my primary computer. It feels much faster that my previous 16″ MacBook Pro with Intel processor. Here’s a good post on how Apple made Read more…
Generating one voucher code is easy, but what if you need to generate thousands (or millions) and you need to be sure that each voucher code is unique? In this post, I will explain how Read more…
My colleague Brent makes the case for targetting and uses the latest PHP version. Read More
Frank De Jonge recently give a very nice introdution to event sourcing. Here’s the recording If you want to know more about event sourcing, you’ll be happy to know that my team is creating a Read more…
Don’t be afraid of friction when learning new things. Read More
Let’s see what CORS is actually doing, and why it’s actually our friend. Read More
Here are 5 simple Laravel tips and tricks that you can start applying and using in your Laravel applications right now! Read More