Restful Controller in Laravel 5.1

Access all tutorials in sprocket icon.

August 17, 2015 from author Bill Keck.

Restful Controller in Laravel 5.1.

Please note that this tutorial references some of other tutorials. Here is a short list of the other tutorials you may want to read before this one:

We are using my Widget model in this tutorial, which is also referenced in the tutorials mentioned above. I recommend create the Widget model and routes to more effectively follow this tutorial.

With a restful controller, you get basic functionality for things like creating, reading, updating and deleting records. These are common tasks that you will have to do with most models you create. This is why I created the generic Widget model, so we can play with common functionality, and you can use this approach in the future for your projects.

A restful controller will have the following 7 methods:

  • index
  • show
  • create
  • store
  • edit
  • update
  • destroy

Now the good news is that Laravel 5.1 has built-in generators to create the controller, so you don’t have to memorize a long list of methods, it’s all there for you when you create it. So let’s make our controller.

Go to the command line and run:



php artisan make:controller WidgetController

That will get you the following file, which is in app/Http/Controllers/WidgetController.php:



 <?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;

class WidgetController extends Controller
{
   /**
    * 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.
    *
    * @param  Request  $request
    * @return Response
    */
   public function store(Request $request)
   {
       //
   }

   /**
    * 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  Request  $request
    * @param  int  $id
    * @return Response
    */
   public function update(Request $request, $id)
   {
       //
   }

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

You can see that these are empty stubs. They perfectly match our route resource that we created in our Route Resource Tutorial.

The workflow is fast and quick with the artisan generators. We’re going to add one more method, so you can stub it out now if you wish:



public function search(Request $request)
{

	//search widget model and return results

}

To avoid doing a super long tutorial all in one go, we’re going to build out our controller, then deal with the views in a separate tutorial.

I’m going to start with the search method, since that is the most complicated one on our controller.

The purpose of the search controller is to manage the POST request from a search form that searches the widgets table for results that are like the input string in the search box. In order for the POST to work, we will have to add the following route:



Route::post('widget/search', 'WidgetController@search');

Next, let’s change the search method on the controller to:



public function search(Request $request)
{
   $this->validate($request, [
       'widget_name' => 'required|alpha_num|max:20',

   ]);

   $searchterm = $request->widget_name;

       $widgets = DB::table('widgets');
       $results = $widgets->where('widget_name', 'LIKE', '%'. $searchterm .'%')
             ->get();


   if (count($results) > 0){

       $count = count($results);

       return view('widget.resultsindex', compact('results', 'count'));
       
   }

       return Redirect::route('widget.index')->with('message', ['Sorry, no results!']);


}

Since we’re dealing with a POST request, we want an instance of the request object handed into the signature like so:



public function search(Request $request)

We follow that with validation of the request:



 $this->validate($request, [
       'widget_name' => 'required|alpha_num|max:20',

   ]);

Note that the $this->validate method is always available to the controller. We hand in the instance of the request object, $request, and also an array of the key value pairs of the input name and the corresponding validation rules.

You can see that we want the input required, to be limited to alphanumeric, and to have a maximum of 20 characters. You can find a complete list of validation rules in the Laravel Docs, if you need other rules.

Next we assign a variable name to the request value:



$searchterm = $request->widget_name;

Then we create our object that pulls all results:



$widgets = DB::table('widgets');

Then we query for results, using LIKE, so we can anything that is like our $searchterm:



$results = $widgets->where('widget_name', 'LIKE', '%'. $searchterm .'%')->get();

The Laravel syntax is so intuitive, it is easier to follow than my written explanations. What a great framework.

So now we have $results holding our search results. We will test to see if there is anything there, and if so, send the user to a view that shows the results, and if not, we send them to the index method, with a message that no results were returned.

You will understand the intent of this when it’s all put together, but for now, imagine an index page for widgets that lists all the widgets. There is a search window on the page. If you use the search and there are results, you go to the results page. If there are no results, we go back to the index page, with a message telling us there are no results.

Let’s take a look at what this looks like:



if (count($results) > 0){

   $count = count($results);

   return view('widget.resultsindex', compact('results', 'count'));
   
}

   return Redirect::route('widget.index')->with('message', ['Sorry, no results!']);

You can see we are also setting a $count variable if there are results that we will send to the view. This is so we can display the number of results.

Of course this is just one implementation, not necessarily the best implementation. There are a lot of different ways to do this and you could implement the repository pattern for example. We’re not doing that here, but that will be the subject of a separate tutorial.

Also, as a side note, I couldn’t get pagination to work on my view partial, so until I solve that problem, I have left it out. I expect to fix it, so check back in the future for that.

One last thing to note here is that when there are no results, we attach a flash message, with a key of message, which is how we are going to let the index method know that it needs to do something if a search was executed and didn’t return results.

If you are not following the intent here exactly, don’t worry it will make more sense when you put it all together with the views.

I could have made this simpler by skipping search, but I felt like it was a nice addition because you are going to want to search your model records in most cases.

Anyway, let’s move on to the index method:



public function index()
{

  $widgets = Widget::paginate(10);

   $count =  DB::table('widgets')->count();

  if (session()->has('message')){

      Session::flash('noResults', 'Sorry, we found 0 results');
   }

   return view('widget.index', compact('widgets', 'count'));
}

For index, we want to return all widget records, paginated at 10 records per page. Can the syntax get any easier?

Next we hold the count of the records in $count.



