So far we have a working database complete with seed data and a bunch of routes for displaying, editing and deleting our projects and tasks. In this second chapter I’ll cover controllers, models (with relationships), views (including the blade templating language and layouts) and route model binding.

Laravel Form Helpers

In Laravel 4 we had a HTML package but it was removed for 5 to cut down on cruft. Add it back in by following the instructions in my How to Install Illuminate/HTML In Laravel 5 tutorial. In addition to HTML and Form facades, this package provides some handy helper functions such as link_to_route() which we’ll be using later.

Looks like the /projects URL is loading ProjectsController’s index method. So open up /app/Http/controllers/ProjectsController.php and update the method to point to a view we’ll create:

1
2
3
4

publicfunction index(){return view('projects.index');}

We’re using Blade Templates in this tutorial so create a /resources/views/projects/index.blade.php file and enter some text in there. Hit /projects in your browser again. If everything is working correctly you should see the text you entered above. Do the same for the create controller method.

Showing the contents of a view is great, but if we have more than one page on our site we’ll want a consistent template across all pages. In other words, we need the view’s contents to sit inside a basic HTML template. This is done with controller layouts.

There are a few steps to implementing controller layouts:

Create a layout view. Laravel actually ships with a pretty decent one called app.blade.php so we’ll save some time and just use that. Notice near the bottom the layout contains a @yield(‘content’) line. That’s the function that will load our actual content.

Reference your layout in your view using @extends(‘app’) and wrap in a @section(‘content’) block like so:

In /resources/views/projects folder create a show.blade.php, index.blade.php and create.blade.php view with the above markup replacing the filename as necessary. With these in place, refresh /projects in your browser. You should now see the app.blade.php skeleton around your view contents.

Route Model Binding

By default Laravel will provide an ID value to various resourceful controller methods such as show(), edit(), update() and destroy(). This is fine but it adds alot of extra boilerplate we need to write – grabbing the model instance, checking if it exists etc. Thankfully Laravel provides something called route model binding that helps with this issue. Instead of providing an $id variable, the method will be given the $project or $task object instance instead.

The TasksController will also need some minor modifications. Because we’re using nested resources, php artisan route:list will tell us that task routes all include a {projects} mask in addition to the {tasks} mask that some of them receive. As a result the controller methods will be passed a Project instance as their first argument. So update them accordingly remembering to update method docs and pass the new $project variable.

If you refresh the url /projects/project-1 everything should still be working.

Displaying Our Models

Project listing page

It’s time to start listing our projects and tasks. Open /projects in your browser. Based on php artisan route:list this is our project listing page. Open /resources/views/projects/index.blade.php and set it to the following:

Note: Be very careful when using model relationships. It’s easy to generate huge numbers of SQL queries if you’re not careful. This is called the N+1 problem. See the video below for details on what exactly the N+1 problem is, and how to protect against it.

Conclusion

Today we covered:

Route Model Binding

Models (with one-to-many relationships)

Controllers (with route model binding)

Views (with blade templating language and layouts)

We now have a working listing of projects and tasks. In the next lesson we’ll concentrate on editing, creating and deleting projects and tasks. Stay tuned!

Share This

Donate

Was this post helpful? Donate and keep a developer fed.

Steve Tredinnick

Hi… to use the link_to_route function in /resources/views/tasks/show.blade.php at the end of the post you need to have installed the Illuminate/Html Service provider, this is not listed until the next part of the tutorial.

Got it working with that! thanks! The link_to_route() function was not working for me even though I had IlluminateHtml installed.

eugenevdm

How did you fix link_to_route? I am getting Call to undefined function link_to_route() even though I also have IlluminateHtml installed as well. I can confirm it’s installed because I follow the tutorial how to install and the ‘artisan tinker’ command works with a sample form.

Ok… using previous Model’s relationship try this (tinker):
$task = AppTask::findOrFail(1)->project;as result you may get either Collection of projects or error message: ‘No query results for model [AppTask].’

P.S. double check every function in the each Model and make sure that you have data in Database … and connection to it

CreativePerson

I’ve made sure of that, but in Tinker, this:

AppTask::first()->project->name;

results in the following error message:

LogicException with message ‘Relationship method must return an object of type IlluminateDatabaseEloquentRelationsRelation’

My Projects.php file consists of this:

hasMany(‘AppTask’);
}
}

What am I doing wrong?

CreativePerson

I solved this problem by typing the following in succession in Tinker:

So add “LaravelCollective/html”:”5.0.*” – it shouldn’t be complicated. Just make sure you’ve added the service provider to your config file or the package won’t get loaded.

eugenevdm

Thanks man, after having spent all that time and finally getting it working, that:

1. My problem was the composer require command and trying to use it in PhpStorm.

2. PhpStorm default for doing composer command is the root of the folder, not the application folder. I kept on updating the wrong .json file until I CD to correct folder. The menu in PhpStorm also seemed to update the incorrect .json file.

3. Even when it properly updated it, PhpStorm didn’t update my remote development server so I have to guess which folder to upload.

It’s working perfectly now. It’s a really great demo. I’ve extended it to be three levels deep, i.e. Projects/Lists/Tasks.

Thank you so much for putting me on the fast track with Laravel 5. I haven’t been this inspired in a very long time.

I had the same issue, but for a different reason. In show.blade.php projects.tasks.show s/b just “project”, so project.tasks.show.

Edit: disregard, I had it wrong in routes.php.

NMSAN

Did you solve this problem.. I am getting it too.. 🙁

Ireco Gnizedyou

Getting 404 code on /projects/project-1 while /projects/1 is working. I have checked/compared the routes and controllers and everything seems correct. Any idea why url with slug causes the error? Thanks

Ireco Gnizedyou

I have added full namespace path to controllers in route resources and only after got worked URL with slug:

You didn’t follow the very first step of this tutorial nor did you read the numerous comments with the exact same issue as you and my response to them.

Sanket Sharma

Yeah.. I skipped IlluminateHTML package.. Thanks its working now…

DaveW

I’m at the of Route Model Binding and get the following error message : FatalErrorException in ProjectsController.php line 18:
Class ‘AppProject’ not found

flynsarmy

Does this file exist and have its namespace set correctly? Are you in routes.php or some other file? If it’s some other file, you need to add use AppProject; to the top.

Charles Vlug

i olso get “Class ‘AppProject’ not found”, even with “use AppProject;” in the controller.
But only if i omit:
”
// Use slugs rather than IDs in URLs
Route::bind(‘tasks’, function($value, $route) {
return AppTask::whereSlug($value)->first();
});
Route::bind(‘projects’, function($value, $route) {
return AppProject::whereSlug($value)->first();
});”
How can i get it working without the slugs?

Go to the git repo (linked to at the top of this post), check your model, controller and routes files and make sure yours are the same as mine.

Charles Vlug

Thanks. Most people don’t want to make a todo list however, but use you tutorial as a blueprint for an other application. If that application is not using slugs, it would be essential to know how to use Route Model Binding wihout slugs.

Katie Jenkins

unless i’m missing something, this repo doesn’t contain all of the files.

Guest

The page loads when I click on a task from a project, but the task name and task description in the tasks/show.blade.php don’t show up on the page. Only the Project link is displayed. Does anyone know why this is?

Can’t tell anything from that. Can you paste the rest of the dump plz.

balakumar

[2015-04-29 07:14:09] production.ERROR: exception ‘SymfonyComponentDebugExceptionFatalErrorException’ with message ‘Namespace declaration statement has to be the very first statement in the script’ in C:wampwwwlaravelappHttpControllersProjectsController.php:2

Look at the git repo mentioned at the top of this and all other posts in this series.

CreativePerson

For me, the following section of the tutorial is not clear. My questions are in [square brackets]. Here’s the problematic section of the tutorial:

“There are a few steps to implementing controller layouts:

Create a layout view. [ Where? You mean in resources/views? ] Laravel actually ships with a pretty decent one called app.blade.php [No such file exists in my project.] so we’ll save some time and just use that. Notice near the bottom the layout contains a @yield(‘content’) line. That’s the function that will load our actual content.

Reference your layout [ Which layout? ] in your view [ You mean in resources/views/app.blade.php ? ] using @extends(‘app’) and wrap in a @section(‘content’) block like so:

[ Are the above 4 lines the entire contents of resources/views/app.blade.php ? If there is more, can you please show it? ]

In /resources/views/projects folder create a show.blade.php, index.blade.phpand create.blade.php view with the above markup replacing the filename as necessary. With these in place, refresh /projects in your browser. You should now see the app.blade.php skeleton around your view contents. ”

[ After trying to follow these steps, my content has disappeared entirely. ]

flynsarmy

I think one look at the git repo linked to at the top of this article would answer all your questions. A lot of your issues probably stem from you using Laravel 5.1 whereas this article was written back when 5.0 was the latest version and those files were available. In 5.1 some directories were changed and it looks like app.blade.php was replaced with welcome.blade.php.

Now for your questions one by one:

[ Where? You mean in resources/views? ]

Yep. That’s where views go. I like to make ‘Layout’ views which is the HTML skeleton around ‘Page’ views – ie the About page content and any relevant markup. And ‘Partial’ views that are called from Layout and Page – ie a ‘header’ partial or a ‘footer’ partial – just to split things up into more workable pieces.

[No such file exists in my project.]

Was a laravel 5.0 thing. See above. It’s still available in my git repo.

[ Which layout? ]
[ You mean in resources/views/app.blade.php ? ]
Any layout you want. It’s your project. In mine I used app.blade.php.

[ Are the above 4 lines the entire contents of resources/views/app.blade.php ? If there is more, can you please show it? ]

The git repo is linked to at the start of EVERY tutorial in this series. Go there. It has the full file.

[ After trying to follow these steps, my content has disappeared entirely. ]

Sounds like you need to do some debugging. View your logs. It’ll tell you what you’ve done wrong. Also make sure the debug config option is turned on.

I may go through the 4 posts and update them for L5.1 however these things are very time consuming to write and as I’m doing it for free, other stuff often takes priority.

Oli

I have en error “View [projects.index] not found.”

my ProjectsController class :

public function index()
{
return view(‘projects.index’);
}

And the file resources/views/projects/index.blade.php is OK (with the right permissions) :
@extends(‘l5todo’)

Route [projects.tasks.show] not defined.
i spent 5-6hrs but not got solution.

nimmy

how to fetch images from database in controller of laravel 5?

Adeyemi

Route::model(‘tasks’, ‘Task’);Route::model(‘projects’, ‘Project’);

gave me several errors but

Route::model(‘task’, Task’);Route::model(‘project’, ‘Project’);

solved my problem

Ubiratan de Carvalho

Hello people!

Everything was going fine till “By this point your controllers should look like so:”

Trying to access /projects/project-1 on browser is returning me the following error:

ErrorException in helpers.php line 273:file_get_contents(/var/www/public/build/rev-manifest.json): failed to open stream: No such file or directory (View: /var/www/resources/views/app.blade.php) (View: /var/www/resources/views/app.blade.php)