Laravel: quick start

//Laravel: quick start

Laravel: quick start

We’ve been working with Laravel framework on daily basis for years, this is a primary framework in our team for now. During this time we have worked out best practices and approaches that save time and increase effectiveness, and we want to share some time-tested solutions with you. The list is ordered by priority according to project building logic. Relevant for Laravel v. 5.4.23 but we hope most of these ideas will be useful with Laravel v. 5.5.

Start

To facilitate development, the following packages should be installed:

Custom Laravel plugins developed by us:

Login and Registration

Simple login and registration are available out of the box.

Creation of Models

There is one out of box model in Laravel, User, which is stored in the app directory. Create Models directory in app directory, move model there and update namespace by adding ‘Models’ there. From now, all models will be stored in App\Models namespace. Please do not forget to update it in all places where User model has been used before (login, registration, settings etc).

After making a rough database design, you can create a model for every table. Better not to copy models but generate with the help of a special command.  When model is generated, add the properties into it (‘table’, ‘fillable’, ‘visible’, ‘casts’, ‘dates’, ‘timestamps’) and all connections. If you have copied a previously existing model please make sure to get rid or update everything that you don’t need here including  connected classes at file header, comments, phpdocs etc.

Creation of controllers

Controllers are not copied or created from scratch; controllers are created with the help of a console command. Please do not forget console command parameters, in order not create pre-set controllers for desired purposes (controller can be based on model).

Routing

For CRUD we recommend to use resource controllers, which are minimalistic and convenient. Other methods are written before resource controllers (see in documentation, why) and they always should obtain a name. Also, it might be useful to add comments to routings, which will help to visually find, which query will direct to a desired controller, and facilitate routing in general.

If you want to build a link, it should use a routing name. Thus, when you want to update a route, you only need to make changes in couple of lines of code, other than changing all urls in the application.

Query validation and permission

Policies are used to setup permissions. Each model has its own class and validation logic for permissions is described there (see more details in documentation). Validation and query to policies is done in FormRequest. FormRequest is created for each controller action; and validation rules are described in rules method (or you can leave it empty). Authorize method sends query to policies checking. In most cases this will be enough but it happens that we are not able to validate all permission or all incoming values at current query stage, and in such cases we just apply policies or validation where needed. Please make sure you test such spots thoroughly.

Logic of controller actions

Code written in action should be easy to read line by line and should store only code that addresses model methods or other classes. So logic should be stored in models, jobs or other components but queries these methods should be done in controller. Here is example:

Jobs

Laravel v.5.1 has out of the box support of a very nice feature, a command bus. This is a way to incapsulate tasks into separate classes, ‘commands’. If you are not familiar with this approach, we suggest that you look into ‘command’ pattern. However, command bus has been removed from Laravel 5.2.

We have found two ways to use this option again. The first solution is to use a package implemented by Laravel community. It is convenient and in fact, it just stores a deleted code of a command bus but as a separate package. The second solution is Jobs, a special class, which is very similar to command bus but intended to work with queues. We use Jobs as a replacement for command bus along with using it for queues.

Let us see an example. The goal is to create a method that would get a page url, scrape and return back some data from the page. All logic for data collection would be moved out into a separate job, which accepts the url and returns data. It would look like this:

In this case, controller just calls this Job.

Thus we get a clean and clear controller method and a logic stored separately in Job, which can easily be re-used again or moved out to a queue (dispatchNow executes Job immediately without putting it into queue).

Example.

FAQ

You are installing npm packages on Windows and you have got the following error:

This error is related to the packages working with sass, if you don’t use sass in your project you won’t see this error. Could not find solution for this issue on Windows but alternative solution is to use Laravel Homestead. For this, after setting up a virtual machine, from root folder of Laravel please run the following commands (all these commands should be run within a virtual machine, not in Windows):

  1. npm install —no-bin-links will install all necessary packages without symbolic link. In the end will most probably say ‘max call stack size’
  2. npm rebuild node-sass —no-bin-links – will re-install the packages for sass compilation
  3. remove cross-env before NODE_ENV in package.json

After that the packages are supposed to work fine but only on the virtual machine.

Most probably, you have ‘sync’ driver selected in queue setting. This driver fulfills queue tasks immediately. Please set up queues properly.

You are running migration with an updated column and you have got an error saying that this type of column is not registered with some of the packages. Please look at this part of documentation. It says that certain types of columns cannot be updated using migrations constructor. As an exception, such columns can be updated with native SQL.

You have run ‘php artisan make:auth’ but then you’ve got an error when making migrations

The issue is that your MySQL version does not support the desired key length (varchar(255) + unique index). In such case you need to set this field to 191 in this migration or re-define default length in Laravel. This is done by adding the following code in AppServiceProvider:

If you have update default value in Laravel please do not forget to update validation as well:

It means that you forgot to generate an encryption key while setting up the project. To resolve this issue please run “php artisan key:generate” in command line.

Most probably, storage directory and bootstrap don’t have permissions to read and write. In this case Laravel is not able to store data in this directory and when it fails, it throws some exception but logs cannot be written too…

Useful links