Laravel
Requirements
- PHP 7.1.3 (as of Laravel 5.7)
- OpenSSL extension
- PDO extension
- MBstring extension
- Tokenizer extension
- XML extension
- Ctype extension
- JSON extension
Projects
Create a new project by running:
composer create-project --prefer-dist laravel/laravel blog
Add everything to Git with:
git init git add . git commit
General
./vendor/bin/phpunit
runs all unit tests (tests/*Test.php
).
Database credentials and other configuration goes in .env
.
All variables set in .env
will be loaded into the $_ENV
superglobal and are also available via the env
helper: env('APP_DEBUG', false)
. The second parameter is the default, which will be returned if no environment variable exists for the given key.
Run php artisan config:cache
as part of production deployment.
php artisan migrate
will turn PHP schema into a database.
dd($var)
dumps $var
and then calls die()
. dd(request->all());
will print all the request variables.
Use the route()
helper instead of url()
to refer to routes.
Route groups allow you to group routes together and share configuration settings without having to repeat them for each route.
Parameterised subdomain routing can be used for multitenancy sites where each client gets its own subdomain:
Route::group(['domain' => '{client}.example.org'], function() { Route::get('/', function($client) { }); Route::get('/users/{$id}', function($client, $id) { }); });
Configuration
Most configuration is stored in .env
, which will be auto-generated by composer create-project
.
Routing
Routes are defined in routes/web.php
and routes/api.php
.
Simple route definitions can be implemented by using closures, e.g.
Route::get('/about', function() { return 'About'; });
However, this can become unwieldy for large sites. Applications using closures also cannot take advantage of Laravel's route caching.
A common alternative to closures is to pass the name and method of a controller as a string:
Route::get('/about', 'WelcomeController@about');
This would call the about
method of the App\Http\Controllers\WelcomeController
controller.
Regular expressions can be set for parameters:
Route::get('users/{id}', function ($id) { })->where('id', '[0-9]+');
Routes are matched top to bottom, so more specific regular expressions should be defined first.
Routes can be grouped, which allows common configuration settings to be defined once.
All defined routes can be listed by running:
php artisan route:list
Routes can be cached by running:
php artisan route:cache
However, from now on Laravel will only look at the cache, so you must run the above command each time you make any changes to the routing file.
Parametised subdomain routing is also available for multi-tenancy applications, where each tenant gets its own subdomain (client1.example.org, client2.example.org etc.)
Naming conventions
Convention is to call a route the plural of the resource name, followed by a period, followed by the action. For example: photos.create
. Named routes can be used with: route('photos.create')
or, if parameters are required: route('photos.edit(['id' => 1])')
.
A route name can be added like so:
Route::get('/', function () { return view('welcome'); })->name('welcome');
Route conventions:
- Index:
GET /photos
- Create:
GET /photos/create
- Store:
POST /photos
- Edit:
GET /photos/1/edit
- Update:
PATCH /photos/1
- Delete:
DELETE /photos/1
- Show:
GET /photos/1
Or:
Route::resource('photos', 'PhotosController');
Controllers
Create a controller by running:
php artisan make:controller PagesController
This will create a file:
app/Http/Controllers/PagesController.php
Add methods such as:
public function about() { return view('about'); }
Route them (routes/web.php
):
Route::get('/about', 'PagesController@about')
Create a resource controller with:
php artisan make:controller TasksController --resource
This will add methods such as index
, create
etc.
You can build routes for all these resources like so:
Route::resource('tasks', 'TasksController');
php artisan route:list
will list all of your routes.
Request data
There are two ways to access request data within a controller:
Input::get('field_name')
Or you can inject a Request:
public function create(\Illuminate\Http\Request $request) { $request->input('field_name') }
Laravel: Up and Running (p.41) claims: 'this is actually how I and many other Laravel developers prefer to get the user input'.
In later versions of Laravel:
request('field_name')
Mass assignment of request data (e.g. request->all()
) is dangerous because the user can send anything they want in the request data, and therefore could alter fields such as id
. You can protect against this using protected $fillable = []
(allow) or protected $guarded = []
(deny) in the model definition.
Views
Views are stored under: resources/views
. return view('about');
will return resources/views/about.blade.php
.
Templates
By default Laravel supports PHP templates and its own templating system called Blade. For developers who prefer Twig, the TwigBridge component provides a bridge which allows files ending .twig
to be loaded automatically.
Blade
Defaults can be provided if a variable is not set: Template:$title or 'Default'
Layouts can be created as normal Blade files, with a .blade.php
extension. The @yield('yield_name')
keyword allows you to mark placeholders where data should be inserted from templates which use the layout.
Templates can use layouts via: @extends('layout')
. Placeholders can be filled with:
@section('yield_name') Some content here @endsection
Short placeholders can also be filled using a single @section
with the second parameter as the data to be inserted:
@section('yield_name', 'Some content')
By default a yield
which is not populated will be blank. However, you can provide a default via the second parameter, such as:
<title>@yield('title', 'Default title')</title>
It it also possible to take action depending on whether a section is defined:
@hasSection('heading') <h1>@yield('heading')</h1> @endif
Partials can be included with:
@include('errors')
The above will include the contents of errors.blade.php
.
Authentication
php artisan make:auth
creates a skeleton login and authentication system.
Auth::routes()
generates all the standard routes for authentication.
The authentication system is middleware so you can wrap all the routes into a group if they require authentication. The middleware can be used in a controller or the routes file.
For routes which should not be accessible to logged in users (or, to put it another way, should only be accessible to guests), the guest
/ RedirectIfAuthenticated
middleware can be used:
Route::get('/register', 'UserController@register')->name('register')->middleware('guest');
Eloquent
Eloquent is Laravel's Active Record implementation.
Database
Default text field sizes will break on MariaDB <= 10.2.1 and MySQL <= 5.7.6 due to the number of bytes used for each character. Upgrade to a supported version or add the following to app/Providers/AppServiceProviders.php
:
<?php use Illuminate\Support\Facades\Schema; public function boot() { Schema::defaultStringLength(191); }
The default character set used by Laravel from 5.4 onwards is utf8mb4
. Basically the maximum length of a key is 767 bytes, and if 4 bytes are used per character then this effectively limits key strings to 191 characters.
Returning a database query from a route casts it to JSON.
Migrations define the modifications which should be run when making the migration up and down. Migrations are run in order of date ascending, hence filenames like 2017_01_01_00000_create_tasks_table.php
.
Modifying or dropping a column requires doctrine/dbal
.
When using SQLite, you can only drop or modify one column per migration closure.
php artisan migrate
runs all outstanding migrations. Laravel keeps track of which migrations have already been run.
php artisan migrate:reset
rolls back all database migrations.
php artisan migrate:fresh
drops all tables and then runs all migrations.
php artisan migrate:status
shows the status of each migration, i.e. whether it has been run or not.
php artisan migrate --seed
will run a seeder along with the migration.
Seeding
Creating a seeder:
php artisan make:seeder UsersTableSeeder
Forms
All forms get CSRF protection by default, but you must include the following somewhere between <form>
and </form>
@csrf
This expands to a hidden form field called _token
. Failing to include this field will result in a 419 response.
To submit a form with any method other than GET or POST, use POST and then add the following to the form:
@method('DELETE')
Validation
Laravel will always supply an $errors
object, even if there are no errors.
Previous form values can be retrieved using old('input-name')
.
Basic validation example:
$validated = request()->validate( 'title' => ['required, 'min:5', 'max:255'] ); Something::create($validated);
Example: Laravel From Scratch: Episode 15 - Two Layers of Validation
Artisan
php artisan serve
starts the PHP built-in server.
php artisan make:model Club -m -c -r
creates a model with a migration and a resource controller. This is generally the command to use to start a new model.
php artisan make:controller ClubsController -m Club --resource
creates a controller with resource routes for an existing model Club
tinker
php artisan tinker
is a command line tool which allows you to run queries.
File locations
Models: app/Club.php
Controllers: app/Http/Controllers/ClubsController.php
Version changes
- 5.6:
php artisan optimize
has been removed - no longer required.
Links
- Laracasts
- #20719 - Bug report for
artisan key:generate
. Closed as effectively WONTFIX. Seems to no longer be an issue in most cases as the installer now generates a key and adds it to.env
. - larastan - Static checking for Laravel code (based on top of PHPStan).
- Simplify Project On-boarding with Laravel Homestead
- Laravel + Docker Part 1 - setup for Development
- Laravel + Docker Part 2 - preparing for production
- Laravel Money