Book Image

Laravel Starter

By : Shawn McCool
Book Image

Laravel Starter

By: Shawn McCool

Overview of this book

<p>Laravel is fundamentally changing the PHP web-development landscape. Laravel is bringing the paradigm-shifts that PHP developers have been craving. We now can take control of our application architecture and advance our craft without needing to fight against our tools. Laravel&rsquo;s philosophy is to provide a highly flexible architecture and an extremely expressive API while emphasizing PHP&rsquo;s strengths and abstracting out its weaknesses. For these reasons Laravel is ideal for quickly creating high performance, robust applications. By providing developers with tools for automating tasks including database schema modification, CRUD operations, and testing we&rsquo;re able to reduce our workload, application complexity, and human-error.<br /><br />"Laravel Starter" is the ideal introduction to this game-changing framework. Learn best-practiced approaches to web-application development with Laravel from a seasoned professional.<br /><br />It starts out by installing and configuring the framework step-by-step. Then you&rsquo;ll use Laravel best-practices to create a private user administration system that is ready for real-world use. The later part deals with digging deep into Eloquent relationships, exploring the different relationship types and how Eloquent is working under-the-hood to simplify your life without forcing you to relinquish control. Exploring Laravel&rsquo;s simple yet flexible authentication system, data validation, and filters allows you to easily run code before and after your controller actions. Finally, it discusses Laravel bundles, the most flexible PHP modular code implementation in its weightclass.<br /><br />Focused on the how as much as the why, Laravel Starter gives you the tools to immediately begin creating professional web-applications with Laravel.</p>
Table of Contents (8 chapters)

Quick start: Creating your first web application


In this section we'll be building a user administration tool. User admins are one of the most common components to be found in web applications. They also use a number of important systems that we want to explore with Laravel including database interactions, forms, and routing.

We'll be storing and retrieving records from a database so now it would be a good time for you to create a database for this application. Keep the database name, user, and password handy.

Let's get started.

Step 1 – Database configuration

Armed with our database name, user, and password, we can now tell Laravel how to connect to our database.

Open the file application/config/database.php and scan the contents. You'll find example configurations for each database driver. Determine which driver you're going to use from the available options (sqlite, mysql, pgsql, and sqlserv) and enter the name of the driver as the default database connection.

Then, in the Connections section add your database name, user, and password.

Ok! We're just where we want to be. Let's get started by creating the users table.

Step 2 – Creating the users table using migrations

You might typically create the users table with a tool like phpMyAdmin or Navicat. But, Laravel provides a fancy migrations system for us and we should use it because it improves our workflow and reduces deployment bugs.

Migrations are version control for your schema modifications. Migrations reduce the amount of headache that we face by requiring us to only define the schema alteration once. Afterwards, we can deploy our changes to any number of systems without the potential for human error.

Note

Migrations are especially useful for projects in which you're collaborating with others. Like using source control, migrations are always a good idea.

Developers who are new to migrations might believe them unnecessary or believe that they add too much additional work at first. But, stick with it and their value will become quickly apparent.

Let's start by creating our migration template with Laravel's command-line tool Artisan.

In order to use Artisan, we will need to add the directory which contains the PHP binary to our PATH environment variable. This lets us execute the PHP binary from anywhere, as the system will know where to find it. You can test this by running the following command from your command-line terminal:

# php -v 

You should see a nice readout telling you which version of PHP you're running.

If you find that your command-line interface doesn't know where the PHP binary is, you'll need to update your system's PATH. You can modify your PATH variable on OS X and Linux with the following command line:

# export PATH=/path/to/php/binary:$PATH

Windows users will need to right-click on Computer from the start menu and click on Properties. Click on Advanced system settings, and then click on Environment Variables. Here you can find the system variable PATH and add the directory that contains your PHP binary.

Now that the PHP binary is in our path, let's navigate to our project folder. Now we can go ahead and install our migrations database table. Execute the following command:

# php artisan migrate:install

You should see the message, Migration table created successfully. If you get errors, verify that your database connection information is correct.

Next, let's create a new migration template in our application/migrations folder.

# php artisan migrate:makecreate_users_table

The migration files are formatted with the year, month, day, time, and the text that you added that enable it to be identified by a human, in this case create_users_table. Mine looks like 2012_08_16_112327_create_users_table.php. The structure of the filename is important as it helps Laravel to understand the order in which it should run the migrations. By using a convention for naming your migrations, you'll be helping your team to better understand your work (and vice-versa). An example convention might consist of entries like create_users_table, add_fields_to_users_table, or rename_blog_posts_table_to_posts.

The migrations file contains a single class with the human readable name that we entered before. The class has two methods, up() and down().

When migrations are run, Laravel reads in each migration file one by one and runs its up() method. If you feel that a mistake has been made, you can rollback migrations. When rolling back a change, Laravel runs the down() method. The up() method is for making your desired changes to the database. The down() method is for reverting your changes.

Let's go ahead and look at what our create_users_table migration should look like:

classCreate_Users_Table
{

  /**
  * Make changes to the database.
  *
  * @return void
  */
  public function up()
  {
    Schema::table('users', function($table)
    {
      $table->create();

      $table->increments('id');

      $table->string('email');
      $table->string('real_name');
      $table->string('password');

      $table->timestamps();
    });
  }

  /**
  * Revert the changes to the database.
  *
  * @return void
  */
  public function down()
  {
    Schema::drop('users');
  }

}

Let's first discuss our up() method. Our goal is to create the users table and to define the fields within it. In order to accomplish this goal, we'll use the Laravel Schema class. When creating or making modifications to tables, we use the Schema class' table() method.

Schema::table() accepts two arguments. The first is the name of the table that you'll be interacting with, in this case it's users. The second argument is a closure which contains your table definition. The closure receives the argument $table and this is the object that we'll be interacting with to define the table.

$table->create();

This line tells Laravel that the table will need to be created. If we omit this line, Schema will generate the ALTER TABLE syntax rather than the CREATE TABLE syntax.

$table->increments('id');

The increments() method tells Schema that the specified field should be an auto-incremented primary key. With Laravel, you'll want to use simple field names such as id, email, and password. If you aren't familiar with using Object-Relational Mapping (ORM), you may be in the habit of creating those same field names with the table name as a prefix. For example, user_id, user_email, user_password. The purpose behind defining field names with the table name as a prefix is to simplify query generation when using a query builder. This is no longer necessary and it's best to follow the more simple convention as it manages redundant interactions for you, removing the need for you to continuously write the boilerplate code.

$table->string('email');
$table->string('real_name');
$table->string('password');

Next we have a few string declarations. These will be created as the VARCHAR fields with the default length of 200. You can override the length of these fields by passing a second argument that represents the intended length. For example:

$table->string('email', 300);

This line creates a VARCHAR field named email with a length of 300.

Note

It's important to note that we shouldn't reduce the size of the password field as we'll need that length for the output from Laravel's Hash class.

$table->timestamps();

Finally, we come to the timestamps() method. This will create two DATETIME fields (created_at and updated_at). It is not unreasonable to create the timestamp fields for every table in the database as they can be very useful for troubleshooting down the road. The Eloquent ORM will automatically manage these timestamp fields for us. So, we can forget about them for now.

The down() method should revert any changes made to the up() method. In this case, the up() method creates a database table called users. So, the down() method should remove the table.

Schema::drop('users');

This is done with the method Schema::drop(). drop() takes a single argument, a string value containing the name of the table that you wish to drop.

That's it! We have our first migration. Once you memorize the commonly used methods such as increments(), string(), decimal(), timestamps(), and date(), you'll be able to make migrations just as fast as you were able to modify your database with your preferred database management tool. But, now we gain the added benefit from using them in versioned and collaborative situations.

Now, we're ready to run our migrations. From this point on, running migrations will always be done in the same way. Let's go ahead and give it a shot:

# php artisan migrate

Now, we should see the message, Migrated: 2012_08_16_112327_create_users_table.

It's very important to test our migrations. If we don't test our migrations, it could come back to bite us later in the project when we need to roll back migrations and run into an error. Proper migration testing verifies that the up() and down() methods both function as intended.

To test the up() method, run the migration and open your preferred database management application. Then, verify that everything is as you intended. Then, test the down() method by rolling back the migration and doing the same. Roll back your migration now by using the following command:

# php artisan migrate:rollback

Optimally, you will be notified that the migration was rolled back successfully. Double-check that your database no longer contains the users table. That's it! This migration is good to go. Run your migrations for one last time and let's move on to the next step.

# php artisan migrate

Step 3 – Creating an Eloquent user model

Now that we have created our users table, we should go ahead and create our user model. In the context of MVC, a model is a class that represents various types of data interactions. The data can include information stored in a database such as users, blog posts, and comments or interactions with many other types of data sources such as files, forms, or web services. For the sake of this document, we'll primarily be using models to represent the data that we store in our database.

Models sit in the application/models folder. So go ahead and create the file application/models/user.php with the following code:

class User extends Eloquent
{

}

This is all we need! This tells Laravel that our user model represents data in the users table. Wait! How does Laravel know that? Well, because we're following Laravel's conventions of course! Our database table users is plural because it signifies that it stores more than one user record. The model class is named User singular because it represents one single user record in the users table. The User class name is capitalized because of the standard for using Pascal case for class names. If your database table was named user_profiles, your model's class name would be UserProfile.

We can see how using conventions prevents us from having to make a bunch of configurations. Well, what if we must use a database table that doesn't follow conventions? No problem! We can just define the table name manually. Just add the following line to the User class:

public static $table = 'my_users_table';

That's all it takes. Now, Laravel knows that when interacting with this model, it should use the table named my_users_table. Most conventions in Laravel can be overridden with configuration when necessary.

There's one important thing that we should add to our user model. We're storing the user's e-mail address, real name, and password. We want to make sure that the user's password isn't stored in plain text. We need to hash their password before it is stored in the database. For this we'll create a setter.

A setter is a method that intercepts the assignment of an attribute. In this case, we're going to intercept the assignment of the password attribute, hash the value that we received, and then store the hashed value in the database.

Let's look at some code.

class User extends Eloquent
{
  public function set_password($string)
  {
    $this->set_attribute('password', Hash::make($string));
  }
}

As you can see, the convention for declaring setters is to prefix the name of the attribute whose assignments you want to intercept with set_. The user's password will be passed to the setter as the argument $string.

We use the set_attribute() method to store a hashed version of the user's password into the model. Typically the set_attribute() method is not necessary. But, we don't want our setter to be stuck in an endless loop as we continuously attempt to assign $this->password. The set_attribute() method accepts two arguments. The first is the name of the attribute and the second is the value that we want to assign to it. When assigning values with set_attribute(), setter methods will not be called and the data will be directly modified within the model.

We're using the make() method from Laravel's Hash class to create a salted hash of the user's password.

Step 4 – Routing to a closure

Before we can move on and test our user model, we need to know a few things about routing in Laravel. Routing is the act of linking a URL to a function in your application. In Laravel, it's possible to route in two ways. You can either route to a closure or a controller action. As we'll be going over controllers in more detail later, let's start by looking at how we can route to a closuRoutes in Laravel are declared in application/routes.php. This file will represent the connection between your site's URLs and the functions that contain application logic for your site. This is very handy as other developers will be able to come into your project and know how requests are routed, simply by reviewing this file.

Here is a simple example of routing to a closure:

Route::get('test', function(){
  return "This is the test route.";
});

