Browsing the API (http://laravel.com/api) can be somewhat intimidating at first.
But it is often the best way to understand how a particular method works under the
hood. Here are a few tips:
• The Illuminate namespace does not refer to a third-party library. It is the
namespace that the author of Laravel has chosen for the different modules
that constitute Laravel. Every single one of them is meant to be reusable and
used independently from the framework.
• When searching for a class definition, for example, Auth, in the source code
or the API, you might bump into Façade, which hardly contains any helpful
method and only acts as a proxy to the real class. This is because almost
every dependency in Laravel is injected into the application container when
it is instantiated.
• Most of the libraries that are included in the vendor/ directory contain a
README file, which details the functionality present in the library (for
example, vendor/nesbot/carbon/readme.md).
If, on the other hand, you have not worked with RESTful sites, the use of the PUT
and DELETE HTTP methods might be new to you. Even though web browsers do
not support these methods for standard HTTP requests, Laravel uses a technique
that other frameworks such as Rails use, and emulates those methods by adding
a _method input field to the forms. This way, they can be sent over a standard
POST request and are then delegated to the correct route or controller method
in the application.
Using the built-in development server
To start the application, unless you are running an older version of PHP (5.3.*), you
will not need a local server such as WAMP on Windows or MAMP on Mac OS since
Laravel uses the built-in development server that is bundled with PHP 5.4 or later.
To start the development server, we use the following artisan command:
$ php artisan serve
Artisan is the command-line utility that ships with Laravel and its features will be
covered in more detail in a future chapter.
Next, open your web browser and visit http://localhost:8000; you will be
greeted with Laravel's welcome message.
Catching the missing routes
Instead of displaying a detailed error message to your visitors, you can catch the
"Not Found" exception and display a custom message by defining the following
missing method for your application inside app/start/global.php:
App::missing(function($exception){
return Response::make("Page not found", 404);
});
Here we are not merely returning a string, but a Response object with the message
as its first parameter and an HTTP status code as the second parameter. In the
first two routes that we wrote, Laravel automatically converted the string that
we returned into a 200 OK HTTP response (for example, in the first route it is:
Response::make("All cats", 200)). While the difference might not be obvious
to the end users, the distinction between "404 Not Found" and "200 OK" is important
for the search engines that crawl your site or when you are writing an API.
Handling redirections
It is also possible to redirect visitors by returning a Redirect object from your
routes. If for example, we wanted everyone to be redirected to /cats when they
visit the application for the first time, we would write the following lines of code:
Route::get('/', function(){
return Redirect::to('cats');
});
Route::get('cats', function(){
return "All cats";
});
Creating the Eloquent models
The first and easiest step is to define the models with which our application is going
to interact. At the beginning of this chapter, we identified two main entities, cats
and breeds. Laravel ships with Eloquent, a powerful ORM that lets you define these
entities, map them to their corresponding database tables, and interact with them
using PHP methods rather than raw SQL. By convention, they are written in the
singular form; a model named Cat will map to the cats table in the database,
and a hypothetical Mouse model will map to the mice.
The Cat model, saved inside app/models/Cat.php, will have a belongsTo
relationship with the Breed model, which is defined in the following code snippet:
class Cat extends Eloquent {
protected $fillable = array('name','date_of_birth','breed_id');
public function breed(){
return $this->belongsTo('Breed');
}
}
The $fillable array defines the list of fields that Laravel can fill by mass
assignment, a convenient way to assign attributes to a model. By convention, the
column that Laravel will use to find the related model has to be called breed_id in
the database. The Breed model, app/models/Breed.php is defined with the inverse
hasMany relationship as follows:
class Breed extends Eloquent {
public $timestamps = false;
public function cats(){
return $this->hasMany('Cat');
}
}
By default, Laravel expects a created_at and updated_at timestamp field in the
database table. Since we are not interested in storing these timestamps with the
breeds, we disable them in the model by setting the $timestamps property to false.
This is all the code that is required in our models for now. We will discover various
other features of Eloquent as we progress in this book; however, in this chapter we
will primarily use two methods: all() and find(). To illustrate their purpose,
here are the SQL queries that they generate:
Breed::all() => SELECT * FROM breeds;
Cat::find(1) => SELECT * FROM cats WHERE id = 1;
In the views and controllers of our application, the properties of an Eloquent model
can be retrieved with the -> operator: $cat->name. The same goes for the properties
of the related models, which are accessible as shown: $cat->breed->name. Behind
the scenes, Eloquent will perform the necessary SQL joins.
Building the database schema
Now that we have defined our models, we need to create the corresponding database
schema. Thanks to Laravel's support for migrations and its powerful schema builder,
you will not have to write any SQL code and you will also be able to keep track of
any schema changes in a version control system. To create your first migration,
open a new terminal window, and enter the following command:
$ php artisan migrate:make add_cats_and_breeds_table
This will create a new migration inside app/database/migrations/. If you open
the newly created file, you will find some code that Laravel has generated for
you. Migrations always have an up() and down() method that defines the schema
changes when migrating up or down. By convention, the table and field names are
written in "snake_case". Moreover, the table names are written in the plural form.
our first migration looks like this:
public function up(){ Schema::create('cats', function($table){ $table->increments('id'); $table->string('name'); $table->date('date_of_birth'); $table->integer('breed_id')->nullable(); $table->timestamps(); }); Schema::create('breeds', function($table){ $table->increments('id'); $table->string('name'); }); } public function down(){ Schema::drop('cats'); Schema::drop('breeds'); }
The date() and string() methods create fields with the corresponding types
(in this case, DATE and VARCHAR) in the database, increments() creates an auto
incrementing INTEGER primary key, and timestamps() adds the created_at and
updated_at DATETIME fields that Eloquent expects by default. The nullable()
method specifies that the column can have NULL values.
To run the migration, enter the following command:
$ php artisan migrate
When it is run for the first time, this command will also create a migrations table
that Laravel uses to keep track of the migrations that have been run.
Seeding the database 播种
Rather than manually populating our database, we can use the seeding helpers
offered by Laravel. This time, there is no Artisan command to generate the file,
but all we need to do is create a new class called BreedsTableSeeder.php inside
app/database/seeds/. This class extends Laravel's Seeder class and defines the
following run() method:
<?php use IlluminateDatabaseSeeder; class BreedsTableSeeder extends Seeder { public function run() { DB::table('breeds')->insert(array( array('id'=>1,'name'=>'Domestic'), array('id'=>2, 'name'=>"Persian"), array('id'=>3, 'name'=>"Siamese"), array('id'=>4, 'name'=>"Abyssinian"), )); } }
You can bulk insert an array but you could also insert arbitrary code in the run()
method to load data from a CSV or JSON file. There are also third-party libraries
that can help you generate large amounts of test data to fill your database.
To control the order of execution of the seeders, Laravel lets you call them
individually inside app/database/seeds/DatabaseSeeder.php. In our case,
since we only have one seeder, all we need to write is the line that follows:
$this->call('BreedsTableSeeder');
Then, we can seed the database by calling it using the following command:
$ php artisan db:seed
Mastering Blade
Now that we have some information in our database, we need to define the
templates that are going to display it. Blade is Laravel's lightweight template
language and its syntax is very easy to learn. Here are some examples of how Blade
can reduce the number of keystrokes and increase the readability of your templates:
Standard PHP syntax Blade syntax
<?php echo $var; ?> {{$var}}
<?php echo htmlentities($var); ?> {{{$var}}}
<?php if($cond): ?>…<?php endif; ?> @if($cond) … @endif
You should only use the double braces to output a variable if you trust the user
or the value that is returned. In all other cases, make sure that you use the triple
brace notation to avoid XSS vulnerabilities (explained in a bit more detail in the
next chapter).
Blade supports all of PHP's major constructs to create loops and conditions: @for,
@foreach, @while, @if, and @elseif; therefore, allowing you to avoid opening
and closing the <?php tags everywhere in your templates
Creating a master view
Blade lets you build hierarchical layouts by allowing the templates to be nested and
extended. The following code snippet is the "master" template that we are going to
use for our application. We will save it as app/views/master.blade.php.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Cats DB</title> <link rel="stylesheet" href="{{asset('bootstrap-3.0.0.min. css')}}"> </head> <body> <div class="container"> <div class="page-header"> @yield('header') </div> @if(Session::has('message')) <div class="alert alert-success"> {{Session::get('message')}} </div> @endif @yield('content') </div> </body> </html>
The Bootstrap 3 CSS framework is included to speed up the prototyping of the
application interface. You can download it from http://getbootstrap.com and
place the minified CSS file inside the public/ folder. To ensure that its path prefix is
set correctly, even when Laravel is run from a subfolder, we use the asset() helper.
In the following template, we will use other helpers such as url and link_to, which
help us write more concise code and also escape from any HTML entities. To
see the complete list of Blade template helpers that are available to you, visit:
http://laravel.com/docs/helpers.
To inform the user about the outcome of certain actions, we have prepared a
notification area between the header and the page content. This flash data (in other
words, the session data that is only available for the next request) is passed and
retrieved to and from the Session object.
The @yield directives act as placeholders for the different sections that a child
view can populate and override. To see how a child template can re-use them, we
are going to recreate the About view by changing its extension to .blade.php and
extending our master template:
@extends('master')
@section('header')
<h2>About this site</h2>
@stop
@section('content')
<p>There are over {{$number_of_cats}} cats on this site!</p>
@stop
The @section ... @stop directives delimit the blocks of content that are going
to be injected into the master template。
The next set of routes will handle the three different types of actions and redirect
the user using a flash data message. This message is then retrieved in the Session
object using Session::get('message') in the master template. Any input data
that is received by the application and that you would normally access via the $_GET
or $_POST variables is instead retrievable using the Input::get() method. It is also
possible to retrieve an array of all the input data with Input::all(). They also use
more features of Eloquent that we have not seen before. The POST /cats and PUT /
cats/{cat} routes, respectively, use the create() and update() methods from
Eloquent with Input::all() as their argument. This is only possible because we
specified the specific fields that are fillable in the Cat model beforehand: