23

Creating a Basic ToDo Application in Laravel 5 – Part 4

Posted (Updated ) in PHP

Welcome back to my simple to-do application tutorial for Laravel 5. This tutorial is relatively long so I’ve broken it up into multiple posts.

  1. Part 1 – Installation, Database and Routes
  2. Part 2 – Listing Projects and Tasks
  3. Part 3 – Create/Edit/Delete
  4. Part 4 – Validation

The source for each part can also be found on GitHub.

So far we’ve learned how to install and set up Laravel, set up some project and task nested resources and display them to the user. Create, edit and delete functionality has also been implemented. In this chapter we’ll finish things off by adding form validation.

 

Server Side Form Validation

As it stands our create and edit forms work but they’re not validated. Let’s fix that.

There are multiple ways of handling form validation – some objectively better than others, however for such a small project as this I like to use the controllers validate() method with a Illuminate\Http\Request object like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// /app/Http/Controllers/ProjectsController.php
 
use Illuminate\Http\Request;
 
class ProjectsController extends Controller {
 
	protected $rules = [		'name' => ['required', 'min:3'],		'slug' => ['required'],	]; 
	/**
	 * Store a newly created resource in storage.
	 *
	 * @param \Illuminate\Http\Request $request	 * @return Response
	 */
	public function store(Request $request)
	{
		$this->validate($request, $this->rules); 
		$input = Input::all();
		Project::create( $input );
 
		return Redirect::route('projects.index')->with('message', 'Project created');
	}
 
	/**
	 * Update the specified resource in storage.
	 *
	 * @param  \App\Project $project
	 * @param \Illuminate\Http\Request $request	 * @return Response
	 */
	public function update(Project $project, Request $request)
	{
		$this->validate($request, $this->rules); 
		$input = array_except(Input::all(), '_method');
		$project->update($input);
 
		return Redirect::route('projects.show', $project->slug)->with('message', 'Project updated.');
	}
 
 
// /app/Http/Controllers/TasksController.php
use Illuminate\Http\Request;
 
class TasksController extends Controller {
 
	protected $rules = [		'name' => ['required', 'min:3'],		'slug' => ['required'],		'description' => ['required'],	]; 
	/**
	 * Store a newly created resource in storage.
	 *
	 * @param  \App\Project $project
	 * @param \Illuminate\Http\Request $request	 * @return Response
	 */
	public function store(Project $project, Request $request)
	{
		$this->validate($request, $this->rules); 
		$input = Input::all();
		$input['project_id'] = $project->id;
		Task::create( $input );
 
		return Redirect::route('projects.show', $project->slug)->with('Task created.');
	}
 
	/**
	 * Update the specified resource in storage.
	 *
	 * @param  \App\Project $project
	 * @param  \App\Task    $task
	 * @param \Illuminate\Http\Request $request	 * @return Response
	 */
	public function update(Project $project, Task $task, Request $request)
	{
		$this->validate($request, $this->rules); 
		$input = array_except(Input::all(), '_method');
		$task->update($input);
 
		return Redirect::route('projects.tasks.show', [$project->slug, $task->slug])->with('message', 'Task updated.');
	}

We need a place to display any generated errors. Open /resources/views/app.blade.php and drop the following above @yield(‘content’):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div class="content">
	@if (Session::has('message'))
		<div class="flash alert-info">
			<p>{{ Session::get('message') }}</p>
		</div>
	@endif
	@if ($errors->any())		<div class='flash alert-danger'>			@foreach ( $errors->all() as $error )				<p>{{ $error }}</p>			@endforeach		</div>	@endif 
	@yield('content')
</div>

See Available Validation Rules for a complete list of rules available. Validation should now be working. If validation on a form fails, $this->validate() will redirect back to the current page along with an ErrorBag of errors which will then be displayed on the page.

 

Conclusion

Over the court of this tutorial we’ve learned how to install and configure Laravel 5, add extra packages, handle seeds and migrations, generate and display resources, add create/edit/display pages for those resources and finally today we set up form validation. Along the way we even picked up a few more advanced concepts such as route model binding and CSRF protection. Despite its seemingly simple appearance at first a to-do application generally makes for a great starter app for any new PHP framework and Laravel has made the process of creating ours painless and fun. Happy coding!