We're using the Route::get() method to define the route. Route::get() registers a closure with the router that specifically responds to a GET request at the specified URI. To register a closure for the POST, PUT, and DELETE requests, you'd use Route::post(), Route::put(), and Route::delete() respectively. These methods correspond to what are commonly referred to as the HTTP verbs.

Typically, developers only interact with the GET and POST requests. When a user clicks on a link or enters a URL in their address bar, they're creating a GET request. When a user submits a form, they're typically creating a POST request.

The first argument for the Route::get() method is the URI for the route (the part of the URL after the domain name), and the second argument is the closure which contains the desired application logic.

Let's update the example and test the route.

Note

Notice that instead of using echo to output the string we're returning it. That's because whether you route to a closure or route to a controller action, you should always return your response. This allows Laravel to handle many situations in a robust way.

Now go ahead and navigate to http://myfirst.dev/test. You will see the message, This is the test route.

Step 5 – Creating users with Eloquent

Now, let's test the User model and learn a bit about Eloquent in the process. In this application, we're going to interact with the User model in a few ways. We'll want to use the Create, Retrieve, Update, and Delete methods for user records. These common methods are referred to as CRUD methods.

Eloquent simplifies development by removing the need to manually implement CRUD methods for your models. If you've ever designed models without an ORM, you are already aware that this alone can save you many hours on large sites.

Now, let's explore the various ways in which you can create new user records. We'll repurpose our test route from the previous step to help us get to know Eloquent. Update the route declaration with the following code:

Route::get('test', function()
{
  $user = new User;

  $user->email = "[email protected]";
  $user->real_name = "Test Account";
  $user->password = "test";

  $user->save();

  return "The test user has been saved to the database.";});

Let's review:

$user = new User;

First, we create a new instance of our User model and store it in the $user variable:

$user->email = "[email protected]";
$user->real_name = "Test Account";
$user->password = "test";

Then, we set some attributes in our User model. These attributes directly correspond to the fields in our users database table.

$user->save();

Next, we tell Eloquent that we want to save the contents of this model to the database.

return "The test user has been saved to the database.";

Finally, we output this string to the browser so that we know that all is well.

Go ahead and navigate to http://myfirst.dev/test in your browser. You should see the confirmation message that the user has been saved to the database.

Now, take a look at the contents of your database's users table. You will see a new record filled with our data. Notice that the timestamps fields have been automatically pre-populated for you. It's that easy to create new database records with Eloquent!

Step 6 – The users controller

Now it's time for us to create our first controller. You've already learned how we can route to a closure and you can use this method to make an entire web-application. So, what are controllers and why should we use them?

Controllers are containers for methods that contain application logic related to a common domain. A domain is simply a categorization of purpose. In the context of our web application, we will be working solely with administrating user data. Therefore, our domain is users. Our users controller will contain the application logic that controls our application flow and delivers our database data to the view for formatting.

Since controllers allow us to group logic, we can also apply configurations to a controller that will affect all of the methods inside it. We'll explore more of this concept later.

Let's create the file application/controllers/users.php and fill it with our controller class' skeleton:

<?php

class Users_Controller extends Base_Controller
{

  public function action_index()
  {
    return "Welcome to the users controller.";
  }

}

Our users controller is a class whose name is constructed from the domain of the methods contained within and is suffixed with _Controller. Since this controller's domain is user accounts, our controller is named Users_Controller. The _Controller suffix is required because it prevents controller classes from having name collisions with other classes in the system.

Note

A controller's domain should always be plural when applicable.

You'll notice that our Users_Controller class extends Laravel's default Base_Controller class. This is a good practice because if we need some code or configurations to affect all of our controllers, we can just edit the file application/controllers/base.php and make changes to the Base_Controller class. Every controller that extends the Base_Controller class will be affected.

You'll also notice that we have defined a controller action named index. A controller action is a method within a controller class that we intend to be the destination for a route. You may decide to create methods within a controller class that will only be called from other methods within that class; these would not be actions.

