laravel-crud
Tutorials

Simple Laravel CRUD with Resource Controllers

Creating, reading, updating, and deleting resources is used in pretty much every application. Laravel helps make the process easy using resource controllers. Resource Controllers can make life much easier and takes advantage of some cool Laravel routing techniques. Today, we’ll go through the steps necessary to get a fully functioning CRUD application using resource controllers.

For this tutorial, we will go through the process of having an admin panel to create, read, update, and delete (CRUD) a resource. Let’s use nerds as our example. We will also make use of Eloquent ORM.

This tutorial will walk us through:

  • Setting up the database and models
  • Creating the resource controller and its routes
  • Creating the necessary views
  • Explaining each method in a resource controller

To get started, we will need the controller, the routes, and the view files.

Getting our Database Ready

Nerd Migration

(This sounds like a bunch of nerds moving south for the winter). We need to set up a quick database so we can do all of our CRUD functionality. In the command line in the root directory of our Laravel application, let’s create a migration.

php artisan migrate:make create_nerds_table --table=nerds --create

This will create our nerd migration in app/database/migrations. Open up that file and let’s add name, email, and nerd_level fields.

// app/database/migrations/####_##_##_######_create_nerds_table.php

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateNerdsTable extends Migration {

	/**
	 * Run the migrations.
	 *
	 * @return void
	 */
	public function up()
	{
		Schema::create('nerds', function(Blueprint $table)
		{
			$table->increments('id');

			$table->string('name', 255);
			$table->string('email', 255);
			$table->integer('nerd_level');

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

	/**
	 * Reverse the migrations.
	 *
	 * @return void
	 */
	public function down()
	{
		Schema::drop('nerds');
	}

}

Now from the command line again, let’s run this migration. Make sure your database settings are good in app/config/database.php and then run:

php artisan migrate

Our database now has a nerds table to house all of the nerds we CRUD (create, read, update, and delete). Read more about migrations at the Laravel docs.

Eloquent Model for the Nerds

Now that we have our database, let’s create a simple Eloquent model so that we can access the nerds in our database easily. You can read about Eloquent ORM and see how you can use it in your own applications.

In the app/models folder, let’s create a Nerd.php model.

// app/models/Nerd.php

<?php

	class Nerd extends Eloquent
	{

	}

That’s it! Eloquent can handle the rest. By default, this model will link to our nerds table and and we can access it later in our controllers.

Creating the Controller

From the official Laravel docs, on resource controllers, you can generate a resource controller using the artisan tool.

Let’s go ahead and do that. This is the easy part. From the command line in the root directory of your Laravel project, type:

php artisan controller:make NerdController

This will create our resource controller with all the methods we need.

// app/controllers/NerdController.php

<?php

class NerdController extends \BaseController {

	/**
	 * Display a listing of the resource.
	 *
	 * @return Response
	 */
	public function index()
	{
		//
	}

	/**
	 * Show the form for creating a new resource.
	 *
	 * @return Response
	 */
	public function create()
	{
		//
	}

	/**
	 * Store a newly created resource in storage.
	 *
	 * @return Response
	 */
	public function store()
	{
		//
	}

	/**
	 * Display the specified resource.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function show($id)
	{
		//
	}

	/**
	 * Show the form for editing the specified resource.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function edit($id)
	{
		//
	}

	/**
	 * Update the specified resource in storage.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function update($id)
	{
		//
	}

	/**
	 * Remove the specified resource from storage.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function destroy($id)
	{
		//
	}

}

Setting Up the Routes

Now that we have generated our controller, let’s make sure our application has the routes necessary to use it. This is the other easy part (they actually might all be easy parts). In your routes.php file, add this line:

// app/routes.php

<?php

	Route::resource('nerds', 'NerdController');

This will automatically assign many actions to that resource controller. Now if you, go to your browser and view your application at example.com/nerds, it will correspond to the proper method in your NerdController.

Actions Handled By the Controller

HTTP Verb Path (URL) Action (Method) Route Name
GET /nerds index nerds.index
GET /nerds/create create nerds.create
POST /nerds store nerds.store
GET /nerds/{id} show nerds.show
GET /nerds/{id}/edit edit nerds.edit
PUT/PATCH /nerds/{id} update nerds.update
DELETE /nerds/{id} destroy nerds.destroy
Tip: From the command line, you can run php artisan routes to see all the routes associated with your application.

The Views

Since only four of our routes are GET routes, we only need four views. In our app/views folder, let’s make those views now.

  • app
    • views
      • nerds
        • index.blade.php
        • create.blade.php
        • show.blade.php
        • edit.blade.php

Making It All Work Together

Now we have our migrations, database, and models, our controller and routes, and our views. Let’s make all these things work together to build our application. We are going to go through the methods created in the resource controller one by one and make it all work.

Showing All Resources nerds.index

Description URL Controller Function View File
Default page for showing all the nerds. GET example.com/nerds index() app/views/nerds/index.blade.php

Controller Function index()

In this function, we will get all the nerds and pass them to the view.

// app/controllers/NerdController.php

<?php

...

	/**
	 * Display a listing of the resource.
	 *
	 * @return Response
	 */
	public function index()
	{
		// get all the nerds
		$nerds = Nerd::all();

		// load the view and pass the nerds
		return View::make('nerds.index')
			->with('nerds', $nerds);
	}

...


The View app/views/nerds/index.blade.php

Now let’s create our view to loop over the nerds and display them in a table. We like using Twitter Bootstrap for our sites, so the table will use those classes.

<!-- app/views/nerds/index.blade.php -->

<!DOCTYPE html>
<html>
<head>
	<title>Look! I'm CRUDding</title>
	<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
</head>
<body>
<div class="container">

<nav class="navbar navbar-inverse">
	<div class="navbar-header">
		<a class="navbar-brand" href="{{ URL::to('nerds') }}">Nerd Alert</a>
	</div>
	<ul class="nav navbar-nav">
		<li><a href="{{ URL::to('nerds') }}">View All Nerds</a></li>
		<li><a href="{{ URL::to('nerds/create') }}">Create a Nerd</a>
	</ul>
</nav>

<h1>All the Nerds</h1>

<!-- will be used to show any messages -->
@if (Session::has('message'))
	<div class="alert alert-info">{{ Session::get('message') }}</div>
@endif

<table class="table table-striped table-bordered">
	<thead>
		<tr>
			<td>ID</td>
			<td>Name</td>
			<td>Email</td>
			<td>Nerd Level</td>
			<td>Actions</td>
		</tr>
	</thead>
	<tbody>
	@foreach($nerds as $key => $value)
		<tr>
			<td>{{ $value->id }}</td>
			<td>{{ $value->name }}</td>
			<td>{{ $value->email }}</td>
			<td>{{ $value->nerd_level }}</td>

			<!-- we will also add show, edit, and delete buttons -->
			<td>

				<!-- delete the nerd (uses the destroy method DESTROY /nerds/{id} -->
				<!-- we will add this later since its a little more complicated than the other two buttons -->

				<!-- show the nerd (uses the show method found at GET /nerds/{id} -->
				<a class="btn btn-small btn-success" href="{{ URL::to('nerds/' . $value->id) }}">Show this Nerd</a>

				<!-- edit this nerd (uses the edit method found at GET /nerds/{id}/edit -->
				<a class="btn btn-small btn-info" href="{{ URL::to('nerds/' . $value->id . '/edit') }}">Edit this Nerd</a>

			</td>
		</tr>
	@endforeach
	</tbody>
</table>

</div>
</body>
</html>

We can now show all of our nerds on a page. There won’t be any that show up currently since we haven’t created any or seeded our database with nerds. Let’s move on to the form to create a nerd.

index-blade

Creating a New Resource nerds.create

Description URL Controller Function View File
Show the form to create a new nerd. GET example.com/nerds/create create() app/views/nerds/create.blade.php

Controller Function create()

In this function, we will show the form for creating a new nerd. This form will be processed by the store() method.

// app/controllers/NerdController.php

<?php

...

	/**
	 * Show the form for creating a new resource.
	 *
	 * @return Response
	 */
	public function create()
	{
		// load the create form (app/views/nerds/create.blade.php)
		return View::make('nerds.create');
	}

...

The View app/views/nerds/create.blade.php

<!-- app/views/nerds/create.blade.php -->

<!DOCTYPE html>
<html>
<head>
	<title>Look! I'm CRUDding</title>
	<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
</head>
<body>
<div class="container">

<nav class="navbar navbar-inverse">
	<div class="navbar-header">
		<a class="navbar-brand" href="{{ URL::to('nerds') }}">Nerd Alert</a>
	</div>
	<ul class="nav navbar-nav">
		<li><a href="{{ URL::to('nerds') }}">View All Nerds</a></li>
		<li><a href="{{ URL::to('nerds/create') }}">Create a Nerd</a>
	</ul>
</nav>

<h1>Create a Nerd</h1>

<!-- if there are creation errors, they will show here -->
{{ HTML::ul($errors->all()) }}

{{ Form::open(array('url' => 'nerds')) }}

	<div class="form-group">
		{{ Form::label('name', 'Name') }}
		{{ Form::text('name', Input::old('name'), array('class' => 'form-control')) }}
	</div>

	<div class="form-group">
		{{ Form::label('email', 'Email') }}
		{{ Form::email('email', Input::old('email'), array('class' => 'form-control')) }}
	</div>

	<div class="form-group">
		{{ Form::label('nerd_level', 'Nerd Level') }}
		{{ Form::select('nerd_level', array('0' => 'Select a Level', '1' => 'Sees Sunlight', '2' => 'Foosball Fanatic', '3' => 'Basement Dweller'), Input::old('nerd_level'), array('class' => 'form-control')) }}
	</div>

	{{ Form::submit('Create the Nerd!', array('class' => 'btn btn-primary')) }}

{{ Form::close() }}

</div>
</body>
</html>

We will add the errors section above to show validation errors when we try to store() the resource.

Tip: When using {{ Form::open() }}, Laravel will automatically create a hidden input field with a token to protect from cross-site request forgeries. Read more at the Laravel docs.

We now have the form, but we need to have it do something when it the submit button gets pressed. We set this form’s action to be a POST to example.com/nerds. The resource controller will handle this and automatically route the request to the store() method. Let’s handle that now.

Storing a Resource store()

Description URL Controller Function View File
Process the create form submit and save the nerd to the database. POST example.com/nerds store() NONE

As you can see from the form action and the URL, you don’t have to pass anything extra into the URL to store a nerd. Since this form is sent using the POST method, the form inputs will be the data used to store the resource.

To process the form, we’ll want to validate the inputs, send back error messages if they exist, authenticate against the database, and store the resource if all is good. Let’s dive in.

Controller Function store()

// app/controllers/NerdController.php

<?php

...

	/**
	 * Store a newly created resource in storage.
	 *
	 * @return Response
	 */
	public function store()
	{
		// validate
		// read more on validation at http://laravel.com/docs/validation
		$rules = array(
			'name'       => 'required',
			'email'      => 'required|email',
			'nerd_level' => 'required|numeric'
		);
		$validator = Validator::make(Input::all(), $rules);

		// process the login
		if ($validator->fails()) {
			return Redirect::to('nerds/create')
				->withErrors($validator)
				->withInput(Input::except('password'));
		} else {
			// store
			$nerd = new Nerd;
			$nerd->name       = Input::get('name');
			$nerd->email      = Input::get('email');
			$nerd->nerd_level = Input::get('nerd_level');
			$nerd->save();

			// redirect
			Session::flash('message', 'Successfully created nerd!');
			return Redirect::to('nerds');
		}
	}

...

If there are errors processing the form, we will redirect them back to the create form with those errors. We will add them in so the user can understand what went wrong. They will show up in the errors section we setup earlier.

Now you should be able to create a nerd and have them show up on the main page! Navigate to example.com/nerds and there they are. All that’s left is showing a single nerd, updating, and deleting.

created

Showing a Resource show()

Description URL Controller Function View File
Show one of the nerds. GET example.com/nerds/{id} show() app/views/nerds/show.blade.php

Controller Function show()

// app/controllers/NerdController.php

<?php

...

	/**
	 * Display the specified resource.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function show($id)
	{
		// get the nerd
		$nerd = Nerd::find($id);

		// show the view and pass the nerd to it
		return View::make('nerds.show')
			->with('nerd', $nerd);
	}

...

The View app/views/nerds/show.blade.php

<!-- app/views/nerds/show.blade.php -->

<!DOCTYPE html>
<html>
<head>
	<title>Look! I'm CRUDding</title>
	<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
</head>
<body>
<div class="container">

<nav class="navbar navbar-inverse">
	<div class="navbar-header">
		<a class="navbar-brand" href="{{ URL::to('nerds') }}">Nerd Alert</a>
	</div>
	<ul class="nav navbar-nav">
		<li><a href="{{ URL::to('nerds') }}">View All Nerds</a></li>
		<li><a href="{{ URL::to('nerds/create') }}">Create a Nerd</a>
	</ul>
</nav>

<h1>Showing {{ $nerd->name }}</h1>

	<div class="jumbotron text-center">
		<h2>{{ $nerd->name }}</h2>
		<p>
			<strong>Email:</strong> {{ $nerd->email }}<br>
			<strong>Level:</strong> {{ $nerd->nerd_level }}
		</p>
	</div>

</div>
</body>
</html>

show

Editing a Resource edit()

Description URL Controller Function View File
Pull a nerd from the database and allow editing. GET example.com/nerds/{id}/edit edit() app/views/nerds/edit.blade.php

To edit a nerd, we need to pull them from the database, show the creation form, but populate it with the selected nerd’s info. To make life easier, we will use form model binding. This allows us to pull info from a model and bind it to the input fields in a form. Just makes it easier to populate our edit form and you can imagine that when these forms start getting rather large this will make life much easier.

Controller Function edit()

// app/controllers/NerdController.php

<?php

...

	/**
	 * Show the form for editing the specified resource.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function edit($id)
	{
		// get the nerd
		$nerd = Nerd::find($id);

		// show the edit form and pass the nerd
		return View::make('nerds.edit')
			->with('nerd', $nerd);
	}

...

The View app/views/nerds/edit.blade.php

<!-- app/views/nerds/edit.blade.php -->

<!DOCTYPE html>
<html>
<head>
	<title>Look! I'm CRUDding</title>
	<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
</head>
<body>
<div class="container">

<nav class="navbar navbar-inverse">
	<div class="navbar-header">
		<a class="navbar-brand" href="{{ URL::to('nerds') }}">Nerd Alert</a>
	</div>
	<ul class="nav navbar-nav">
		<li><a href="{{ URL::to('nerds') }}">View All Nerds</a></li>
		<li><a href="{{ URL::to('nerds/create') }}">Create a Nerd</a>
	</ul>
</nav>

<h1>Edit {{ $nerd->name }}</h1>

<!-- if there are creation errors, they will show here -->
{{ HTML::ul($errors->all()) }}

{{ Form::model($nerd, array('route' => array('nerds.update', $nerd->id), 'method' => 'PUT')) }}

	<div class="form-group">
		{{ Form::label('name', 'Name') }}
		{{ Form::text('name', null, array('class' => 'form-control')) }}
	</div>

	<div class="form-group">
		{{ Form::label('email', 'Email') }}
		{{ Form::email('email', null, array('class' => 'form-control')) }}
	</div>

	<div class="form-group">
		{{ Form::label('nerd_level', 'Nerd Level') }}
		{{ Form::select('nerd_level', array('0' => 'Select a Level', '1' => 'Sees Sunlight', '2' => 'Foosball Fanatic', '3' => 'Basement Dweller'), null, array('class' => 'form-control')) }}
	</div>

	{{ Form::submit('Edit the Nerd!', array('class' => 'btn btn-primary')) }}

{{ Form::close() }}

</div>
</body>
</html>

Note that we have to pass a method of PUT so that Laravel knows how to route to the controller correctly.

Updating a Resource update()

Description URL Controller Function View File
Process the create form submit and save the nerd to the database. PUT example.com/nerds update() NONE

This controller method will process the edit form. It is very similar to store(). We will validate, update, and redirect.

Controller Function update()

// app/controllers/NerdController.php

<?php

...

	/**
	 * Update the specified resource in storage.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function update($id)
	{
		// validate
		// read more on validation at http://laravel.com/docs/validation
		$rules = array(
			'name'       => 'required',
			'email'      => 'required|email',
			'nerd_level' => 'required|numeric'
		);
		$validator = Validator::make(Input::all(), $rules);

		// process the login
		if ($validator->fails()) {
			return Redirect::to('nerds/' . $id . '/edit')
				->withErrors($validator)
				->withInput(Input::except('password'));
		} else {
			// store
			$nerd = Nerd::find($id);
			$nerd->name       = Input::get('name');
			$nerd->email      = Input::get('email');
			$nerd->nerd_level = Input::get('nerd_level');
			$nerd->save();

			// redirect
			Session::flash('message', 'Successfully updated nerd!');
			return Redirect::to('nerds');
		}
	}

...

Deleting a Resource destroy()

Description URL Controller Function View File
Process the create form submit and save the nerd to the database. DELETE example.com/nerds/{id} destroy() NONE

The workflow for this is that a user would go to view all the nerds, see a delete button, click it to delete. Since we never created a delete button in our app/views/nerds/index.blade.php, we will create that now. We will also add a notification section to show a success message.

We have to send the request to our application using the DELETE HTTP verb, so we will create a form to do that since a button won’t do.

Alert: The DELETE HTTP verb is used when accessing the nerds.destroy route. Since you can’t just create a button or form with the method DELETE, we will have to spoof it by creating a hidden input field in our delete form.

The View app/views/nerds/index.blade.php

<!-- app/views/nerds/index.blade.php -->

...

	@foreach($nerds as $key => $value)
		<tr>
			<td>{{ $value->id }}</td>
			<td>{{ $value->name }}</td>
			<td>{{ $value->email }}</td>
			<td>{{ $value->nerd_level }}</td>

			<!-- we will also add show, edit, and delete buttons -->
			<td>

				<!-- delete the nerd (uses the destroy method DESTROY /nerds/{id} -->
				<!-- we will add this later since its a little more complicated than the other two buttons -->
				{{ Form::open(array('url' => 'nerds/' . $value->id, 'class' => 'pull-right')) }}
					{{ Form::hidden('_method', 'DELETE') }}
					{{ Form::submit('Delete this Nerd', array('class' => 'btn btn-warning')) }}
				{{ Form::close() }}

				<!-- show the nerd (uses the show method found at GET /nerds/{id} -->
				<a class="btn btn-small btn-success" href="{{ URL::to('nerds/' . $value->id) }}">Show this Nerd</a>

				<!-- edit this nerd (uses the edit method found at GET /nerds/{id}/edit -->
				<a class="btn btn-small btn-info" href="{{ URL::to('nerds/' . $value->id . '/edit') }}">Edit this Nerd</a>

			</td>
		</tr>
	@endforeach

...

Now when we click that form submit button, Laravel will use the nerds.destroy route and we can process that in our controller.

Controller Function destroy()

// app/controllers/NerdController.php

<?php

...

	/**
	 * Remove the specified resource from storage.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function destroy($id)
	{
		// delete
		$nerd = Nerd::find($id);
		$nerd->delete();

		// redirect
		Session::flash('message', 'Successfully deleted the nerd!');
		return Redirect::to('nerds');
	}

...

Conclusion

That’s everything! Hopefully we covered enough so that you can understand how resource controllers can be used in all sorts of scenarios. Just create the controller, create the single line in the routes file, and you have the foundation for doing CRUD.

As always, let us know if you have any questions or comments. We’ll be expanding more on Laravel in the coming articles so if there’s anything specific, throw it in the comments or email us.

Chris Sevilleja

Design, development, and anything in between that I find interesting.

View My Articles

Stay Connected With Us
hover these for magic

Get valuable tips, articles, and resources straight to your inbox. Every Tuesday.

  • Tanner Hearne

    Hey Chris,

    Great tutorial! You can also do all of this using a single line with Artisan:

    artisan generate:resource nerds –fields”name:string, email:string, nerd_level:integer”

    Or, if you want the forms generated for you as well, just use “scaffold” instead of “resource” (“scaffold” does everything “resource” does plus more, like adding the forms to create, edit, delete, etc.)

    artisan generate:scaffold nerds –fields”name:string, email:string, nerd_level:integer”

    Check it out:
    https://packagist.org/packages/way/generators
    https://github.com/JeffreyWay/Laravel-4-Generators

    Thanks,
    Tanner

    • http://scotch.io/ Chris Sevilleja

      Hey Tanner,

      That is awesome. I knew about the generator but never actually played with it. After seeing that, I’m definitely going to use it.

      Thanks and glad you enjoyed the article!

    • http://www.localpricelookup.com Paul Reichow

      When I follow those commands on my Ubuntu distro with Lamp stack/Laravel4, I get “artisan: command not found”.

      I first tried running these from the project root directory (www), and then I ran it in a number of other folders just to make sure I wasn’t running it from the wrong location.

      Any idea how to solve this? I’m pretty sure I have everything installed correctly.

      • Tanner Hearne

        Hey Paul,

        Did you install the Way Generators package and paste in the necessary Service Provider in “app/config/app.php”?

        Tanner

        • http://www.localpricelookup.com Paul Reichow

          I installed the package and it worked great! The documentation was clear, and the video made it very simple to install. Nice work!

          Just a heads-up: I think there’s an equals sign missing in your two commands. I got this to work:

          php artisan generate:resource nerds –fields=”name:string, email:string, nerd_level:integer”

          artisan generate:scaffold nerds –fields=”name:string, email:string, nerd_level:integer”

          Anyways, what a great time saving tool.

          • Tanner Hearne

            Whoops, you are right, there should be an equals sign! Good catch!

    • JR

      Hey Chris and Tanner,
      What would I have to change in both your methods to be able to run this on IIS with ms sql server 2008 ?
      I have a connection established to the DB using a basic index controller, so I know it works there, but Im not sure if I will have any problems when running both of your examples.

      What do you think ?

      Thanks!

      • http://www.tannerhearne.com Tanner Hearne

        Hey JR,

        What I am referring to you should be able to run in your local environment to generate the required database migrations, views, controllers, etc. So I think your question is related to just Laravel database migrations.

        Are you asking how to run Laravel database migrations on IIS with MS SQL Server 2008?

        Thanks,
        Tanner

        • JR

          Hey Tanner,

          I guess thats what I am asking. I just wanted a heads up before I run the commands you suggested. I am not sure how to auto generate the necessary tables from your example, in a SQL server database instead of mysql which is probably the default assumption.

          I am fairly new to Laravel so I am not sure how these “migrations” work in Laravel.

          In another environment, whenever i ran the migrate commands, they would generate to my mysql database. But when I tried a migrate command on this IIS 7 / sql server 2008 system, it gave me an error.

          Any tips for this ? Or do I need to set everything up manually ?

          Thanks,

          JR

          • http://www.tannerhearne.com Tanner Hearne

            I would just Google SQL Server 2008 PHP PDO extension. You don’t need to do the migrations manually once you install the PHP PDO extension. After that isinstalled you can just run “php artisan migrate” to have artisan automatically build your database using those migration files you generated.

            Tanner

          • JR

            Thanks for your time Tanner. Turns out i missed something pretty basic and misspelled “sqlsrv” when setting the default db in the database config file. *stares at feet*

        • JR

          The way addon works fine until it tries to migrate tables to the database. I get a “could not find driver” PDOexception.
          My database.php file has all the correct credentials. Any ideas?

          • http://www.tannerhearne.com Tanner Hearne

            The exception that you are seeing about PDO relates to your PHP install. You will need to upgrade your PHP and/or install the PDO extension/driver in order to do Laravel database migrations.

  • Aldren Terante

    Superb Awesome Tutorial! BTW Chris, are you a Filipino?

    • http://scotch.io/ Chris Sevilleja

      Thanks! Yes I am.

  • Dani

    Hi! Great tutorial on a great website! Keep up the good work!

    I’ve found a small syntax error on this page, so I want share it:
    In app/views/nerds/edit.blade.php is missing a right parenthesis from the line
    {{ Form::model($nerd, array(‘route’ => array(‘nerds.update’, $nerd->id), ‘method’ => ‘PUT’) }}

    It should be:
    {{ Form::model($nerd, array(‘route’ => array(‘nerds.update’, $nerd->id), ‘method’ => ‘PUT’)) }}

    • http://scotch.io/ Chris Sevilleja

      Good find. Fixed. Thanks!

  • sunnyfrimley

    Thank you kindly. I spent ages this morning trying to get DELETE working properly, and your tutorial was the only one on the web I could find that actually had a working method.

    • http://scotch.io/ Chris Sevilleja

      Awesome. I spent a lot of time on this too. Even though the Laravel docs say something about it, I couldn’t find any actual code on how to implement. Glad it helped.

      • sunnyfrimley

        In the end I managed to shorten it by a line:

        {{ Form::open(['method'=>'DELETE', 'route'=>['groups.destroy', $group->id]]) }}

        {{ Form::submit(‘Delete’) }}

        {{ Form::close() }}

        Obviously, I was using a groups table instead of a nerds table, but this generated a workable link without having to add the hidden field.

        • http://scotch.io/ Chris Sevilleja

          That’s great. Cleaner is always better. Thanks for the info.

  • Pingback: » Laravel RESTful快速部署指南(二) WEB第二站

  • Fernando

    This is the best example I found on the web CRUD. Thank you very much.

    • http://scotch.io/ Chris Sevilleja

      You’re welcome! Thanks for reading!

  • Haezal

    Awesome tutorial.. Good for me as beginner in Laravel 4.

    • http://scotch.io/ Chris Sevilleja

      Sounds good. Good luck on your Laravel learning journey.

  • haider

    nice job, you are the best :-)

  • haider

    thnx for the toturial, i have one question how can i protect the route and add a filter to it, like this one hier

    Route::resource(‘nerds’, ‘NerdController’);

    what i want is if i type somthing in the browser nothing will be showed exept if am logged in
    i hope you will help me chris with this one.

    • http://scotch.io/ Chris Sevilleja

      Hey haider, I am not entirely sure if you can apply it directly to the route itself. You could apply a Route::group(array(‘before’ => ‘filter_name’), around that array.

      What I would suggest for a resource route though is to use controller filters. You define this in the __construct() of your resource controller. You can also only apply the filter for specific methods inside that resource controller. Let me know if you want a further explanation of this.

      http://laravel.com/docs/controllers#controller-filters

      • haider

        thnx for your reply, i did it hust like this

        in the filters.php

        Route::filter(‘auth’, function()
        {
        if (Auth::check())
        {
        return Route::resource(‘users’, ‘UserController’);
        }
        else
        {
        return Redirect::to(‘login’);
        }
        });

        and in the routes.php

        Route::group(['before' => 'auth'], function()
        {
        Route::resource(‘users’, ‘UserController’);
        });

        and it worked

  • Erich Casagrande

    Awesome!!! Great tutorial!!
    Best example I found on the web.

    Thank you very much.

    • http://scotch.io/ Chris Sevilleja

      Welcome! Thanks for reading!

  • Erik

    So I stumbled onto this website just this week. … I am now kicking myself for not having simply started my Laravel journey here.

    Seriously best Laravel tutorials out there! … (admittedly I’ve been through my fair share).

    I would like to see the L4 docs link here for examples/further reading.

    Thanks again Chris… I do believe you have saved me yet another several hours of perusing less than worthy tutorials ;)

    • http://scotch.io/ Chris Sevilleja

      Great to hear that this stuff helps. I try to link to other resources as often as I can, but I’ll definitely try to add more in. Thanks for reading and the encouragement.

      • Erik

        What I meant was, I would like to see the L4 docs contain links to these tuts ;)

        • http://scotch.io/ Chris Sevilleja

          Oooh. Yea that would be amazing! We’re still trying to get our site off the ground since we started back in the summer and something like that would be a giant boost.

  • Erik

    @sevilayha:disqus as for a tut I would love to see …. L4 + AngularJS.

    I have yet to spend much time in AngularJS (although I have spent much time dreaming about using it), so I don’t know how great of a fit they would be.

    Definitely something I would be interested in seeing put together…

    • http://scotch.io/ Chris Sevilleja

      Funny you should say that. I am working on an Animating Angular Apps article currently and then next week I was planning on doing a Laravel + Angular article similar to our Node + Angular ones.

  • Dhea Raniasti

    Thank you very much Chris.. :)

  • Thommy

    Great article, thank you alot. What I’m still lokking for is a good way to provide an API Key, so that, for example, only nerds are able to create their own kind. Sessions are not popular among REST interfaces. Do you ave a solution for that?

  • Pingback: Top 10: Aprendiendo Laravel | Silvercorp

  • AlfieBesin

    @sevilayha:disqus Woah! This post was a time saver! I went through a lot of Google searches but this one saves my day. Thanks!

    What syntax highlighter plugin did you use in your blog, it looks amazing. ;)

  • Gilles Vanpeteghem

    I always get this message: Unable to generate a URL for the named route “users.update” as such route does not exist.

    I’m looking at it all day, can’t find the problem. Can someone please help?

    I have this in my routes file: Route::put(‘/users/update’, ‘UserController@update’);

    • http://scotch.io/ Chris Sevilleja

      In general, you’re not really supposed to generate a url to user.update since you’re supposed to access that route from a form using the PUT method.

      That said, are you using {{ URL::route(‘user.update’) }}? Try using {{ URL::to(‘user.update’) }}.

      The difference here is that one is explicitly named and one is just a route to it. I’m not sure if either of those will work since you’re supposed to use a form with the method PUT.
      Also, if you’d like to see all your routes (super helpful), go into your command line at the root of your Laravel project and use php artisan routes. You can see all the routes and their names.

      • Gilles Vanpeteghem

        I have this now: {{ Form::model($user, array(‘route’ => array(URL::route(‘users.update’), $user->user_id), ‘method’ => ‘PUT’)) }}
        I got the same message: Unable to generate a URL for the named route “users.update” as such route does not exist.

        • http://scotch.io/ Chris Sevilleja

          Try removing the URL::route in there. I believe Laravel will automatically create the right route.

          From the tutorial:

          {{ Form::model($nerd, array(‘route’ => array(‘nerds.update’, $nerd->id), ‘method’ => ‘PUT’)) }}

          • Gilles Vanpeteghem

            It probably doesn’t work because I have a one to one relationship with another table

          • Sandra Gindroz

            You must add ‘ ‘ with $user->user_id

        • Gilles Vanpeteghem

          With this: {{ Form::model($user, array(URL::to(‘users.update’), ‘method’ => ‘PUT’)) }} i don’t get an error, but it doesn’t want to update

  • Pingback: Simple CRUD (Create, Read, Update, and Delete a resource) with Laravel | donvercety's blog

  • irham syah

    it’s great example about CRUD, its very clear…, by the way, would u explain to me how to render nerd’s data to modal form..thx before :)

  • Pingback: Laravel Form Model Binding ♥ Scotch

  • Moises

    Awesome Chris, you made my day :-)

    • http://scotch.io/ Chris Sevilleja

      Hey Moises. Glad to hear it and thanks for reading!

  • Kris

    Great Tutorial! Like many others said the best I’ve found so far. Let’s say I wanted to create another view – not replace existing one index.blade.php but give possibility to view same table in full screen mode, so same data (all nerds) but different html. What would be the approach?
    I’ve tried to create new function in NerdController like this:

    public function index()
    {
    $nerds = Nerd::all();

    return View::make(‘nerds.index’)
    ->with(‘nerds’, $nerds);
    }

    public function table()
    {
    $nerds = Nerd::all();

    return View::make(‘nerds.table’)
    ->with(‘nerds’, $nerds);
    }
    Creted new layout in table.blade.php but for whatever reason it throws an error referencing show.blade.php:

    ErrorException
    Trying to get property of non-object (View:
    /home/asdrubal/Projects/matrix/app/views/nerds/show.blade.php) – line in question:

    Showing name; ?>

    Any idea what I’m doing wrong?

    • http://scotch.io/ Chris Sevilleja

      Having a Laravel resource controller, you are limited to the functions already created in there. To add another function like your public function table, you will have to define that in your routes BEFORE you define your resource controller.

      // routes.php
      Route::get(‘nerds/table’, array(‘uses’ => ‘NerdController@table));
      Route::resource(‘nerds’, ‘NerdController’);

      Then displaying your information in your view, use the Blade double brackets. {{ }}. Let me know if that helps.

      • Kris

        Yes, that was it! Thanks a lot.

  • Stephan Jusypiw

    Wow. Without a doubt the BEST introduction to Laravel 4 tutorial on the net. four.laravel.com should link to your great work. Thank-you so much!

    • http://scotch.io/ Chris Sevilleja

      Thanks for the kind words. That’d be insane if we got linked from there!

      • leonardo odriozola

        Definetly agree wiht Mr Stephan, your tutorial is much more clearer than any of the documentation, so i second that motion for link. Thanks again

  • Pingback: How to display the view generated by the controller in Laravel? | Developers Questions - Msn4Free.com

  • Mario

    Hey, very nice tutorial. Thanks!

    I have one problem though:
    Is there any way to align the delete button with the other two? When I remove the “pull-right” class name the button is underneath the other two and I don’t want it on the right side. Is there a quick solution for this problem? Would be awesome if you could help me!

    • http://scotch.io/ Chris Sevilleja

      I’ve actually tried to come up with a good solution for that myself. Since the DELETE button has to be in a form (to spoof the DELETE method), it will be on its own line.

      Maybe try doing form-inline and putting the edit buttons inside the form? That way all the buttons would sit next to each other?

      • Mario

        This works great! Thanks for the fast reply!

        Heres what I did:

        {{ Form::open(array(‘url’ => ‘networks/’ . $value->id, ‘class’ => ‘form-inline’)) }}

        id) }}”>Show

        id . ‘/edit’) }}”>Edit

        {{ Form::hidden(‘_method’, ‘DELETE’) }}

        {{ Form::submit(‘Delete’, array(‘class’ => ‘btn btn-small btn-warning’)) }}

        {{ Form::close() }}

      • Mario

        Thank you for the fast reply! Works great now!
        I Just put the two links (Edit, Show) inside the form and used ‘form-inline’ on the Form::open thing as class.

      • guest

        That’s awesome, another stellar tutorial form you Chris. Question for you Chris, how would you go about adding a delete confirmation when selecting delete?

        • http://scotch.io/ Chris Sevilleja

          Hello sorry for the late response. The way I would see to do it is to have the first delete not be the actual delete form. It would just be a link that you could show a confirm dialog with.

          Inside that form dialog, you would put the actual delete form. You could have the first delete button use this: http://getbootstrap.com/javascript/#modals

          Then inside that modal, show the real delete form.

  • Maul

    Hey Chris,

    it’s a great tutorial,

    have a question, i’m using id_nerds as primary key, when editing the page, it’s return error, is this problem is related with declaring primary key such as declaring table in model?
    public static $key = ‘id_nerds’; maybe?

  • Pingback: Laravel4 tutoriály a snippety | IT.zena

  • Guest

    Howdy Chris,

    How would you implement a delete confirmation to delete form?

    • http://scotch.io/ Chris Sevilleja

      Hello, I hope I answered your question well in the other comment in this thread. Best way is to handle showing the delete button on the frontend of your application.

      First delete button to show a confirmation dialog. Then the real delete button/form inside of that dialog.

      • Guest

        Cheers Chris, will give it a shot–thanks for the suggestion!

  • Naimish Sakhpara

    That was a great Tutorial … I am just starting learning Laravel and post is encouraging… I wanted to know the methods to DEBUG … as similar to CakePHP’s debug() … and other debugging methods…Official documents are little difficult to catch …

  • Laurie Knight

    Great tutorial sir! I’d love to see a second tutorial on these lines about related tables. So nerds have none-many of a sub-nerd-thing?

  • Keith

    Just working through the tut. Thanks for this. First script is a slight error

    Schema::table(‘nerds’, function(Blueprint $table)

    should be

    Schema::create(‘nerds’, function(Blueprint $table)

    Took me best part of the day to work that one through. Good learning experience though. Well done.

    • http://scotch.io/ Chris Sevilleja

      That’s weird. Doing a double check on that, it looks like it already says Schema::create. Just want to make sure this is all sorted for the next people that go through this article.

      Thanks for reading and the help.

      • madhavi

        Looks like it is sorted

    • Kiee

      Thank you kind sir, I was lost with this one!

  • gulamgaus

    Hi Chris
    Simple and great article for CRUD. As a newbie question on Laravel4, Is it possible for you to add or come up with additional feature to this CRUD tutorials such as “Search” and “Date computation”. For any real-time application these 2 feature is a must-have and cannot be neglected. As a newbie I had struggled hard to codify the search function initially. I am sure this would help many readers like me.
    Thanks a lot.
    Great Job!

    • http://scotch.io/ Chris Sevilleja

      I’ll definitely get to some more CRUD stuff. I especially want to get into Eloquent and do complex relationships with it.

      Could you clarify what you mean by date computation? Do you just mean display “3 days old” and stuff like that?

      Any other tutorials you would like to see?

      • gulamgaus

        Date computation.. i meant to say .for eg. lets say we have 2 date columns such as start date and end date (in the same CRUD table we have) and we need to know the difference between ( either in terms of no.of days or hours ,seconds etc) the start date and end date. How do we do that as part of this CRUD tutorials..Usually such date functions helps a lot in the real application.
        One more important must have feature of any CRUD is ofcourse as you said the relationshop. Simple eg could be Customer, Order and Order Detail (pivot-table) using the most effective one-to-many relationship. If we could have a CRUD of maintaining multiple customer orders. Definitely there are many articles written in bits and pieces everywhere but if we have all the features in one place then i guess it would be fantastic!
        Thanks for your reply.

        • gulamgaus

          One more thing I forgot to mention..regard to 2 date column that I mentioned. Based on the 2 given date, we should be able to list only those nerds rows whose start date is >= (given date) and end date <= (given date)..Such queries is very useful to learn as part of our tutorials.

  • Jay

    Great article, really helped clear some things up for me and simplify a site I’m working on. Just one thing I would mention to others. For testing, hard coding a URL in your template is ok. But what if you had to change /nerd to /geek? Just be aware of that.

  • Matthias

    Hey Chris! Awesome Tutorial! Thank you so much :)

  • Pingback: Create a Laravel and Angular Single Page Comment Application ♥ Scotch

  • Alec

    This is a really helpful tutorial and a life saver for sure!

    I have question regarding the delete method, instead of using the spoof form could you create an anchor link with a data attribute, for example data-userID=’1′ and then use ajax to send the request? Just a thought, if ajax can use the delete method?

    Anyway, thanks again!

  • leonardo odriozola

    Wonderfull tutorial, very clear manner of explaining things, use it as a reference all the time.
    Gracias

  • Pingback: A Guide to Using Eloquent ORM in Laravel ♥ Scotch

  • Diegus

    Hi Chris,

    Thank you for your tutorial

    I have a problem with routes that have {id} like update, edit or show, the result are always the same NotFoundHttpException, i spent to days but i can’t find the problem, i change Route::resource for Route::get/post/delete… meanwhile, you have any idea?

    I upload a capture of my routes

    Thank you

    • http://scotch.io/ Chris Sevilleja

      That is weird. Does your campanas/{id} route work ok for @show? Have you tried changing out {campanas} for {id}?

  • Vidya VidyaG

    Great tutorial!

    it helped me understand the Laravel MVC concept as i’m a newbie in Laravel.
    But i could not understand the database connection. Please guide me. If i not wish to connect to the same database but to another database and manipulate this small application, how can i? Please help. Thank you.

  • Alfin Abdullah

    Amazing tutorial for the newbie like me :D
    can you post a tutorial about searching data using laravel?

    • http://scotch.io/ Chris Sevilleja

      Hey Alfin, that’s always been on my list and I will try to get around to it this month. Thanks for reading.

  • http://77-webdev.com/ HaDi MaKawi

    Hey Chris,

    First i would like to thank you about this tutorial really it was needed, anyways what about if user wants to edit his/her password and the password is Hashed or MD5 for example (:

  • Mike Ritter

    Chris, really helpful and thorough TUT. One request… isn’t there a more “DRY” way by using a single form to handle all the calls?

    • http://scotch.io/ Chris Sevilleja

      There is definitely a DRY way to do this. I think the way to accomplish that is without using a resource controller and defining the routes yourself. Then you would route the create and edit forms to the same view with a parameter (lets say type). Then you could change out the Form::open which is really the main difference between the create and edit form.

      In your routes:

      // instead of
      Route::resource('nerds', 'NerdController');

      // use multiple defined routes

      Route::get('nerds/create', function() {

      return View::make('nerd-build-form')->with('type', 'create');

      });

      Route::get('nerds/edit', function($id) {

      return View::make('nerd-build-form')->with('type', 'edit')->with('nerd', Nerd::find($id));

      });

      I think this would be a good way of doing it. Let me know if you find other ways. Thanks for commenting on those other posts by the way and being helpful to the other users.

  • Retrograde

    Great Tutorial. It has been very helpful, thank you.

    I am running into a problem on the edit(). Upon hitting submit a blank screen appears and the data isn’t saved. The url for the blank screen is /nerds/1/edit. Any idea what is causing this?

    • Mike Ritter

      i had this problem too. don’t forget the `save` command at the end of your inputs.

      $nerd = Nerd::find($id);
      $nerd->name = Input::get(‘name’);
      $nerd->email = Input::get(‘email’);
      $nerd->nerd_level = Input::get(‘nerd_level’);
      $nerd->save();

      • Retrograde

        Thanks! That was the error.

  • Peter Mulli

    Excellent tutorial easy to follow and understand please keep it up

  • Narwen Tamang

    Your tutorials are amazing for new beginners like me. Thank You very much for your effort. I look forward to more from you on laravel 4.

  • Narwen Tamang

    Chris what is the purpose of mode? Is it just to link the controller with the migration.

    • http://scotch.io/ Chris Sevilleja

      Mode? Did you mean model? The models are Eloquent’s way of defining an object that is mapped to the table in your database. That way you can call it like Nerd::all();

  • kanav

    Yesterday i followed this tutorial and was able understand it. Everything was working fine.

    Today i tried to revise it by creating a new dummy application. So i created a form(using view) and returned it via a controller(testController) using index method. i created another method (dologin) in the controller which would process the form. In the form url parameter i gave the address of dologin method.

    This is the route:
    Route::resource(‘test’, ‘testController’);

    This is the controller
    ‘test/loginform’)) }}
    {{ Form::text(‘username’, null, array(‘placeholder’=>’Username’)) }}
    {{ Form::password(‘password’, array(‘placeholder’=>’Password’)) }}

    {{ Form::submit(‘Login’) }}
    {{ Form::close() }}

    After submitting form, it should echo “working” in the browser. But after submitting the form, page is blank. The url changes though from

    http://localhost/laravel/public/index.php/test/

    to

    http://localhost/laravel/public/index.php/test/loginform

    • http://scotch.io/ Chris Sevilleja

      Since you are using a resource controller, there are already predefined routes for that (index, show, edit, create, update, destroy). You will probably want to use Route::controller instead of Route::resource since you have a custom function name (doLogin()).

      Here’s an article on doing login: http://scotch.io/tutorials/simple-and-easy-laravel-login-authentication

  • Lavinia Manzanarez

    Great! You really make this seen so easy! Thank you so much and great work!!

  • ytsejamburak

    What about the relationships..how can I get belongsto-hasmany relationships? is there an example of it ?

  • Tom

    One of the best tutorials for beginners. Really nice guys, keep the good work!

  • bigmac

    How do I take care of missing Methods? I added this in my resource controller ,
    public function missingMethod($parameters = array())
    {
    }

    but still getting blank page when I go to a missing method? help

  • Gayan Ramya Kumara

    I tried to add this function inside the NearController ..but it’s not working

    public function search($id)
    {

    }

    i need to add search function to the NearController.Can you please tell me how can i add this.

  • Pingback: Co hledám

  • Pingback: Best Laravel Tutorial for Beginners : Fresh Web Dev

  • Maria G.

    Best introduction tutorial I’ve seen so far. Thank you.

  • Mike Ritter

    Found a pretty big hole (been learning a lot these few months). On the UPDATE method you’re posting the data, but not checking that ‘email’ is unique. That’s a pretty big hole. I’ll post my solution when I figure it out and advise the changes.

    • Mike Ritter

      Here’s my solution for my app. Adjust to suit your need.

      public function update($id)

      {

      //

      $i = Input::all();

      if($i){

      $rules = array(‘email’=>’email|unique:users’,’password’=>’alphanum|confirmed’);

      // $rules = array();

      $validator = Validator::make($i,$rules);

      if($validator->fails()){

      $response = $validator->messages()->toJson();

      return Response::make($response,400);

      }

      else{

      $u = User::find($id);

      // change email if it’s changed

      if($u->email != Input::get(‘email’)){

      $u->email = Input::get(‘email’);

      }

      if(Input::get(‘password’)){

      $u->password = Hash::make(Input::get(‘password’));

      }

      $u->save();

      // take to updated profile

      $response = “Update successful! User Page.”;

      return Response::make($response,202);

      }

      }

      • http://scotch.io/ Chris Sevilleja

        Sorry for the late response. Thanks for pointing out the hole and providing a solid solution. This was meant to be a starting point for CRUD applications so people could extend it for their needs and I really appreciate the work you’ve added.

        Thanks!

  • http://www.mrgeek.me/ Ali Gajani

    I would like to pay you for writing this tutorial. It’s that good. What’s your PayPal ? No I am serious!

  • Mona Ali
  • zak

    test

  • pushplaybang

    Great tut thanks, overall scotch seems to hit the mark for me, good job.

  • Don

    What are your thoughts on combining the create/update code into one? I don’t think that’s possible using Route:resource, which means you’d have to write the routes manually, but could be worth saving the duplicate code across all of the controllers.

    • http://scotch.io/ Chris Sevilleja

      I think that as long as the code would be similar, then that’s a good way to reduce code repeating.

      The biggest difference is populating the form (if you are updating an already existing item) and finding an existing item or creating a new one when going to do the save. Both of which are totally doable and adding just a few extra lines for those is better than repeating the entire function pretty much.

      Also a thing to look at when doing that to make things easier when updating, you can use Form Model Binding: http://scotch.io/quick-tips/php-tips/laravel-php/laravel-form-model-binding

  • http://www.mrgeek.me/ Ali Gajani

    Why aren’t you using Models.

    • http://scotch.io/ Chris Sevilleja

      We are using the Eloquent models. That’s why we can do things like Nerd::find($id)

      • http://www.mrgeek.me/ Ali Gajani

        I understand, but shouldn’t we pass the data from controllers to models for storing records instead of controllers handling all that?

        • http://scotch.io/ Chris Sevilleja

          Yes that’s how it would normally work in the MVC model. What’s happening here is pretty much that. Since Eloquent is an ORM, it magically handles all of that storing to the database logic for us.

          So we are handing it off to the model, which then stores for us. I know some people don’t like ORMs because of the automation and “magic” they provide. It’s preference.

          You could always create your own models and do the handoff from the controllers.

          • http://www.mrgeek.me/ Ali Gajani

            I see. That’s sweet, but we can save users from the model by passing it via controllers using static reference like User::createUser() where createUser() is a function in the model, taking in the data and storing it. Even though it is ORM, understandably a good practice would be to let model talk to the database; in true MVC fashion.