  • Infacq

    do you have tutorial for RESTful api in laravel 5

  • Namal

    Thanks.. learnt a lot

  • chagam kamalakar

    Thanks bro.. it taught me many things as a beginner

  • Very good series, but I do have one question: shouldn’t the slug(s) have to be unique to prevent them from deleting multiple rows which have the same slug? Also in your conclusion you reference Laravel 4. Keep up the good work 🙂

    • flynsarmy

      Fixed the conclusion. Thanks 🙂

  • up23

    There needs to be a like button or a button give you karma points.

  • Eyal

    Cheers mate. Good stuff!

  • joynalabd

    May be slug should be unique, and rules will be:
    ‘slug’ => [‘required’, ‘unique:projects’]
    and in TasksController slug should be

    ‘slug’ => [‘required’, ‘unique:tasks’]

  • Avi Zuber

    Thanks for the tutorial! I started adding auth to this and so far I have it so each Project belongs to a User (with new migrations and everything). The only issue I have is changing $projects = Project::all(); to only return the logged in user’s projects. Any tips?

  • Nicolas Aguirre

    When I try to create a new task on a project, I get this error:

    Undefined variable: project (View: /home/vagrant/Code/todo/resources/views/tasks/create.blade.php)

    My tasks/create.blade.php:

    @extends (‘app’)

    @section(‘content’)
    Create Task for Project “{{ $project->name }}”

    {!! Form::model(new AppTask, [‘route’ => [‘projects.tasks.store’, $project->slug], ‘class’=>”]) !!}
    @include(‘tasks/partials/_form’, [‘submit_text’ => ‘Create Task’])
    {!! Form::close() !!}
    @endsection

  • Batz

    Everything worked until now. But the validation part i get this error when try to update / create task/ project
    “Undefined variable: request”.
    Anyone else has this?

  • Claudio Dobniewski

    Very Thank you! I’m a ultra newby in laravel, this tutorial is very good, higlinght code is very usefull and clear, and github source code available by part, can check my code.

  • Ricardo De la Vega

    Thanks for this useful explanation.

  • Foysal Mamun

    Thank you very much for very good tutorials.
    hope we will see more laravel tuts here.

  • thumbsup

    You saved me nearly one year of googling. Thank you very much!

  • Abraham Limpo

    Loved the tutorial. Very well explained. One thing only: it would be interesting to add some explanation about route validation: I can go to /projects/anything and it will not return an error, by default.

  • Leon

    Thank you! A wonderful tutorial!

  • Aasim Sajjad

    Love it 🙂 thankyou soo much for such a nice tutorials

  • Joao Prado

    I don’t usually comment on blog posts but this has helped me so much. Thank you.

  • Maximus Celestial Lee

    Hi i’m using Laravel 5.2 and got this error message:

    Undefined variable: errors

    • Place all route into middleware group.

      Route::group([‘middleware’ => [‘web’]], function () {
      //routes here
      }

  • Gerald Kigen

    Hi thanks for the tutorial.I am getting this error: Sorry, the page you are looking for could not be found.NotFoundHttpException in RouteCollection.php line 161:
    My routes.php looks like ths-

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

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

    // 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();

    });

    Route::resource(‘projects’, ‘ProjectsController’);

    Route::resource(‘projects.tasks’, ‘TasksController’);

  • Michel

    I’m late to the party, but if place in your model class:

    protected $fillable = [‘name’, ‘slug’, ‘description’];

    you don’t need to use array_except(). Just $task->update($request->all());