Controller actions are named with the prefix action_. This is an important distinction because we do not want users to be able to access methods within our controller that aren't actions.

So, now that we have this controller how can we access the index action from our browser? For now, we can't. We haven't routed any URL to that controller action. So, let's do that. Open up application/routes.php and add the following line:

Route::controller('users');

As you can see, we can register an entire controller with the router with one command. Now, we can access our users controller's index action with http://myfirst.dev/users/index. The index action is also considered to be the default action for a controller, so we can also access our index action at http://myfirst.dev/users.

It's important to note that while routing to closures is convenient, routing to controllers is generally considered better practice for a few reasons. Controllers are not loaded into memory until their routes are accessed, which helps to reduce the memory footprint of your application. They also make maintenance easier by making it quite clear where the developer can find the code for the route. Controllers are derived from a base class, so it's simple to make a change in one class and through inheritance have that change affect other classes. Finally, since controllers are actions grouped by purpose, it's often quite convenient to assign filters on a per-controller basis. We'll talk more about filters in the section Top 5 features you need to know about.

Step 7 – Creating the users index view

Now we can go to http://myfirst.dev/users and access the index method of our controller. That's pretty cool, but our users controller's index page needs to show us a list of the users in the system. To display a list of users, we're going to need to create a view.

A view is a file that contains formatting data (typically HTML). PHP variables, conditionals, and loops are used within the view to display and format dynamic content.

Laravel provides its own templating system called Blade. Blade removes PHP tags and provides shortcuts for common tasks so that your views are cleaner and easier to create and maintain.

Let's get started by creating the folder application/views/users/. This folder will store all of the views for our users controller. It is a standard convention to create a folder under application/views for each controller that needs a view. Then, create the view file at application/views/users/index.blade.php. The convention is to name the view file after the controller action in which it's used. In this example, we're using Blade. If you do not wish to use Blade simply name the file index.php.

Let's fill the view with the following HTML:

<h1>Users</h1>

<ul>
  <li>Real Name - Email</li>
</ul>

It's not pretty. But, it's easy to understand.

Now, we'll make a modification to the users controller's index action:

public function action_index()
{
  return View::make('users.index');
} 

Now, where we were previously returning a string, we'll return a View object. Let's take a closer look at what's happening here.

The View class' make() method is a factory method that is used to generate View objects. In this case, we're passing the argument users.index. This is Laravel's internal notation for referring to view files. The notation is made up of the path to the view file relative to the application/views directory including the filename without its file extension. For example, application/views/users/index.php would be written as users.index, and application/views/admin/users/create.php would be written as admin.users.create.

Note

It's important to note that we're returning the View object instead of using echo to send the rendered contents of the view to the browser. This is an important aspect of the way that Laravel works. We'll never use echo from within a routed closure or a controller action. Instead, we'll always return the result and allow Laravel to handle things appropriately.

Now, when we go to http://myfirst.dev/users, we'll see the view that we just created!

Step 8 – Passing data from a controller to a view

The fact that we can go to a URL and see the view file that we created is pretty cool. But, we need to be able to see the list of users from our database. To accomplish this goal, we'll first query the User model from our controller action, and then pass that data to the view. Finally, we'll update our view to display the user data received from the controller.

Let's start by updating our users controller's index action:

public function action_index()
{
  $users = User::all();

  return View::make('users.index')->with('users', $users);
}

Let's look at this line by line:

$users = User::all();

First, we request all users as objects from Eloquent. If we have no rows in our users table, $users will be an empty array. Otherwise, $users will be an array of objects. These objects are instantiations of our User class.

return View::make('users.index')->with('users', $users);

Then, we modify the creation of our View object a bit. We chained a new method named with(). The with() method allows us to pass data from the controller into the view. This method accepts two arguments. The first argument is the name of the variable that will be created in the view. The second argument will be the value of that variable.

