package

All my posts about package.

Automatically generate a sitemap in Laravel original

by Freek Van der Herten – 7 minute read

Today my company released a package called laravel-sitemap. There are already a lot of excellent sitemap packages out there. They all have in common that you have to manually add links that must appear in the sitemap. With our new package that isn't required. It can automatically build up a sitemap…

Read more

A package to easily work with regex in PHP original

by Freek Van der Herten – 2 minute read

PHP offers some functions to work with regular expressions, most notably preg_match, preg_match_all and preg_replace. Unfortunately those functions are a bit hard to use. Take preg_match_all for example, it requires you to pass in an array by reference to get all the matches. When something goes…

Read more

Join 9,500+ smart developers

Get my monthly newsletter with what I learn from running Spatie, building Oh Dear, and maintaining 300+ open source packages. Practical takes on Laravel, PHP, and AI that you can actually use.

No spam. Unsubscribe anytime. You can also follow me on X.

Some handy collection macros original

by Freek Van der Herten – 4 minute read

Laravel's collection class is truly wonderful. It contains a lot of handy methods and you can create some very elegant code with it. In client projects I found myself adding the same macro's over and over again. That's why my colleague Seb and I took some time to create a package aptly called…

Read more

Comparing laravel-mediable with laravel-medialibrary

Laravel-Mediable is a package to upload and handle all sorts of files (aka media) in a Laravel app. It was built by a Canadian based web agency called Plank.

With it you can do things like this:

$media = MediaUploader::fromSource($request->file('thumb'))
    ->toDestination('uploads', 'post/thumbnails')
    ->upload();

$post = Post::create($this->request->input());
$post->attachMedia($media, ['thumbnail']);

Pretty cool. You can read more on the way and how the package was built in an introductory post on the Plank blog.

At Spatie we've also built our own solution for handling media. In Plank's blogpost Sean lists these differences between their package and our Medialibrary.

spatie/laravel-medialibrary plank/laravel-mediable
Relationship many-to-one polymorphic, each media record is owned by one related model many-to-many polymorphic, each media record can connect to any number of related models, and vice versa.
Filesystem Files are stored in directories named after the media id relative to the disk root Files can be stored anywhere on the disk
Association Identifier Each media record belongs to one "collection" Media can be attached to a model with any number of "tags"
Aggregate Types Support for images and pdfs Configurable support for any number of custom types
Miscellaneous Features Glide manipulations Synchronization commands

Since our medialibary was introduced I've been asked from time to time why our medialibrary uses a many-to-one polymorphic relationship. The answer is: simplicity.

A previous iteration of our Blender CMS (a version that used Zend Framework 1 instead of Laravel ?) had a screen where the user could pick a file from all uploaded files (it looked much like this wordpress screen). We saw that, after having set up a lot of sites with Blender, that almost none of our clients used that screen...

In our projects we also see that our clients mostly need to attach an image, or a pdf or whatever, ... to only one model (for instance a news item). It rarely happens that a client wants to attach the same file to different models.

In our code we want to handle that use case as simple as possible and that's why we preferred using a many-to-one relation over a many-to-many relation. All the other differences listed in Plank's post are caused by the same reasoning, we preferred simplicity and ease of use over flexibility.

If you're looking for a good solution to handle media in a Laravel app I suggest you take a look at both our Medialibrary and Plank's Mediable package. Both packages are good at what they do. Pick the one that best fits your project (and just feels good to you).

Read more

Validating SSL certificates with PHP

With vanilla PHP it's possible to check of if the SSL certificate of a given site is valid. But it's kinda madness to do it. Let's look at the code required:

<br />// Step 1: downloading the certificate from the site
$streamContext = stream_context_create([
    'ssl' => [
        'capture_peer_cert' => true,
    ],
]);

$client = stream_socket_client(
    "ssl://spatie.be:443",
    $errorNumber,
    $errorDescription,
    $timeout,
    STREAM_CLIENT_CONNECT,
    $streamContext);

$response = stream_context_get_params($client);

$certificateProperties = openssl_x509_parse($response['options']['ssl']['peer_certificate']);

// Step 2: parsing the certificate

/*
* I'm not even going to type out the further code needed.
*
* `$certificateProperties` has two keys `validFrom_time_t` and `validTo_time_t`. 
* Those keys contain the UTC representation of the date.
* You will need to check if the current date is between those dates.
*/ 

What. The. Actual. F. Let's fix this!

We've released a new package named spatie/ssl-certificate that makes checking the SSL certificate of a site laughably easy. Let's take a look at the code:

$certificate = SslCertificate::createForHostName('spatie.be');
$certificate->isValid(); // returns true if the certificate is currently valid

Boom, done.

The package has a few more methods that makes working with an SSL certificate a breeze:

$certificate->getIssuer(); // returns "Let's Encrypt Authority X3"

$certificate->getDomain(); // returns "spatie.be"

//A certificate can cover multiple (sub)domains. Here's how to get them.
$certificate->getAdditionalDomains(); // returns ["spatie.be", "www.spatie.be]

$this->certificate->validFromDate(); // returns an instance of Carbon

$certificate->getExpirationDate(); // returns an instance of Carbon

You can also use isValid to determine if a given domain is covered by the certificate. Of course it'll keep checking if the current datetime is between validFromDate and expirationDate.

$this->certificate->isValid('spatie.be'); // returns true
$this->certificate->isValid('laravel.com'); // returns false

The source code of the package is available on GitHub. My company has made many more PHP framework agnostic, Laravel and JavaScript packages in the past. Take a look at the open source page at our site to see if we've made anything that could be of use to you.

Read more

Processing a csv file in Laravel original

by Freek Van der Herten – 2 minute read

From time to time I need to process a csv file. PHP provides a fgetcsvfunction to help with that task. Unfortunately this is a very basic function. It will not, for instance, recognize a header column as such. In this quick post I'll show how using the excellent laravel-excel package (which can…

Read more

A package to log activity in a Laravel app original

by Freek Van der Herten – 4 minute read

In your apps there's probably a lot going on. Users log in and out, they create, update and delete content, mails get sent and so on. For an administrator of an app these events provide useful insights. In almost every project we make at Spatie we log these events and show them in the admin-section…

Read more

Make your Laravel app comply with the crazy EU cookie law

All sites owned by EU citizens or targeted towards EU citizens must comply to a crazy EU law. This law requires a dialog to be displayed to inform the users of your websites how cookies are being used. You can read more info on the legislation on the site of the European Commission. The newest Laravel package made by my colleagues at Spatie and myself makes your app compliant with that law.

Once installed the package will render the following dialog that, when styled, will look very much like this one: 68747470733a2f2f7370617469652e6769746875622e696f2f6c61726176656c2d636f6f6b69652d636f6e73656e742f696d616765732f6469616c6f672e706e67

When the user clicks "Allow cookies" a laravel_cookie_consent cookie will be set and the dialog will be removed from the DOM. On the next request Laravel will notice that the laravel_cookie_consent has been set and will not display the dialog again.

We've made it easy to customize the texts shown by the dialog. You can also make changes to the dialog or JavaScript itself.

The legislation is pretty very vague on how to display the warning, which texts are necessary, and what options you need to provide. This package will go a long way towards compliance, but if you want to be 100% sure that your website is ok, you should consult a legal expert.

Take a look at the package on GitHub to learn how to install the package and which options it provides. If you like it, be sure to check out our full list of Laravel packages.

Read more

Laravel Analytics v2 has been released original

by Freek Van der Herten – 2 minute read

One of our more popular packages is laravel-analytics. The package makes it easy to fetch information such as pageviews, top referrers, etc... from the Google Analytics API. In our Blender-based projects we use the fetched data to display a nice chart in the admin section: Laravel-analytics is one…

Read more

A Blade directive to export PHP variables to JavaScript original

by Freek Van der Herten – 1 minute read

Today we released our new package called laravel-blade-javascript. It provides you with a javascript Blade directive to export PHP variables to JavaScript. So it basically does the same as Jeffrey Way's popular PHP-Vars-To-Js-Transformer package but instead of exporting variables in the controller…

Read more

A package to determine which track a last.fm user is playing original

by Freek Van der Herten – 1 minute read

If you've been reading the last couple of posts on this blog then you'll know we're busy building a dashboard. I think it's fair to say that everyone at Spatie is music addict. We have the unwritten rule that whoever who comes in first at the office is DJ for the day. One of the things we'd like to…

Read more

A package to manage events on a Google Calendar original

by Freek Van der Herten – 3 minute read

Like previously mentioned we're currently building a new dashboard to display on our wall mounted TV at the office. One of the things we want to show on that dashboard are important events for our company. Things like when a site goes live, when there's a conference we're going to visit, when we're…

Read more

How to setup and use the Google Calendar API original

by Freek Van der Herten – 4 minute read

For a project I'm working on I needed to interact with a Google Calendar. If you've ever worked with some API's by Google then you know their documentation can be very confusing. It's not that they don't have documentation, but code examples of common use cases are simply not present. You must wade…