   $count =  DB::table('widgets')->count();

Next we check to see if there is a ‘message’ in session, and if so, flash it into the session here, so we can pass it to the view:



  if (session()->has('message')){

      Session::flash('noResults', 'Sorry, we found 0 results');
   }

Then finally, we return to the view, using the compact function to pass our objects along:



return view('widget.index', compact('widgets', 'count'));

Note the syntax of the view method, widget.index. The widget in this case refers to a folder inside of views, and index is inside the widget folder.

Remember, I will be providing the views in a separate tutorial, so you will see how all this plays out.

Ok, next up we have the create method, which shows us the create form:



public function create()
{
   return view('widget.create');
}

You can see we are just returning a view for the form.

In restful controllers, there is a separate method for storing the form data:



public function store(Request $request)
{
   $this->validate($request, [
       'widget_name' => 'required|unique:widgets|alpha_num|max:20',

   ]);

   $widget = Widget::create(['widget_name' => $request->widget_name]);
   $widget->save();

   return Redirect::route('widget.index');

}

You can see we are taking in the request object, and running it through a validator:




$this->validate($request, [
       'widget_name' => 'required|unique:widgets|alpha_num|max:20',

   ]);

What’s different here than when we did it with search is that now we have to enforce the unique rule because we don’t want different widgets with the same name. When you see unique:widgets, that widgets part is the name of the table.

Next we create our instance of the model:



$widget = Widget::create(['widget_name' => $request->widget_name]);

Then we save it to the DB:



$widget->save();

Again, thanks to Laravel’s incredibly intuitive syntax, this is all just ridiculously easy.

Finally we return to the index page:



 return Redirect::route('widget.index');

Alternatively, you could go to the show page for the individual record, but I decided not to do that here.

Next we have the show method:



public function show($id)
{
   $widget = Widget::findOrFail($id);

   return view('widget.show', compact('widget'));
}

We hand in the id of the record we want, then use the findOrFail method to return it. Why findOrFail? Because it will return a ModelNotFound exception, which we can handle a certain way, so the user experience is good one. We will cover that in a separate tutorial.

Then we just return the result to the show view:



 return view('widget.show', compact('widget'));

Next we have the edit method, that returns the edit form:



public function edit($id)
{
   $widget = Widget::findOrFail($id);

   return view('widget.edit', compact('widget'));
}

We hand in the id of the record we are looking for, do a findOrFail, then return it to the view so we can bind it to the form.

To process the edit form, we need the update method:



public function update(Request $request, $id)
{
   $this->validate($request, [
       'widget_name' => 'required|unique:widgets|alpha_num|max:20',

   ]);
   $widget = Widget::findOrFail($id);
   $widget->update(['widget_name' => $request->widget_name]);


   return Redirect::route('widget.show', ['widget' => $widget]);
}

In this case, we are handing both the request object and the id. Then we validate the POST:



  $this->validate($request, [
       'widget_name' => 'required|unique:widgets|alpha_num|max:20',

   ]);

Next we find the model instance:



$widget = Widget::findOrFail($id);

Then we update using the value from the request object:



$widget->update(['widget_name' => $request->widget_name]);

Finally, we redirect to the show view, passing in the model instance:



return Redirect::route('widget.show', ['widget' => $widget]);

Ok, so the last method we have is the destroy method:



public function destroy($id)
{
   Widget::destroy($id);

   return Redirect::route('widget.index');
}

We use a model method, destroy, to delete the record of the id that we handed in. Then we simply redirect where we want, in this case, to the index page.

And that’s it for our Restful widget controller. I’ll follow this up with tutorial on the views within a few days, so you will understand all of this fully when you put it all together.

I hope you have enjoyed this tutorial and found it useful. Click on the sprocket icon at the top of the page to see all tutorials.

Please comment, share, and like if you can, thanks!

I don’t have a donate button, but If you would like to support my work and learn more about Laravel, you can do so by buying one of my books, Laraboot: laravel 5* For Beginners, I really appreciate it.

4 thoughts on “Restful Controller in Laravel 5.1

  1. khande1n says:

    I have followed widget tutorials, but when I try to get on page: widget/search, it shows an error.

    FatalErrorException in WidgetController.php line 71:
    Class ‘App\Http\Controllers\Widget’ not found

    The below is the 71 line : $widget = Widget::findOrFail($id);
    and it is in the show method.

    What should I do to get over this error. Thank you.

    Like

      • khande1n says:

        After adding the statement (use App\Widget) in WidgetController.php, now there are two new errors:

        1. ModelNotFoundException in Builder.php line 129:
        No query results for model [App\Widget].

        2. NotFoundHttpException in Handler.php line 46:
        No query results for model [App\Widget].

        It is pretty clear that the issue is somewhat related to the statement use App\Widget, but I cannot find the solution for the same.

        Like

      • Did you do the previous tutorials that set up the widget model and database? Do you have any widget records in the database? The beginning of the tutorial lists the dependencies of the other tutorials.

        Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s