To recap, we've queried the database for all users and passed them as an array of User objects to the view. The array of User objects will be available in the view as the variable $users due to the fact that users was the first argument to the with() method.

Step 9 – Adding our dynamic content to the view

Now that our view has access to the user data, let's update the view so that we can actually see those users.

<h1>Users</h1>

@if($users)
  <ul>
    @foreach($users as $user)
      <li>{{ $user->real_name }} - {{ $user->email }}</li>
    @endforeach
  </ul>
@else
  Looks like we haven't added any users, yet!
@endif

Blade is easy to understand and results in much more elegant code. The {{ }} tags output the results of the expression within them and replace a typical echo command. Other constructions such as if(), foreach(), and for() are the same, but without PHP tags and with a preceding @.

Note

Blade doesn't incur a significant performance penalty since it renders to a raw PHP cache. Parsing of a Blade template is only done when changes have been made.

It's also important to note that you are still free to use PHP tags in the Blade templates.

As you can see we use an if statement to check if the $users array contains data. If it does, we loop through the users and display a new list item for each. If the $users array doesn't contain any data, we output a message saying so.

And that's it! Save the file and hit reload in your browser, and you will see the test account that we created.

Note

This may be a good time to play around with the HTML or add new users using the test route that we made to get a better feel for how everything works.

Step 10 – RESTful controllers

We've already mentioned that Laravel's routing system enables you to route GET, POST, PUT, and DELETE requests to closures. But we haven't talked about how to individually route them to controller actions.

The answer is RESTful controllers! RESTful controllers enable you to route to different controller actions based on the request method. Let's configure our application to use RESTful controllers.

Since all of our controller classes are derived from the Base_Controller class, we can simply add the $restful configuration to it and all of our controllers will be affected.

Update your Base_Controller class to look like this:

classBase_Controller extends Controller{
  public $restful = true;

  /**
  * Catch-all method for requests that can't be matched.
  *
  * @param  string    $method
  * @param  array     $parameters
  * @return Response
  */
  public function __call($method, $parameters)
  {
    return Response::error('404');
  }

}

Now, every controller that extends Base_Controller (including our own Users_Controller) is a RESTful controller!

But, wait. Now, we'll get a 404 error when we go to http://myfirst.dev/users. This is because we are not declaring our actions the RESTful way.

Edit your Users_Controller class and change the line:

public function action_index()

To this:

public function get_index()

Your Users_Controller class should now look like this:

classUsers_Controller extends Base_Controller
{

  public function get_index()
  {
    $users = User::all();

    return View::make('users.index')->with('users', $users);
  }

}

Now, when we save and reload the page in our browser it works again! The get_ prefix that we added to our index method serves much the same purpose as the action_ prefix that we were using previously.

Unless a method is prefixed appropriately, Laravel will not route URLs to them. In this way, we can ensure that only controller actions are routable and that our web-application's users can't access other methods that may exist in our controllers by simply typing the names of the methods in their browsers.

When an action is prefixed with get_, it will only respond to the GET requests. An action prefixed with post_ will only respond to the POST requests. The same is true of put_ and delete_. This gives us more code separation and allows us to really improve the readability and maintainability of our application.

Step 11 – Creating a form for adding users

It's time to give our site's administrators the ability to create users. We're going to need a new form. Let's start off by creating the file application/views/users/create.php and populating it with the following form HTML:

<h1>Create a User</h1>

<form method="POST">
  Real Name: <input type="text" name="real_name"/><br />
  Email: <input type="text" name="email"/><br />
  Password: <input type="password" name="password" /><br />
  <input type="submit" value="Create User"/>
</form>

Then, let's create a controller action for it. In our Users_Controller, let's add the following action.

public function get_create()
{
  return View::make('users.create');
}

Now, we can go to http://myfirst.dev/users/create and see our form. Once again, it's not pretty but sometimes simple is best.

