PHP
Making our Laravel test suite in Oh Dear ready for parallel testing
Using the new parallel testing feature that recently landed in Laravel, we managed to run the Oh Dear testsuite about four times faster. Read More
Using the new parallel testing feature that recently landed in Laravel, we managed to run the Oh Dear testsuite about four times faster. Read More
Using @LaravelLivewire it is incredibly easy to display real-time progress of batched jobs! ð¥ Just drop in this simple trait & blade component and you’re off to the races #hottip pic.twitter.com/I6K1zalzeJ — Willem Leuverink (@gwleuverink) Read more…
PHP 8.1 is currently in active development and will probably be released somewhere around the end of November 2021. We already know some features, changes and deprecations, so let’s go through them one by one. Read more…
[AdSense-A]
Using our laravel-mail-preview package, you can quickly display mails that are sent by your Laravel application in your browser.
Today, we've released v5 of the package. In this blog post, I'd like to tell you all about it.
This package was not originally created by our team, but by Mohamed Said. Ever since Mohamed released it, we've been using it in several of our projects. Because we wanted to modernize the package, and Mohamed didn't have time to do this, Mohamed graciously decided to hand over the package to us. We'd like to thank Mohamed for entrusting his work to us.
If you were already using themsaid/laravel-mail-preview
v4, then the only thing you need to do is change that in your composer.json
to spatie/laravel-mail-preview
v4. The API is identical; nothing has changed in the v4 version.
A new major release of spatie/laravel-mail-preview, v5, was released today. This version is a rewrite v4 using the latest and greatest Laravel features.
The core functionality has remained the same. Whenever a mail is sent in your application, the package will inject a small overlay with a link to that sent mail. This is what that overlay looks like.
This allows you to test out the mail in your browser quickly. This is pretty handy when using the site locally. For example, when you want to change your password, you can simply submit the forgot password form. The link to the mail will be displayed in your browser. When you click it, you see the mail's content, and you can click the reset password link. So, you can use the entire e-mail flow without leaving your browser.
This package is also convenient in Dusk tests. Using the same scenario as above, you can quickly write a Dusk test to test that reset password flow. You just have to click links using the automated browser in your test.
We've made sure that the package is extensible, you can publish the views to customize that overlay and how the content of a mail is displayed. When a mail is stored, an event is fired, so you can listen for that to perform custom logic.
Additionally, the package will also store any sent mails in the storage
directory of your app. Two versions will be stored. The HTML
version can be displayed in the browser, the eml
version can be opened in any modern e-mail client. This allows you to see how the mail looks like in your particular e-mail client.
Right now, the package only has the feature set that Mohamed initially coded up. We've got some features in mind that we'll add to the package soon to make it even easier to test your e-mails. Keep an eye out on the repo.
Be sure, to also take a look at this list of packages that our team has created previously.
Thanks again Mohamed for entrusting us with your great package. We'll take good care of it!
(more…)Here’s a simple approach on how to use cookies with AlpineJS Read More
Learn how to deploy your Laravel application without any down-time using Github Actions. This technique works for almost any application (Symfony, WordPress, you name it). Read More
In this post, Kai takes a look at how you can write tests to ensure consistent behavior across all implementations of an interface. Read More
Here is the recording of Laravel World Wide Meetup #5. Tony Messias showed the magic of Hotwire in Laravel. Kevin McKee shared an very elegant way to implement single database multi tenancy.
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…)