Laravel is a PHP framework that's really a joy to work with -- though I did find the initial learning curve a bit steep.
This tutorial describes a minimum set of steps necessary to pull content from a database and dump it to a url using Laravel's Eloquent ORM. For me, that was the breakthrough moment.
Assuming you've got Laravel installed and the database configured, here are the steps needed to get your data from the database into a web browser:
- Create a migration
- Create an Eloquent model file
- Create a database seeder file
- Seed!
- Define a route
- Create the controller
In this example, we're going to create a tasks table which simply contains an id
and a name
:
1 Design
2 Programming
3 Administration
4 Consulting
Use the Artisan command to make a migration file. That file will be used to create the database table:
php artisan migrate:make create_tasks_table
Artisan creates a skeleton migration file in app/database/migations/
named something like 2013_10_23_123456_create_tasks_table.php
. Open that up in an editor and use Laravel's Schema class to define the database table.
Something like this:
<?php
use Illuminate\Database\Migrations\Migration;
class CreateTasksTable extends Migration {
public function up()
{
if (Schema::hasTable('tasks')) {
Schema::drop('tasks');
}
Schema::create('tasks', function($table)
{
$table->increments('id');
$table->string('name');
});
}
public function down()
{
if (Schema::hasTable('tasks')) {
Schema::drop('tasks');
}
}
}
Laravel expects database table names to be plural. Sticking to that convention saves typing later on.
Model files tell Laravel's Eloquent ORM about a database table. The model name is the singular of the table in StudlyCaps. At their simplest, models can be a single line, this is all of app/models/Task.php
:
<?php class Task extends Eloquent {}
Seeder files are just simple PHP scripts that extend Laravel's Seeder class. They're stored in app/database/seeds/
and must be explicitly called from app/database/seeds/DatabaseSeeder.php
.
Below is the seed file to add the first four tasks to our table. Note this just inserts names, table IDs will auto-increment.
<?php
class TaskSeeder extends Seeder {
public function run()
{
Eloquent::unguard();
DB::table('tasks')->delete();
$rows = array(
['name' => 'Design'],
['name' => 'Programming'],
['name' => 'Administration'],
['name' => 'Consulting'],
);
Task::insert($rows);
}
}
Be sure to add $this->call('TaskSeeder');
to app/database/seeds/DatabaseSeeder.php
or Laravel won't know about the TaskSeeder
file.
At this point, the database can be seeded. This artisan command will create and seed the database in one step:
php artisan migrate --seed
The table should now exist in the database:
> select * from tasks;
+----+----------------+
| id | name |
+----+----------------+
| 1 | Design |
| 2 | Programming |
| 3 | Administration |
| 4 | Consulting |
+----+----------------+
Add the following line to app/routes.php
, this defines a "resourceful route" to the controller we'll define in the next step.
Route::resource('task', 'TaskController');
Use Artisan to generate a skeleton controller:
php artisan controller:make TaskController
That creates app/controllers/TaskController.php
where various resourceful route handlers are defined.
In the interest of brevity, I'm going to skip View functions and templates and just dump JSON data directly into the browser.
Rewrite the index
and show
methods like this:
public function index()
{
return Task::all();
}
public function show($id)
{
return Task::find($id);
}
That's it, /task
will show a JSON dump listing all tasks and /task/{id}
will display a detail view of whatever entry matches {id}
.
With a little bit more work, we can add the complete set of CRUD (Create, Retrieve, Update, Delete) methods to TaskController
.
But first, since the tasks table doesn't use created/modified timestamps, add a line (and some whitespace) to app/models/Task.php
so it looks like this:
<?php
class Task extends Eloquent {
public $timestamps = false;
}
Back in TaskController.php, two methods need to be modified to let us create new tasks, create
and store
.
Skipping views and templates again, modify create
so it dumps a simple form to create a new task. It should look something like this:
public function create()
{
echo Form::model('Task', array('route' => 'task.store'));
echo Form::text('name');
echo Form::submit();
echo Form::close();
}
Form::model
sets up a form that knows something about the Task
model and Form::text()
is the editing field.
Next, the controller needs to save input. Edit the store
method to create a new Task, set its name from Input
, then save and return to the list of tasks. The basic code for this is beautifully straightforward and self-documenting:
public function store()
{
$task = new Task;
$task->name = Input::get('name');
$task->save();
return Redirect::to('task');
}
That's all that's needed. Go to /task/create
and you should be able to create a new task.
Similar to creating tasks, editing uses the edit
and update
methods. The main difference is that these two methods have an $id
parameter so they can work on a specific Task. The edit
method looks very similar to the create
method:
public function edit($id)
{
$task = Task::find($id);
echo Form::model($task, array('route' => ['task.update', $task->id], 'method' => 'PUT'));
echo Form::text('name');
echo Form::submit();
echo Form::close();
}
The main changes are that we store the specific task in $task
and changed some arguments to Form::model
.
The only difference between update
and store
is that update
retrieves a task rather than creating one.
public function update($id)
{
$task = Task::find($id);
$task->name = Input::get('name');
$task->save();
return Redirect::to('task');
}
With those in place, going to /task/2/edit
should present a pre-populated form which lets us modify existing tasks.
Deleting is slightly trickier than the other methods since it doesn't get a distinct url (for good reason). Instead, tasks are deleted when a task url is accessed with the DELETE
method.
The destroy
method is very simple:
public function destroy($id)
{
Task::find($id)->delete();
return Redirect::to('task');
}
To get there, I'm going to add a delete button to the view returned by the show
method:
public function show($id)
{
$task = Task::find($id);
echo $task;
echo Form::model($task, array('route' => ['task.destroy', $task->id], 'method'=> 'DELETE'));
echo Form::submit('Delete');
echo Form::close();
}
The direct url for a Task will now include a delete button that will remove that task from the list.
Laravel provides a very robust toolset for getting a lot of common tasks done with a minimum of code. With a couple files and a few dozen lines of code, the basics of a robust