Read more

Easily integrate MailChimp in Laravel 5 original

by Freek Van der Herten – 2 minute read

Today we released a new major version of our laravel-newsletter package. This package makes it easy to integrate MailChimp in your Laravel app. Under the hood V3 of the MailChimp API is used. If you're used the older version of our package be sure to upgrade by the end of this year: MailChimp will…

Read more

Laravel medialibrary hits v4 original

by Freek Van der Herten – 2 minute read

Today we tagged a new major version of laravel-medialibrary. In case you're not familiar with this package here's a quick rundown of what it can do. The package can associate all sorts of files with Eloquent models. It provides a simple, fluent API to work with. Here's a quick example: $newsItem =…

Read more

Making Eloquent models translatable original

by Freek Van der Herten – 2 minute read

Spatie, the company where I work, is located in Belgium. Although our country is quite small, there are three official languages: Dutch, French and German. That's why nearly all of our projects are multilingual. In most projects we used to rely on Dimitris Savvopoulos popular translatable package to…

Read more

Easily store some loose values

For a site I was working on the admin should be able to switch on or off a form that's displayed on the homepage. Question: where's the best place to store the value of that switch? Creating a table and column for it in the database seems overkill. Putting it in a never expiring cache does not feel right. I think the best place to store such value is just write it to a simple file.

In the example above only one value needed to be stored, but for other projects there sometimes were two or three of them. Over the years I found myself writing the same code over and over again to store and work with such values.

Our intern Jolita and I whipped up a valuestore package. It only provides one class: Valuestore. The values will get written as JSON in a given file. The API mostly reflects Laravel's caching API. Here's how you can work with it:

$valuestore = Valuestore::make($pathToFile);

$valuestore->put('key', 'value');

$valuestore->get('key'); // Returns 'value'

$valuestore->has('key'); // Returns true

// Specify a default value for when the specified key does not exist
$valuestore->get('non existing key', 'default') // Returns 'default'

$valuestore->put('anotherKey', 'anotherValue');

// Put multiple items in one go
$valuestore->put(['ringo' => 'drums', 'paul' => 'bass']);

$valuestore->all(); // Returns an array with all items

$valuestore->forget('key'); // Removes the item

$valuestore->flush(); // Empty the entire valuestore

$valuestore->flushStartingWith('somekey'); // remove all items who's keys start with "somekey"

$valuestore->increment('number'); // $valuestore->get('key') will return 1 
$valuestore->increment('number'); // $valuestore->get('key') will return 2
$valuestore->increment('number', 3); // $valuestore->get('key') will return 5

// Valuestore implements ArrayAccess
$valuestore['key'] = 'value';
$valuestore['key']; // Returns 'value'
isset($valuestore['key']); // Return true
unset($valuestore['key']); // Equivalent to removing the value

// Valuestore impements Countable
count($valuestore); // Returns 0
$valuestore->put('key', 'value');
count($valuestore); // Returns 1

As you see it's quite a simple class, but I'm sure it'll come in handy in the future. The package can be found on GitHub.

Read more

Publishing package assets the right way original

by Freek Van der Herten – 2 minute read

At Spatie we do not only create a lot of Laravel packages, but we use also use a bunch of existing ones. In this post I'd like to give a quick hint to our fellow package developers. In the readme's of packages you'll often find an instruction like this to publish it's assets: php artisan…

Read more

A package to protect your work in progress from prying eyes

Imagine you are working on new app. Your client wants to see the progress that you've made. However your site isn't ready for prime time yet. Sure, you could create some login functionality and display the site only to logged in users. But why bother creating users when there is a more pragmatic approach?

At Spatie we often instruct a client to visit /demo. Visiting that url will unlock access to the entire front site. Because creating packages has many benefits we decided to open source our solution.

Our newly released laravel-demo-mode package blocks your work in progress from prying eyes. After it is installed you can use a route macro to register a route that grants access to the protected routes:

Route::demoAccess('/demo');

Routes can be protected by using the demoMode-middleware on them:

Route::group(['middleware' => 'demoMode'], function () {
    Route::get('/secret-route', 'SecretController@index');
});

Unless a user has first visited /demo first, he or she will be redirected to /under-construction. This url can be changed in the config file.

A word to the wise: do not use this package to restrict access to sensitive data or to protect an admin section. For those cases you should use proper authentication.

You can take a look at the package on GitHub. If you like it, you might like some of our other Laravel packages as well.

Read more