Quantcast
Channel: Laravel News
Viewing all 1732 articles
Browse latest View live

Vue.js v2.4.0 is now released

$
0
0

Vue.js v2.4.0 is now released and available. This version features full SSR + async component support in core, easier creation of wrapper components, better performance, and more.

Here is a highlight of the new features:

Full SSR + async component support in core

SSR now supports rendering async components used anywhere and the client also supports async components during the hydration phase. This means async components / code-splitting now just works during SSR and is no longer limited at the route level

Easier creation of wrapper components:

New component option: inheritAttrs. Turns off the default behavior where
parent scope non-prop bindings are automatically inherited on the component root
as attributes.

New instance properties: $attrs & $listeners. $attrs contains the parent-scope attribute bindings that were not recognized as props, and $listeners contains the v-onlisteners registered in the parent scope (without the .native modifier). These are essentially aliases of $vnode.data.attrs and $vnode.data.on, but are reactive.

Combining these allows us to simplify a component like this down into this:

<div>
  <input v-bind="$attrs" v-on="$listeners">
</div>

v-on:

Support v-on object syntax with no arguments. This pairs well with the new $listenersinstance property when creating higher-order components. Note this syntax does not support modifiers.

v2.4.0 also features a number of bug fixes and you can find the complete change log on the Vue.js releases page.


Laravel 5.5 Custom Validation Rule Objects

$
0
0

Laravel 5.5 will introduce support for custom validation rule objects as an alternative to using Validator::extend for custom validation rules.

To define a custom validation rule, implement the Illuminate\Contracts\Validation\Rule interface or use a Closure. The custom rule is then used directly in a validator.

An example of a custom object validation rule might look something like:

use Illuminate\Contracts\Validation\Rule;

class CowbellValidationRule implements Rule
{
    public function passes($attribute, $value)
    {
        return $value > 10;
    }

    public function message()
    {
        return ':attribute needs more cowbell!';
    }
}

With the custom rule defined, you might use it in your controller validation like so:

public function store()
{
    // Validation message would be "song needs more cowbell!"
    $this->validate(request(), [
        'song' => [new CowbellValidationRule]
    ]);
}

The same rule as a Closure would look something like the following.

public function store()
{
    $this->validate(request(), [
        'song' => [function ($attribute, $value, $fail) {
            if ($value <= 10) {
                $fail(':attribute needs more cowbell!');
            }
        }]
    ]);
}

The custom rule examples will not run if the song field is empty or isn’t present in the request. If you want a custom validation object to run even with the value is empty, you need to use the ImplicitRule contract.

use Illuminate\Contracts\Validation\ImplicitRule;

class CowbellValidationRule implements ImplicitRule
{
    public function passes($attribute, $value)
    {
        return $value > 10;
    }

    public function message()
    {
        return ':attribute needs more cowbell!';
    }
}

Custom validation rule objects will be an excellent alternative to Validator::extend() style custom rules if you prefer to organize custom rules in classes. Also, jumping to the rule source code from a validator can be more convenient than searching for a custom string-based rule defined with Validator::extend.

The Closure style custom validation rules will be nice for simple one-off needs and make it really convenient to experiment with custom validation rules without leaving the controller. You could use a Closure to experiment with a custom rule and then move it to an object if the rule proves useful.

Check out the pull request files to see how this feature was implemented and tested.

Bravo!

Bouncer: a Laravel Package for Role and Ability Authorization

$
0
0

Bouncer is an authorization package by Joseph Silber which allows role and ability checks at Laravel’s authorization gate. The package is described as follows:

Bouncer provides a mechanism to handle roles and abilities in Laravel’s ACL. With an expressive and fluent syntax, it stays out of your way as much as possible: use it when you want, ignore it when you don’t.

Bouncer makes it trivial to quickly create roles and abilities with a fluent API that creates them automatically.

Bouncer::allow('admin')->to('ban-users');

You can optionally add the HasRolesAndAbilities trait to the User model. This trait allows you to assign roles and abilities, and check them with in the model.

use Silber\Bouncer\Database\HasRolesAndAbilities;

class User extends Authenticatable
{
    use Notifiable,
        HasRolesAndAbilities;
}

When you assign a role that hasn’t been created yet, Bouncer will do it automatically.

$user->assign('admin');

As a quick example, imagine a database seeder that creates a few roles with Bouncer and assigns users to a role using the HasRolesAndAbilities trait.

public function run()
{
    \Bouncer::allow('admin')->to('*', \App\Post::class);
    \Bouncer::allow('editor')->to('update', \App\Post::class);

    $admin = factory(App\User::class)->create([
        'email' => 'admin@example.com'
    ]);

    $admin->assign('admin');

    $editor = factory(App\User::class)->create([
        'email' => 'editor@example.com'
    ]);

    $editor->assign('editor');

    factory(App\User::class)->create([
        'email' => 'user@example.com'
    ]);
}

The database seeder conveniently creates two roles: admin and editor. The admin will have permission to all post abilities on the App\Post model. The editor role only has the update ability.

With the above roles, abilities, and users, we can define a route and protect updating a Post using Laravel’s Authorize middleware.

Route::get('/posts/{post}', 'PostsController@show')
        ->name('post.update')
    ->middleware('can:update,post');

Both authenticated administrators and editors will be able to see a post, guests will be redirected to login, and authenticated users lacking the update ability will get a 403 Forbidden response.

In the view, you can use Laravel’s @can directive to check for abilities and Bouncer will intercept the check and authorize it if an ability has been granted to the user.

@can ('update', $post)
    <a href="{{ route('post.update', $post) }}">Edit Post</a>
@endcan

Not only can you grant user abilities through roles, but you can also assign an ability directly to a user.

$post = \App\Post::first();
$normalUser = \App\User::find('email', 'user@example.com')->first();

// Only update a specific post, perhaps one this user submitted.
$normalUser->allow('update', $post)

// Ability to update all posts directly on a user
$normalUser->allow('update', \App\Post::class);

Bouncer provides methods for checking user roles, but the Bouncer documentation warns against role checking directly:

Generally speaking, you should not have a need to check roles directly. It is better to allow a role certain abilities, then check for those abilities instead. If what you need is very general, you can create very broad abilities. For example, an access-dashboard ability is always better than checking for admin or editor roles directly.

Last, if you want to get a user’s abilities, call $user->getAbilities(), which returns a database collection:

user-abilities-example.png

Check out the package’s readme to learn how to install and use Bouncer. The cheat sheet is handy for a quick overview of the package’s API and capabilities.

The Road To Laracon Soundtrack

$
0
0

Next week is Laracon US, and Jacob Bennett and Michael Dyrynda have been interviewing many of the speakers on the podcast. As part of the interview, they’ve asked the speakers to pick a few of their favorite songs and put it together in a Spotify playlist.

It features twenty-three songs and is an hour and forty-three minutes of listening pleasure and I enjoy trying to match the song to the speaker. To get to know the speakers here are links to each of their podcast interviews:

Insights into Laravel package design

$
0
0

This tutorial brought to you by

Laravel is a massively influential PHP framework, and its simple but powerful design means that it’s easy to utilize packages in your application. In this blog post, we will look at the basics of creating and installing Laravel packages.

Where do I start?

Composer is massively important in the PHP world, and Laravel is no exception to this. The Laravel framework core specifies its dependencies using Composer and so do Laravel applications by default. With this in mind, it is totally natural for our packages to also define their dependencies using Composer, and to be distributed via Packagist using Composer.

For an introduction to Composer and Packagist, you may want to read the previous two blogs in this series: Building maintainable PHP apps using Composer and Packagist and the PHP ecosystem

In this blog post, we’ll be building a small package by means of an example. You can follow along with the example here.

The basic structure of a package

At the core of things, remember there’s actually nothing special about a Laravel package compared to any other PHP package. Most people start off with:

  • A readme – README.md
  • A license file – LICENSE
  • A composer file – composer.json
  • A gitignore file – .gitignore
  • Your code folder – src

So, we will write a short readme, choose a license, add a basic composer.json file, and a .gitignore file:

We’ve named our package foo-bar/example, and namespaced the source folder to Foo\Bar\Example.

Adding your code

Next, we will write a short class that will give us random cat names!

Facades and Containers

Our class can be used in any PHP project, Laravel or not. What if we want to make it available through the Laravel service container, or a Laravel facade?

First, we add a service provider. This binds an instance of Foo\Bar\Example\Cats to the service container and allows us to access it via app(‘example.cats’) and to inject it into classes with a parameter typed with Foo\Bar\Example\Cats. Users of your package can register this service provider in order to setup the bindings.

Your facade means that your package users can now call:

Foo\Bar\Example\Facades\Cat::generate()

or Cat::generate() if aliased or imported.

Since we’re making use of the support component, we will require it:

Configuration

Suppose we want to add the ability to customize the names of the cats provided by the generator? We can do this using Laravel’s config facilities.

First, we modify our code to receive the desired names through the constructor. It’s important that we do this rather than trying to read the configuration from inside the class in the interest of avoiding coupling our class to the configuration. One common error I see is to not only couple code where not needed, but more seriously, to make the assumption that the global config function is available for use. You cannot assume this unless you require all of laravel/framework, and similarly, you can never assume Config is aliased to Illuminate/Support/Facades/Config, or even that facades are enabled (in the case of Lumen, or other custom frameworks). Never write “use Config;” unless you know that alias exists.

So, we modify our constructor:

And write a configuration file with the cat names:

Users can publish this file to their application in order to enter their configuration. There is actually no requirement to place this file in this exact location in your package code since Laravel 5 is much more flexible than Laravel 4; however, I think this makes for a good place to put it.

Next, we define our service provider:

There’s a lot going on here! Let’s walk through it. We will start by looking at the modifications to the register function. Since our Cats class now takes an array of cat names in the constructor, we need to pass one. We read the configuration from the file “cats.php”, entry “names”.

Our boot function is needed to register our configuration file with the framework. It’s actually okay to call the global config_path function here, since we only ever enter that branch of the code if we know the container is an instance of a Laravel application, so it must be the case that the whole Laravel framework is there.

One should also note that it’s absolutely fine in PHP to import classes that don’t exist. The only side effect of an import statement is to bind the long name to the short name. With this is mind, it really does mean that PHP doesn’t care if the class doesn’t exist because it doesn’t try to load it. Similarly, in an instance of check, PHP will not bother checking if the class provided actually exists since the implementation seemly needs to perform reflection on the object.

Testing

Before we finish, it is only natural that we take a very quick look at testing.

The most widely used framework for this is PHPUnit. This can be installed globally or added as a local composer dependency.

We pull in PHPUnit, and add a basic config file:

We now write a few simple tests to check if our Cats class is behaving as it should:

We can run our tests:

Conclusion

We have seen how to write a simple Laravel app with configuration, a facade, and basic tests. Now, go build something great!

You can find the Laravel example in this blog post here on GitHub.

Are you monitoring your Laravel application for errors? Try Bugsnag’s Laravel error reporting to gain insight on bugs and fix them for your users.

PhpStorm 2017.2 is released

$
0
0

Today the JetBrains team released PhpStorm 2017.2, the second major update for PhpStorm in 2017. This release brings improvements when working with Composer, Docker Compose, reworked polymorphic types support, automatically run PHPUnit tests and many other enhancements.

The Composer improvements look really fantastic and include the following new features:

Composer Actions

Now you can execute the actions Update Dependencies, Install Dependencies, Remove Dependencies, and Self-update directly from the IDE, without having to switch to the command line.

composer.json settings synchronization

Since composer.json contains the most up-to-date information about the project, the synchronization of new settings between PhpStorm and composer.json ensures that PHP Language Level, PhpStorm Source, and Test folders exactly match the project settings and structure specified in composer.json. This significantly simplifies project configuration in PhpStorm.

Seamless work with composer global installation

Now you can use globally installed composer. PhpStorm detects whether you have it installed and simplifies project creation in case you do. You can also set globally installed composer for existing projects and make it default for all projects. All this will save you time that you spent on looking for the previously downloaded composer.phar or on downloading yet again composer.phar into the project.

For a complete overview of new features check out this video by Gary Hockin:

To get the latest version head over to their what’s new page to see all the new features as well as the download.

Laravel v5.4.29 is Released with Two New Blade Directives

$
0
0

Laravel V5.4.29 is now released and available. This is a maintenance release but it includes two new Blade Directives, a --force option on some of the “make” commands, and more.

New @auth and @guest Directives

The @auth directive allows you to simplify the check to see if a user is logged in. For example, in the past you might use:

@if(Auth::check())
   You are logged in.
@endif

Now with the @auth directive, this can be simplified to:

@auth
   You are logged in.
@endauth

It also supports the Guard to use as the first parameter:

@auth('admin')
    You are logged in through admin guard
@endauth

The other new directive is @guest which is the inverse:

@guest
   Welcome Guest
@endauth

v5.4.29 Complete Changelog

Added

  • Added ManagesFrequencies::twiceMonthly() method (#19874)
  • Added RouteCollection::getRoutesByName() method (#19901)
  • Added $expiresAt parameter to CallbackEvent::withoutOverlapping() (#19861)
  • Support keeping old files when testing uploads (#19859)
  • Added --force option to make:mail, make:model and make:notification (#19932)
  • Added support for PostgreSQL deletes with USES clauses (#20062, f94fc02)
  • Added support for CC and BBC on mail notifications (#20093)
  • Added Blade @auth and @guest directive (#20087, #20114)
  • Added option to configure MARS on SqlServer connections (#20113, c2c917c)

Changed

  • Support object items in Arr::pluck() (#19838, #19845)
  • MessageBag interface now extends Arrayable (#19849)
  • Made Blueprint macroable (#19862)
  • Improved performance for Arr::crossJoin() (#19864)
  • Use the correct User model namespace for new policies (#19965, a7094c2)
  • Consider scheduled event timezone in inTimeInterval() (#19959)
  • Render exception if handler can’t report it (#19977)
  • Made MakesHttpRequests::withServerVariables() public (#20086)
  • Invalidate session instead of regenerating it when logging out (#20107)
  • Improved InvalidPayloadException error message (#20143)

Fixed

  • Don’t re-escape a View instance passed as the default value to @yield or @section directives (#19884)
  • Make sure migration file is loaded before trying to rollback (#19922)
  • Fixed caching issue in mix() (#19968)
  • Signal alarm after timeout passes (#19978)

Two Best Laravel Packages to Manage Roles/Permissions

$
0
0

Roles and permissions are an important part of many web applications. Laravel historically had a lot of packages for them, and improved the core code as well. So what is the situation on this market today? What packages are the best to use? I’ve picked two.

Why Do You Need Packages?

Let’s start from the beginning—Laravel has its own core logic for managing permissions. It was introduced in version 5.1.11 and has remained almost unchanged since. There we have things like:

  • Gates and Policies
  • $this->authorize() method
  • @can and @cannot Blade commands

One might say it’s enough to have Laravel core and there’s no need for packages. This is part of the reason older packages are abandoned; core functions replaced them.

But there’s still an area where packages can help—to manage the permissions and roles, which is not easy in the core. And there are two packages which do that really well and are actively maintained:

Special mention: santigarcor/laratrust, which is a fork of unmaintained Entrust, and could be a strong third contestant. The problem with Laratrust is it replaces default Laravel commands with its own, so you wouldn’t be able to use Gates or @can syntax. Instead, you would need to use $user->can(‘edit-user’) or @permission Blade command. But if you don’t care about those extra syntax pieces, Laratrust is a great package. It also has Teams functionality, which is not present in Spatie’s or Bouncer packages.

There are a few more options, but they seem outdated and not that active. Still, you may want to watch them for a potential comeback:

Now, let’s get deeper into a “battle review” between two main contestants.

What Do These Packages Actually Do?

They give you an API to deal with roles and permissions more easily. Also, the final code is more reader-friendly and easier to understand.

Instead of creating all rules in Policies and Gates, which would be fragmented in a few different places, you would have code like this:

$user->givePermissionTo('edit articles'); // Spatie package
$user->allow('ban-users'); // Bouncer package

Essentially, those two packages offer really similar functionality, with slightly different syntax and database structure. Let’s dig deeper and compare.

Installation and Usage

Both packages are installed similarly:

  • Add to composer and install.
  • Add a provider and facade (Bouncer) to config/app.php.
  • Publish and run migrations.
  • Add a special trait into User model (both packages use Traits).
  • That’s it; use package’s methods (optionally including its classes where needed).

Packages assume you already have a default Laravel users DB table, but don’t have any structure for roles/permissions. They will add their own tables and fields.

Both packages have clear documentation, and there were no issues whatsoever. Great job done on README files!

Database Structure

This is where the packages are quite different. Spatie’s package has these tables:

Some explanations here:

  • Field guard_name has default value webpackage allows to use multiple guards.
  • As you can see, there are two pivot tables for permissions—one with roles, and one with users.
  • Field model_type has default value App\User so there’s no direct foreign key to users table, no other table has user_id field.

Now let’s look at Bouncer’s database:

Quite different, isn’t it? And even fewer relationships. Now, let me explain:

  • What Spatie calls “permissions,” Bouncer calls “abilities.” And then the “permissions” table is a set of abilities attached to an “entity.”
  • Entity” (in all tables) is an object to assign abilities to. It may be a role or a user. Therefore, there is no direct relationship to user_id or users table; the same as with Spatie’s package.
  • There are a few more fields different from the previous package: abilities.title, abilities.only_owned, and roles.level. They add some additional functionality, but it is not well explained in the README file.
  • Spatie has guard fields which are not present in Bouncer.

All in all, Bouncer’s database structure seems a little more complicated and more difficult to understand at first, but with that comes a little more flexibility.

Available Methods

These packages do offer really similar functionality, so let’s compare in details.

Create Roles/Permissions/Abilities

Spatie

You can use facades of the package as normal facades of Laravel:

use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;

Role::create(['name' => 'writer']);

Permission::create(['name' => 'edit articles']);

Bouncer

You can create role and ability, and assignment all in one sentence:

Bouncer::allow('admin')->to('ban-users');

That’s it. Behind the scenes, Bouncer will create a Role model and an Ability model for you.

But you can also work with facades, too:

use Silber\Bouncer\Database\Ability;
Ability::create(['name' => 'edit articles']);

As you can see, Bouncer has a little more functionality here with automatic “behind the scenes” model creation.

Assigning Roles to a User

Spatie

$user->assignRole('writer');
$user->assignRole(['writer', 'admin']);

$user->removeRole('writer');

Roles can also be synced:

// All current roles will be removed from the user and replace by the array given
$user->syncRoles(['writer', 'admin']);

Bouncer

$user->assign('admin');
$user->assign(['writer', 'admin']);

$user->retract('admin');

It’s great that both packages accept either individual roles or arrays.

But Spatie’s package wins here because of syncRoles functionality. It’s really useful; with Bouncer you need to perform it manually with a few operations.

Assigning Permissions/Abilities to a User

Spatie

$user->givePermissionTo('edit articles');
$user->givePermissionTo('edit articles', 'delete articles');

$user->revokePermissionTo('edit articles');

Bouncer

$user->allow('ban-users');
$user->allow(['ban-users', 'edit-articles']);

You can pass the model name as a second argument.

Bouncer::allow($user)->to('edit', Post::class);
Bouncer::allow($user)->to('edit', $post);

$user->disallow('ban-users');
Bouncer::disallow($user)->to('delete', Post::class);

Similar functionality, but Bouncer offers the ability to pass the model class or its instance.

Checking Permissions/Roles for a User

Spatie

Check roles

$user->hasRole('writer');
$user->hasAnyRole(Role::all());
$user->hasAllRoles(Role::all());

Check permissions

$user->can('edit articles');
$role->hasPermissionTo('edit articles');

Bouncer

Check roles

$user->isAn('admin');
$user->isA('subscriber', 'editor');
$user->isAll('editor', 'moderator');
$user->isNot('subscriber', 'moderator');

Check permissions

Bouncer::allows('edit articles')

This section is pretty similar in both packages, with no clear winner.

Blade Commands

Spatie

@role('writer')
    I'm a writer!
@else
    I'm not a writer...
@endrole
@hasanyrole('writer|admin')
    I have one or more of these roles!
@else
    I have none of these roles...
@endhasanyrole

Bouncer

Bouncer does not add its own Blade directives.

More functionality by Spatie’s package. Of course, with both packages you can use default Laravel commands like @can and @endcan.

Caching

Spatie

Role and permission data is automatically cached to speed up performance.

To manually reset the cache for this package, run:

php artisan cache:forget spatie.permission.cache

Bouncer

All queries executed by the bouncer are cached for the current request. If you enable cross-request caching, the cache will persist across different requests.

Whenever you need, you can fully refresh the bouncer’s cache:

Bouncer::refresh();

Alternatively, you can refresh the cache only for a specific user:

Bouncer::refreshFor($user);

Caching is a little more robust in Bouncer. Enabling/disabling cache is a good thing, and refreshing the cache for a particular user might come handy.

Overall Conclusion

If you still expect a clear winner here, it’s not going to happen. Both packages are really good, and it’s a matter of preference.

Both of them have advantages in some functionality, but it’s more about the details.

Spatie’s Advantages:

  • A little better documentation (some Bouncer’s methods aren’t mentioned in README)
  • A little more understandable DB structure
  • syncRoles() method instead of delete-insert way
  • A few blade commands – @role and @hasanyrole
  • Ability to use multiple guards

Bouncer’s Advantages:

  • Create role/ability and assign it—all in one sentence
  • Allow or disallow permission based on model or its instance
    • A little better caching mechanism
    • A little more robust DB structure with a few more useful fields

If any of these details are really important to you, that could be the reason for your choice. Otherwise, pick Spatie or Bouncer, and you shouldn’t be disappointed.

P.S. Bonus Gift

Finally, both packages offer a set of functions to manage roles and permissions but don’t have any UI or admin panel to manage it. I’ve prepared a UI starter kit, based on both packages. You can use it as a boilerplate to manage roles and permissions.

Here are links to the GitHub repositories:


PHP Released v7.2.0 Beta 1

$
0
0

Yesterday, the PHP team released the first beta of the 7.2.0 release. From the announcement this version builds on previous releases with the following:

  • The much-anticipated Sodium extension
  • Opcache improvements
  • Countable support for DOMNodeList and DOMNamedNodeMap
  • Improved handling for invalid UTF8 in json_decode()
  • And many bugfixes…

If you have the ability, they encourage you to start testing this version and the second beta will release on August 3rd.

For more information on this release check out the following resources:

Image Optimization With Spatie Laravel Image Optimizer

$
0
0

Image optimization can greatly improve site performance, and is one of the most common issues I see in Google pagespeed insights reports. Sometimes images can be reduced by 50% or more, yet, it can be difficult to string various tools together to optimize images in web applications.

Enter Spatie’s image-optimizer PHP package:

This package can optimize PNGs, JPGs, SVGs and GIFs by running them through a chain of various image optimization tools.

To go along with this tool (wait for it), they’ve released a package for Laravel integration which makes it simple to use in a Laravel application.

We will cover a basic overview and some examples in action with a Laravel application.

Image Optimization Basics

One implicit goal most people have when using an image optimization tool is to provide smaller images yet sacrificing as little quality as possible. While striking a balance between smaller images and crisp quality is different for everybody, most people want their images to still look good. Optimization tools are available for every image format, and do a great job of optimizing without compromising the images; however, finding a unified API that connects these tools is where Spatie’s package fills an important void.

According to the authors of the plugin, Spatie’s image-optimizer package provides the glue code that developers might ignore or be overwhelmed with:

You must make sure that you pass the right kind of image to the right optimizer. You also have to decide which optimization parameters you’re going to use for each tool. None of this is rocket science, but I bet that the vast majority of small to medium sites don’t bother writing this code or researching these optimizations.

The interface for Spatie’s image-optimizer package is quite simple:

use Spatie\ImageOptimizer\OptimizerChainFactory;

$optimizerChain = OptimizerChainFactory::create();

$optimizerChain->optimize($pathToImage);

Internally, the package uses the following optimizers if they are available on the system to optimize images:

Quick Example

Let’s create a small CLI project and run an image optimization to get a feel for the package. Later we will take the Laravel package for a spin to see how easy the package makes optimizing images.

If you want to follow along, check out the readme for installation instructions for the optimization tools.

First, create a small project somewhere on your filesystem:

mkdir ~/Code/image-optimizer-example && cd $_

composer init --no-interaction \
--name="laravel-news/image-optimizer-example" \
--require="spatie/image-optimizer:1.*"

composer install

brew install \
  jpegoptim \
  optipng \
  pngquant \
  svgo \
  gifsicle

Create an index.php file with the following:

require __DIR__.'/vendor/autoload.php';

use Spatie\ImageOptimizer\OptimizerChainFactory;

if (!isset($argv[1]) || !file_exists($argv[1])) {
    echo "Please provide a valid image path";
    exit(1);
}

// Get the image and store the original size
$image = $argv[1];
$originalSize = filesize($image);

// Optimize updates the existing image
$optimizerChain = OptimizerChainFactory::create();
$optimizerChain->optimize($image);

// Clear stat cache to get the optimized size
clearstatcache();

// Check the optimized size
$optimizedSize = filesize($image);
$percentChange = (1 - $optimizedSize / $originalSize) * 100;
echo sprintf("The image is now %.2f%% smaller\n", $percentChange);
exit(0);

Most of the code was validating the argument and getting the file size. It only took a few lines of code from the library in order to optimize the image.

If you run it against a file, you should see some savings (unless the file you picked was already optimized). I used a Creative-Commons photo of the Alexandra Bridge to run the script:

php index.php ./6873422757_91470bca43_o.jpg
The image is now 15.23% smaller

Awesome, that was easy! Now that we’ve looked at a basic script, let’s get the package working with a Laravel application!

A Laravel Example

Let’s work on a quick example of using Spatie’s laravel-image-optimizer package within Laravel. First, create a project somewhere:

laravel new image-optimizer
cd ./laravel-image-optimizer
valet link # use this if you are using Laravel valet
composer require spatie/laravel-image-optimizer
php artisan make:controller PhotosController

The commands create a new Laravel application, link Laravel Valet (skip if you are not using Valet), and create a PhotosController for our demo.

Next, follow the installation guide to set up the laravel-image-optimizer package provider, facade, and middleware. Once Laravel 5.5 ships, the package auto-discovery feature will reduce setup even more.

After setting up the provider and middleware, add the following route in the routes/web.php file:

Route::post('/photos', 'PhotosController@store')
    ->middleware('optimizeImages');

The route uses Spatie’s image optimization middleware to automatically optimize uploaded images.

Next, the PhotosController will store the optimized image and respond with an “OK” message just for testing.

namespace App\Http\Controllers;

class PhotosController extends Controller {
    public function store() {
        $this->validate(request(), [
            'photo' => 'required|image:jpeg '
        ]);

        request()->photo->storeAs('images', 'optimized.jpg');

        return response('OK', 201);
    }
}

Lastly, create a simple form using the existing welcome.blade.php file you can use to submit an image:


<form action="/photos" enctype="multipart/form-data" method="POST"> {{ csrf_field() }} <div class="form-group"> <label for="">Photo</label> <input class="form-control" name="photo" type="file" /> <button type="submit">Upload</button> </div> </form>

That should be enough to submit a JPEG by visiting the / route of the application and uploading a JPEG file. If you hooked up the service provider and the middleware, you should see that the file located at storage/app/images/optimized.jpg is a reduced size from the original you submitted.

With hardly any effort, you will benefit from optimized images that use this middleware! You can also reach for the ImageOptimizer facade or the OptimizerChain service to optimize images using the same API from the base image-optimizer package.

The package also allows you to write your own custom optimizations and tweak the default options in the Laravel package’s configuration file. The installation section provides instructions on how to publish the config file.

Laravel 5.5 Responsable Interface for Responses

$
0
0

A new return type will be supported in Laravel 5.5 routes: the Responsable interface. This contract allows objects to be converted to an HTTP response instance when returned from a controller or route closure. A Responsable object needs to implement a toResponse() method which represents the object as an HTTP response.

<?php

use Illuminate\Contracts\Support\Responsable;

class ExampleObject implements Responsable
{
    public function __construct($name = null)
    {
        $this->name = $name ?? 'Teapot';
    }

    public function status()
    {
        switch(strtolower($this->name)) {
            case 'teapot':
                return 418;
            default:
                return 200;
        }
    }

    public function toResponse()
    {
        return response(
            "Hello {$this->name}",
            $this->status(),
            ['X-Person' => $this->name]
        );
    }
}

Using the ExampleObject in a route, you can now do something like this:

Route::get('/hello', function () {
    return new ExampleObject(request('name'));
});

In the framework, the Router class now checks for this type when preparing the response:

if ($response instanceof Responsable) {
    $response = $response->toResponse();
}

Let’s say you have various response types in the App\Http\Responses namespace to organize your responses. One example might look like this to support a Posts model:

<?php

namespace App\Http\Responses;

class PostIndexResponse extends Response
{
    public function __construct($posts)
    {
        $this->posts = $posts;
    }

    public function toResponse()
    {
        return response()->json($this->transformPosts());
    }

    protected function transformPosts()
    {
        return $this->posts->map(function ($post) {
            return [
                'title' => $post->title,
                'description' => $post->description,
                'body' => $post->body,
                'published_date' => $post->published_at->toIso8601String(),
                'created' => $post->created_at->toIso8601String(),
            ];
        });
    }
}

This is a basic example that illustrates a simple use-case. It returns a JSON response, but you might want the response layer include additional functionality like content negotiation. The example above also assumes an App\Http\Responses\Response class that could provide some base functionality. The response layer could also contain transformation code like Fractal instead of using it directly in the controller.

A controller that works with the PostsIndexResponse might look like the following:

<?php

namespace App\Http\Controllers;

use App\Http\Responses;

class PostsController extends Controller
{
    public function index()
    {
        $posts = \App\Post::all();

        return new Responses\PostIndexResponse($posts);
    }
}

Check out the commit implementing this contract. While simple, I think it will be interesting to see how people will use Responsable in Laravel 5.5.

Introducing Laravel Horizon

$
0
0

The moment everyone in the Laravel community has been waiting for has finally arrived! Laravel Horizon is software to “supercharge your queues with a beautiful dashboard and code-driven configuration.”

On a regular basis, I find myself on a production server console trying to rerun failed jobs and clear a “stuck” jobs and using redis-cli see what is in the queue. Generally speaking, Laravel queues are amazing and work fantastically most of the time; however, when things fail, troubleshooting queues can be a daunting task. On top of troubleshooting, wouldn’t you also like some key metrics on queue performance?

Laravel Horizon is designed to make it easy monitor your queues from a web interface and receive notifications when things go wrong.

According to Taylor Otwell, the creator of Laravel, here’s the background of why he built Laravel Horizon:

I built Horizon to scratch my own itch. I need deep insight into my queue throughput, performance, wait times, failures. And, when a customer has a problem, Horizon allows me to quickly find the job that failed.

Key Features

At a high level, here are some of the key features of Laravel Horizon:

  • Auto-balancing
  • Code-Driven Configuration
  • Dashboards and Metrics
  • Queue monitoring
  • Failed Job Management
  • Notifications
  • Open-Source Software

Auto-balancing

Horizon will balance your workers across queues. When a queue gets busy, Horizon can intelligently see if any other workers are available and move them to queues that need help.

Code-Driven Configuration

Laravel Horizon uses code-driven configuration, which is awesome because you can version control it along with your project.

Dashboard Metrics

See what your queue is doing in real-time with dashboard metrics for your queues and jobs. The metrics can help you monitor things like performance, job stats, and throughput.

Queue Monitoring

With Laravel Horizon you will be able to tag your jobs and monitor them with a simple dashboard. Monitoring will allow you to isolate issues and usage patterns according to your specific needs.

Failed Job Management

Most people that have used Laravel queues have had to SSH into a server and retry failed queue jobs. Laravel Horizon will make it easy to retry failed jobs and even search failed jobs and retry specific jobs. For example, you can search for a failed jobs for a single user and retry them.

Notifications

When a queue is getting overloaded, Laravel Horizon can notify you of the issue, allowing you to react much more quickly. I’ve set up custom monitoring in order to receive queue notifications when things go bad, but Laravel Horizon should make it much simpler to get notifications up without all the hassle of setting up custom monitoring solutions.

Open Source

In my opinion, one of the most awesome parts of Laravel Horizon is that the free version will be 100% open-source software. You will be able to browse the source code and contribute if you run into a bug or spot an improvement that can be made.

Conclusion

Laravel Horizon is an exciting addition to the Laravel ecosystem and solves a much-needed pain point around using queues with Laravel. I personally can’t wait to install Horizon and give it a further review after launching it into one of my production systems!

Laravel Valet v2.0.5 is released

$
0
0

Laravel Valet 2.0.5 is now released and available. This version includes support for PHP 7.2, Favicons, and other improvements.

Valet Changelog

  • Shows useful output about what Valet is doing during installation/restart
  • Added support for Craft 3 Beta
  • Test for nginx config errors before attempting to restart Valet
  • Prevent access to valet CLI commands that do not work until valet install is run
  • Added Magento 2 driver
  • Fixes for CakePHP 3 driver
  • Added support for PHP 7.2

To get the latest version all you need to do is run a global composer update:

composer global update

Freelancing Conference (sponsor)

$
0
0

This conference is specifically created to help amazing entrepreneurs like you – consultants, freelancers, and agencies. It consists of a variety of sessions covering exciting topics to help you grow your freelancing business – Get ready to learn about an actionable framework and earn $100K in 2018.

We have amazing talks lined up for everyone. Great speakers with great topics. The time and money you spend at Freelancing Conference will be paid back immediately.

Learn from the specialists who are consistently making $100K+ revenue from their consulting business. Know about the speakers:

Kai Davis

Kai Davis teaches Freelancers and Consultants how to get more clients without spending more money on marketing. He’s an evangelist of the model of modern freelancing. Kai runs Double Your Audience, an Outreach Consulting Agency, helps authors and self-funded business owners reach through target audience through Digital Outreach.

Kai sends out a DAILY email on marketing and consulting for freelancers at kaidavis.com. You aren’t alone any longer, fellow freelancer.

Sean D’Souza

Sean has always followed his dreams, putting in the effort required to achieve them. He was running a successful business as a freelance cartoonist in Mumbai when he and his wife decided to embark on a completely new adventure – moving to beautiful New Zealand. Through relentless perseverance, springing out of bed at 4am, he once again built up a portfolio of delighted clients. Eventually, he developed a three-pronged strategy that allows him to take three months off every year, while running the very successful website pyschotactics.com.

Christopher Hawkins

Just before turning 30, Chris walked away from his successful career leading technical projects for large enterprises, launching his own consulting practice instead. He quickly built a 6-figure practice that provides consulting and web development for businesses of every size, from Fortune 500s on down.

Chris writes extensively on the software consulting industry and hosts the $100K Freelancing show, teaching other consultants and freelancers how to run an effective and profitable practice.

Having built a reputation as an expert in handling crisis projects, difficult clients, and recurring engagements, Chris says “When I teach consultants how to hold professional boundaries, manage crises, and re-sell new projects to old clients, I’m teaching them how to sustain an entire 6-figure career.”

Jane Portman

Jane is an independent UI/UX consultant from Russia who helps software companies build focused, profitable web applications.

Previously a creative director at a large agency, Jane went solo after having two boys. Since then, she’s written three books on UI/UX design, given talks at multiple conferences, and grown a successful podcast. These days she’s focused on building her own software product called Tiny Reminder.

Besides helping founders, she teaches other consultants and freelancers build their authority. Her favorite topics include productized consulting, product strategy, and action-driven consulting websites. “Start building your own platform as early as possible,” — Jane recommends.

Mojca Mars

Mojca from Super Spicy Media is a Facebook Ads expert, author, and international speaker. Her work focuses on helping businesses generate more leads and increase profits with a professionally-made Facebook Advertising Strategy, so they can devote their time to other aspects of their business.

Philip Morgan

Philip Morgan teaches self-employed software developers how to identify, validate, and dominate a desirable niche market position. He’s also the author of The Positioning Manual for Technical Firms.

The event has turned out to be amazing – with 6 professional speakers, interactive experiences and the opportunity to meet one-on-one with the leaders who are shaping the future of freelancing.

So, what are you waiting for? Book your place right now! Do not forget to use the code laravel-news and get a 30% discount on the ticket prices.


Many thanks to Freelancing Conference for sponsoring Laravel News this week.

Laravel Homestead Version 6 Released

$
0
0

The Laravel Homestead project just tagged the release of version 6.0.0 along with Settler 3.0. Homestead 6 now supports multiple versions of PHP on the same virtual machine. For developers maintaining apps on different versions of PHP, this change will make it easier to use Homestead.

The available PHP versions include 5.6, 7.0, and 7.1. If you want a site to use 5.6, you would specify the following in the Homestead.yaml file:

sites:
  - map: homestead.app
    to: /home/vagrant/Code/Laravel/public
    php: "5.6"

If the php key is omitted the site will default to PHP 7.1, so things will continue to work as expected for existing sites.

You can get the full details from the 6.0 release notes.


Track Laravel Model Changes with Laravel Auditing

$
0
0

Laravel Auditing is a Laravel package that aims to make it easy to track eloquent model changes. The documentation describes Laravel Auditing as follows:

This package will help you understand changes in your Eloquent models, by providing information about possible discrepancies and anomalies that could indicate business concerns or suspect activities.

Laravel Auditing allows you to keep a history of model changes by simply using a trait. Retrieving the audited data is straightforward, making it possible to display it in various ways.

Along with model changes, each audit record contains the User Agent, audit URL, and the IP address of the user. One of the main use-cases of the package is looking at suspicious activities or unexpected changes in the model.

Model Diffs with the Laravel Auditing Package

In my opinion, another use-case for this package could be providing versioning for records, such as blog posts or other content that allows you to see who changed what on a model easily. This could be used to perform auto-saves, see what changed, who changed it and revert changes from a previous version.

Let’s say you have a Post model that holds articles. The following would be how you add auditing to posts when they are saved and updated:

<?php

namespace App;

use OwenIt\Auditing\Auditable;
use Illuminate\Database\Eloquent\Model;
use OwenIt\Auditing\Contracts\Auditable as AuditableContract;

class Post extends Model implements AuditableContract
{
    use Auditable;

    public function user()
    {
        return $this->belongsTo('App\User');
    }
}

Although not included in the example above, you can also define with attributes that will be included in the audit with an $auditIncluded = []; property on the model.

With the example Post model, you could get the diffs for a post like so with the Laravel auditing package:

// PostsController with route model binding
use App\Post;

function show(Post $post)
{
    $diff = $post->audits()->with('user')->get()->last();

    return view('posts.show')
        ->withPost($post)
        ->withDiff($diff);
}

Here’s an example of how you could display the diffs in a Blade view:

@if($diff)
    <h3>Post Changes</h3>

    <div class="author-info">
        <span class="byline">
            Revision by <strong>{{ $diff->user->name }}</strong>
        </span>
        <span class="time-ago">
            {{ \Carbon\Carbon::parse($diff->created_at)->diffForHumans() }}
        </span>
    </div>

    @foreach($diff->getModified() as $field => $value)
        <h3>{{ ucfirst($field) }}</h3>
        <table class="diff">
            <tr>
                <td style="background: #ffe9e9" class="deleted-line">{{ $value["old"] }}</td>
                <td style="background: #e9ffe9" class="added-line">{{ $value["new"] }}</td>
            </tr>
        </table>
    @endforeach
@endif

The example above only displays the last diff, but you could provide functionality to select the revision number or loop through the entire version history. The audits come back as a collection allowing you to perform collection operations on audits like any other model. The documentation contains audit presentation documentation to give you more ideas on how to present audit changes and metadata.

One thing to note: when I started experimenting with the package I used php artisan tinker to try and create audits. By default, the Laravel auditing package doesn’t track changes to models from the consoles (including tinker). If you have console commands or scheduled commands making changes to models you might want to store audits from the console. You can modify this behavior by publishing and update the provided config with:

<?php

return [
    // ...
    'console' => true,
]

Lastly, the package allows customizations to the audit model, audit driver (the package ships with the Database audit driver), and customizations to audit transformations before data for an audit is stored.

Check out the documentation for more details on everything you can do with the Laravel auditing package!

How to Make Your Code Sustainable

$
0
0

From JavaZone 2015, Christin Gorman presents How to make your code sustainable – what they don’t teach you.

The presentation was at a Java conference, but it’s pertinent to most programming projects (it also validates why I want to code by myself):

Join me for some ranting about how best practices from open source development and project management school is making your sustaining team miserable.

I dare say most projects start off with a goal of producing code that is easy to maintain for the sustaining crew. But as developers are too often split into either pure development teams or pure sustaining teams, not many in the development teams get to experience what sustaining is actually like.

Many seemingly good ideas that are great in the developing phase, make life more difficult in sustaining. Many things that are essential for a good library or framework, are harmful when applied to application development.

I want to share some concrete examples and hopefully inspire you all to write applications that is easier for others to work with.

Terms like “best practices” and “future-proofing software” can mean different things to different people based on context, and this video sheds some light on how sustaining teams will hate your code and how you can simplify it. She also talks about how software constraints and restricting users can become burdensome to your codebase.

(via @christingorman)

Minio: An Open-Source S3 Compliant Storage Service

$
0
0

Have you ever wanted a local version of Amazon S3 while developing Laravel applications? Well want no more, Minio is an open-source distributed object storage server built in Golang. The best part: Minio is Amazon S3 compatible. Let’s go through setting up Minio locally and then try out the new temporaryUrl method introduced in Laravel v5.4.31.

Installing Minio

According to the the quick start guide, Minio is described as:

…an object storage server released under Apache License v2.0. It is compatible with Amazon S3 cloud storage service. It is best suited for storing unstructured data such as photos, videos, log files, backups and container / VM images. Size of an object can range from a few KBs to a maximum of 5TB.

You can install Minio in a couple of different ways, including a Docker image and installing a binary on your machine. The quick start guide contains binaries you can download for your platform of choice.

If you are on OS X, you can install Minio with Homebrew:

brew install minio/stable/minio

Once you have Minio installed you can run it like this:

mkdir /tmp/minio
minio server /tmp/minio

I created the folder Minio will use in /tmp, but you could create this anywhere you want.

Minio’s default port is 9000, which means if you are running PHP-FPM on your machine you will need to specify a different port like so:

minio server --address :9005 /tmp/minio

Endpoint:  http://192.168.1.9:9005  http://127.0.0.1:9005
AccessKey: KBSIYRR36U3A1IO1QARI
SecretKey: Z9BV6YsP7jtRQR1qCJk3PWecs22smNTOl7HC1Yj3

Browser Access:
   http://192.168.1.9:9005  http://127.0.0.1:9005

# ...

You can now access a control panel in your browser with the provided URL using the key and secret credentials to login. With a local instance of Minio running, let’s take it for a test drive with Laravel.

Laravel Minio Setup

Because Minio is S3 compliant, you can use it with Laravel’s S3 driver, with a couple of tweaks. Assuming you have installed the S3 driver as outlined in the filesystem documentation, add a new configuration key in config/filesystems.php:

<?php

return [
    // ...
    'cloud' => env('FILESYSTEM_CLOUD', 's3'),

    'disks' => [

        // ...

        'minio' => [
            'driver' => 's3',
            'endpoint' => env('MINIO_ENDPOINT', 'http://127.0.0.1:9005'),
            'use_path_style_endpoint' => true,
            'key' => env('AWS_KEY'),
            'secret' => env('AWS_SECRET'),
            'region' => env('AWS_REGION'),
            'bucket' => env('AWS_BUCKET'),
        ],
    ],
];

Update your local .env file to use the minio configuration locally:

# .env file

# Default cloud will be Minio locally
FILESYSTEM_CLOUD=minio

# Minio config
MINIO_ENDPOINT="http://127.0.0.1:9005"
AWS_KEY=KBSIYRR36U3A1IO1QARI
AWS_SECRET=Z9BV6YsP7jtRQR1qCJk3PWecs22smNTOl7HC1Yj3
AWS_REGION=us-east-1
AWS_BUCKET=test

Before you can use this, you need to create the “test” bucket to match your configuration. Login to Minio at http://127.0.0.1:9005 and click the “plus” button on the bottom right. Based on our .env configuration, create a bucket named “test”.

If you want the files in the “test” bucket to have read-only access, you need to create a policy by clicking the bucket options icon in the left navigation menu and click “add” in the modal to allow read-only to all files in the bucket.

You should now be ready to start using Minio with Laravel as the default cloud driver locally!

Creating Files with Laravel

Now that Minio and Laravel are set up, let’s test things out in tinker:

php artisan tinker

>>> Storage::cloud()->put('hello.json', '{"hello": "world"}');
=> true
>>> Storage::cloud()->get('hello.json');
=> "{"hello": "world"}"
>>> file_get_contents('http://localhost:9005/test/hello.json');
=> "{"hello": "world"}"

Getting the default cloud driver with Storage::cloud(), our code can use Minio locally and Amazon S3 in production. We demonstrate getting the file from Minio through the S3 driver and through an HTTP request via file_get_contents().

This week, Mohamed Said added a temporaryUrl() method that works exclusively with the S3 driver in Laravel. Now that you have a file stored in Minio, let’s create a temporary URL (you must be using >= Laravel 5.4.31) just like we can in S3:

>>> Storage::cloud()->temporaryUrl("hello.json", \Carbon\Carbon::now()->addMinutes(1));
=> "http://127.0.0.1:9005/test/hello.json?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=KBSIYRR36U3A1IO1QARI%2F20170803%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20170803T034835Z&X-Amz-SignedHeaders=host&X-Amz-Expires=60&X-Amz-Signature=b58451a860d2a511d703d60fcd425edb3dfac3c8c5f0adb1f3b67bcf3d9cfae1"

If you open the URL returned from temporaryUrl() you will get the JSON response we originally created. If you wait 1 minute, you will eventually get a 403 response.

<Error>
    <Code>AccessDenied</Code>
    <Message>Request has expired</Message>
    <Key/>
    <BucketName/>
    <Resource>/test/hello.json</Resource>
    <RequestId>3L137</RequestId>
    <HostId>3L137</HostId>
</Error>

Now you have a free, open-source, lightweight, S3-compatible storage service you can run locally! All your code in existing projects that use S3 should work transparently with Minio.

Conclusion

I love isolating my development environment locally as much as possible and mimicking production at the same time. Minio is a great alternative to running S3 in development and testing against the S3 API. It’s also lightweight enough that you can run it in your stack. Check out minio.io to learn more.

Laravel v5.4.32 is Released with a Security Fix for Image Uploads

$
0
0

Laravel 5.4.32 is now released and it includes a security fix for apps that accept local image uploads and a revert on a recent change to the “BelongsToMany::create()” method.

If your app allows local image uploads you should upgrade to this version now. Below is a complete list of changes.

v5.4.32 Changelog:

Added

  • Added FilesystemAdapter::path() method (#20395)

Changed

  • Allow Collection::random() to return 0 items (#20396, #20402)
  • Accept options on FilesystemAdapter::temporaryUrl() (#20394)
  • Sync withoutOverlapping method on Event and CallbackEvent (#20389)
  • Prevent PHP file uploads by default unless explicitly allowed (#20392, #20400)
  • Allow other filesystem adapter to implement temporaryUrl() (#20398)

Fixed

  • Reverted breaking change on BelongsToMany::create() (#20407)

Laracon US 2017 Recap

$
0
0

Laracon US 2017 is now over, and it was another fantastic event to meet up with old friends and meet new ones in the community. This year it was held in the Hell’s Kitchen area of New York at a venue called New World Stages.

“I attended my first Laracon in person and I have to say I really enjoyed the experience — maybe more than I expected to.” said Sid K. in his Laracon Recap, “It was well organised and the talks were diverse, informative and actionable.”

Photo by Bill Condo

In my opinion, one of the best features of all Laracon’s is that they are held in some of the nicest venues around in the heart of the city. No hotel or airport convention centers here. The benefit to this is during the down time you get the chance to tour the city and see new places.

Ready for the Central Park Jog

For example, Daniel Abernathy setup a Central Park morning jog and had about a dozen people come out to run. It was great chance to meet new people and see the park.

Photo by NinjaParade

This year for the first time, the event featured two tracks, the main talks, and a science fair. The science fair is unique in that it allowed people to showcase what they’ve been working on and for those new to speaking, talk on a smaller stage than the main track.

The keynote is always the highlight of the event and this year Taylor covered some of the new Laravel 5.5 features and then announced Laravel Horizon, which combines a beautiful dashboard and code-driven configuration system for your Laravel Redis queues.

More Laracon Resources:

Viewing all 1732 articles
Browse latest View live