Step 12 – Routing POST requests to a controller action

When we submit the form it's going to make a POST request to our application. We haven't yet created any actions to handle the POST requests, so if we submit it now we're going to get a 404 error. Let's go ahead and create a new action in Users_Controller:

public function post_create()
{
  return "The form has been posted here.";
}

Notice that this method has the same action name as the get_create() method that we're using to show the create user form. Only the prefix is different. The get_create() method responds to the GET requests where the post_create() method responds to the POST requests. In the case of our create user form, the post_create() method receives the contents of the form's submitted input fields.

Go ahead and submit the create user form and you'll see the message, The form has been posted here.

Step 13 – Receiving form input and saving to the database

Now that we are receiving the data from the form, we can go ahead and create the user account.

Let's update our post_create() function in the Users_Controller class to add this functionality:

public function post_create()
{
  $user = new User;

  $user->real_name = Input::get('real_name');
  $user->email = Input::get('email');
  $user->password = Input::get('password');

  $user->save();

  return Redirect::to ('users');
}

Here we're creating a new user record in the same way that we did in our test route. The only difference is that we're using Laravel's Input class to retrieve the data from the form. Whether the data comes from a GET request's query string or a POST request's post data, the Input::get() method can be used to retrieve the data.

We populate the User object with input data. Then we save the new user.

return Redirect::to('users');

Here's something new. Instead of returning a string or a View object, we're using the Redirect class to return a Response object. Both routed closures and controller actions are expected to return a response. That response could be a string or a Response object. When a View object is returned it will be rendered as a string. The Redirect class' to() method specifically tells Laravel to redirect the user to the page specified in its argument. In this example the user will be redirected to http://myfirst.dev/users.

We're redirecting the user here so that they can see the updated list of users, which will include the user that they just created. Go ahead and give it a try!

Step 14 – Creating links with the HTML helper

We need a link from the users index view to the create user form as it's currently inaccessible from the user interface. Go ahead and add the link to the file application/views/users/ index.blade.php with the following line of code:

{{ HTML::link('users/create', 'Create a User') }}

Laravel's HTML class can be used to create a variety of HTML tags. You might be asking yourself why you wouldn't simply write the HTML for the link yourself. One very good reason to use Laravel's HTML helper class is that it provides a unified interface for creating tags that may need to change dynamically. Let's look at an example to clarify this point.

Let's say that we want that link to look like a button and our designer created a sweet CSS class named btn. We need to update the call to HTML::link() to include the new class attribute:

{{ HTML::link('users/create', 'Create a User', array('class' => 'btn')) }}

Actually, we could include any number of attributes to that class and they'd all be handled appropriately. Any attribute assigned to the HTML elements can be updated dynamically by passing a variable to that method instead of declaring it inline.

<?php $create_link_attributes = array('class' => 'btn'); ?>

{{ HTML::link('users/create', 'Create a User', $create_link_attributes) }}

Step 15 – Deleting user records with Eloquent

Now that we can add users, we may want to do a bit of cleanup. Let's add a delete action to our users controller.

public function get_delete($user_id)
{
  $user = User::find($user_id);

  if(is_null($user))
  {
    return Redirect::to('users');
  }

  $user->delete();

  return Redirect::to('users');
}

Now, let's step through this.

public function get_delete($user_id)

This is the first time that we've declared a parameter in a controller action. In order to delete a user, we need to know which user to delete. Since we have used Route::controller('users') to have Laravel automatically handle the routing for our controller, it'll know that when we go to the URL http://myfirst.dev/users/delete/1 it should route to the delete action and pass additional URI segments as arguments to the method.

If you wanted to receive a second argument from a URL (for example, http://myfirst.dev/users/delete/happy), you would add a second parameter to your action as follows:

public function get_delete($user_id, $emotion)

Next, we need to verify that a user with the specified user ID actually exists.

$user = User::find($user_id);

This line tells Eloquent to find a user with an ID that matches the argument. If a user is found, the $user variable will be populated with an object that is an instance of our User class. If not, the $user variable will contain a null value.

if(is_null($user))
{
  return Redirect::to('users');
}

Here, we're checking if our user variable has the null value indicating that the requested user was not found. If so, we'll redirect back to the users index.

$user->delete();
return Redirect::to('users');

Next, we delete the user and redirect back to the users index.

Of course, our work here won't be finished until we update our application/views/users/index.php file to give us links to delete each user. Replace the list item code with the following:

<li>{{ $user->real_name }} - {{ $user->email }} - {{ HTML::link('users/delete/'.$user->id, 'Delete') }}</li>

Reload the users index page and you'll now see the delete link. Click on it and be horrified that we've irreparably removed data from the database. I hope it wasn't anything important!

Step 16 – Updating a user with Eloquent

So, we can add and delete users, but what if we have made a typo and want to fix it? Let's update our users controller with the methods that are necessary for us to display our update form and then to retrieve the data from it in order to update the user record:

public function get_update($user_id)
{
  $user = User::find($user_id);

  if(is_null($user))
  {
    return Redirect::to('users');
  }

  return View::make('users.update')->with('user', $user);
}

Here we have our new get_update() method. This method accepts a user ID as an argument. Much like we did with the get_delete() method, we need to load the user record from the database to verify that it exists. Then, we'll pass that user to the update form.

public function post_update($user_id)
{
  $user = User::find($user_id);

  if(is_null($user))
  {
    return Redirect::to('users');
  }

  $user->real_name = Input::get('real_name');
  $user->email = Input::get('email');

  if(Input::has('password'))
  {
    $user->password = Input::get('password');
  }

  $user->save();

  return Redirect::to('users');	
}

When a user submits our update form, they'll be routed to post_update().

You may have noticed a common theme with methods that receive a user ID as an argument. Whenever we are going to interact with a user model we need to know for sure that the database record exists and that the model is populated. We must always first load it and validate that it is not null.

Afterwards, we assign new values to the real_name and email attributes. We don't want to just change the user's password every time we submit a change. So, we'll first verify that the password field wasn't left blank. Laravel's Input class' has() method will return false, if an attribute either wasn't sent in the form post or if it's blank. If it's not blank, we can go ahead and update the attribute in the model.

We then save the changes to the user and redirect back to the users index page.

Step 17 – Creating the update form with the form helper

Now, we just need to create the update form and we'll have a full administrative system!

Go ahead and create the view at application/views/users/update.blade.php and fill it with this lovely form:

<h1>Update a User</h1>

{{ Form::open() }}

  Real Name: {{ Form::text('real_name', $user->real_name) }}<br />
  Email: {{ Form::text('email', $user->email) }}<br />
  Change Password: {{ Form::password('password') }}<br />

{{ Form::submit('Update User') }}

{{ Form::close() }}

This is almost exactly like the create form except that we have mixed things up a little. First of all, you'll notice that we're using Laravel's Form class helper methods. These helper methods, like the HTML class' helper methods, are not mandatory. However, they are recommended. They offer many of the same advantages as the HTML class' helper methods. The Form class' helper methods offer a unified interface for generating the resulting HTML tags. It's much easier to programmatically update HTML tag attributes by passing an array as an argument than to loop through and generate the HTML yourself.

Real Name: {{ Form::text('real_name', $user->real_name) }}

Text fields can be prepopulated by passing in a second argument. In this example, we're passing the real_name attribute from the user object that we passed from the controller. We then prepopulate the email field in the same way.

Change Password: {{ Form::password('password') }}

Notice that we're not prepopulating the password field. It doesn't make sense to do so as we're not storing a readable version of the password in the database. Not only that, to prevent a developer from making a mistake the Form::password() method does not have the functionality to prepopulate this field at all.

And with that we have a fully working update user form!