Example PHP application through Laravel – Notes

Unit: 12 of 12

After familiarizing ourselves in the previous lessons with how to create a PHP application and how to create different parts of the application in the Laravel framework, in this lesson we will create an application similar to the application in the previous lesson using Laravel.

The application we will create here is called Notes, and its job is to allow the user to enter notes within the application, edit, view, and delete them. However, at first it might appear to be similar to the To Do app, which it is. The purpose of this lesson is to see, with minor changes to the previously created application and given the specific purpose of the application, how easy it is to create a new application without having to start it from scratch every time and type the code completely (even when it’s much faster using the Laravel framework).

As before, most of this lesson in its text part will deal with the most important parts of the application, while in the video lesson we will show everything that is important: which way to go when creating application and how we should go through the different parts of the code to create the application successfully.

From the well-known GitHub link  https://github.com/amarbeslija/php-development  you will be able to download the complete application. Also, on the link  https://phpsandbox.io/e/x/gbmnc , using the phpsandbox.io tool, you can see how the full application works, or you can copy this notebook to edit it independently on your profile.

Of course, here we will not repeat absolutely everything that we have presented so far in the previous application, but we will focus on those places that have been changed and are different from the To Do application, and the rest will certainly remain the same.

Before starting, we advise you to try to make the same application yourself after familiarizing yourself with the application in detail. Although it may sound too difficult, following what you will learn in this lesson, the exercise will be quite easy, but working independently will help you learn more about Laravel and application development in general, than watching or reading ( which is of course a prerequisite for work).

Creating a migration

Before we start working, it would be good to think about what are the requirements of our application. As we said before, our app is called Notes and it allows us to enter some notes inside it. Here we will guide you to the simplest type of application, in which you can enter the title of the note as well as its text. Later, you can further develop this application and introduce the possibility to introduce other materials and data into it.

Of course, in addition to input, we need to be able to display these notes in a certain order (most often, from newest to oldest), edit their content, as well as delete notes. So we need to create a basic CRUD application as we saw before.

Based on what has been said, we understand that we need to create a table called “notes”, which will have the following columns: id, title, text, status, as well as timestamps, which Laravel gives us by default. We will use the status column for the so-called “soft delete”, i.e. not to show notes that have been deleted, but which, in fact, remain in the database. For such notes we will create a separate view where we can view the deleted notes.

Based on this, we can create the migration. We will start the console and inside it we will type the following command:

1

php artisane make:migration create_note_table

After running this command, inside the database/migration folder, we will find our migration and open it to edit it. It currently looks like this:

Image 16.1. A newly created migration in the application

After that, inside our up() method, we’ll enter the following code, which is actually a reflection of the columns we specified earlier in the lesson:

1

2

3

4

5

6

7

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

            $table->id();

            $table->string(‘title’);

            $table->string(‘text’);

            $table->string(‘status’);

            $table->timestamps();

        });

In the down method we will enter the following code:

1

Schema::dropIfExists(‘note’);

With this we are done creating the migration and we can run it. Of course, we will do this using the command we already know:

1

php artisan migrate:fresh

We see that the migrations have completed successfully inside our terminal:

Image 16.2. Migrations performed in the application

After a successful migration, we can start building our model.

Creating the model

As we saw earlier in this course, most things for our model are provided to us by default through Laravel. It’s just up to us to run a few commands and connect a few things.

First, we’ll create a new model. Of course, we will do this using the following command:

1

php artisan make:model Note

After we’ve successfully created the model, of course we’ll find it inside the app/Models folder, so we’ll open it up for editing. Currently it looks like this:

Image 16.3. New model created in the app

As mentioned earlier, here we will connect the table we created by migration and set which fields it is possible to make the input, that is, work with them through the ORM.

We will do this using the following code:

1

2

3

4

5

6

7

protected $table = ‘note’;

    protected $fillable = [

        ‘title’,

        ‘text’,

        ‘status’

    ];

Our model will look like this:

Image 16.4. Appearance of a completed model

Now that we have created the model, we can move on to creating the controller.

Creating the controller and setting the route

After we’ve created the model, we need to create a base for our controller so that we can initially present our view, while later editing it to receive data and work with our model.

To begin, let’s create our model with the following command:

1

php artisan make:controller NoteController –resource

As we want, as in the previous examples, for our controller to control all the actions of our application, we added a flag  when creating the controller , that is, an additional command in the form of the “–resource” command. This way, when creating the controller, all the default actions have been created automatically, which we will fill in with the Responses needed for the moment.

We can find the controller inside the app/Http/Controllers folder and it currently looks like this (the comments that usually exist have been removed to see all the methods in one screenshot):

Image 16.5. The current content of the NoteController.php controller

Having done this, let’s see in the following table what each method in this controller will do for us.

The name of the action The purpose of the action
index() Displaying the home page, where we will print all the notes (view index.blade.php).
create() Displaying the page for entering new notes  (view create.blade.php).
store() Action that will be called when the note entry form is executed, which will enter the data into the model.
show() Showing a single note in the application (show.blade.php).
edit() Displaying the page on which we will edit  the note (update.blade.php).
update() The action that will be called when the edit note form is executed, which will edit the data in the model.
destroy() The action that will be called when we want to delete the note, which will delete the note itself from the model (ie just change its state).

Table 16.1. Actions in the controller and their purpose

Now we’ll place the corresponding view calls inside the index(), create(), show(), and edit() actions, so that when we work on the views, we can test them visually without just doing it through code. Once we’re done creating layouts and views, we’ll go back to the controller and add bits of code that will handle Requests within these actions and other actions, of course, as needed.

Enter the following code:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

public function index()

    {

        return view(‘index’);

    }

    public function create()

    {

        return view(‘create’);

    }

    public function show($id)

    {

        return view(‘show’);

    }

    public function edit($id)

    {

        return view(‘edit’);

    }

After this, our controller will look like this:

Image 16.6. Controller layout that now only calls routes

All that remains is to edit our routes in the web.php file, in the routes folder.

Inside the web.php file we will enter the following code (we will edit the base route and add a new resource route):

1

2

3

4

5

Route::get(‘/’, function () {

    return redirect(“/Note”);

});

Route::resource(“/Note”, “App\Http\Controllers\NoteController”);

After that, our file will look like this:

Image 16.7. Layout of the routes file

After this, we can just move on to creating the layout file, which we will use inside the views, as well as the views themselves.

Creating the layout and views

As I said before, now we need to create the layout file as well as the views. Here we will essentially create the previously mentioned views: index, edit, show and create. Since the layout file uses the Blade Template Engine, we can create it in the standard way, and its name will be layout.

Of course, we will create views directly through the file system, without using commands, so after creation, we will have these five files created in the resources/views folder, as in the image:

Image 16.8. All files for views in the resources/views folder

After creating these files, let’s start editing them. First, we’ll edit layout.blade.php, as it’s the base for all other views. Inside it we will enter the following code:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

<!DOCTYPE html>

<html lang={{ app()->getLocale() }}>

<head>

    <title>Note Application</title>

    <meta charset=”utf-8″>

    <link href=”https://fonts.googleapis.com?css?family=Raleway:100,600″

    rel=”stylesheet” type=”text/css”>

    <link href=”https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css”

    rel=”stylesheet”>

    <script src=”https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js”></script>

    <script src=”https://maxcdn.bootstrapcdn.com/bootstrapcdn/3.3.7/js/bootstrap.min.js”></script>

</head>

<body>

    <div class=”container”>

        @yield(‘content’)

    </div>

</body>

</html>

As we can see, we could see this type of code in the previous application as well, and as I said, we left everything identical. Inside the div with the container class we will print our views.

Now we also edit index.blade.php, respectively view index. Inside it we will insert the following code:

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

@extends(‘layout’)

@section(‘content’)

    <div class=”row”>

        <div class=”col-lg-12 margin-tb”>

            <div class=”pull-left”>

                <h2>Notes Application</h2>

            </div>

            <div class=”pull-right”>

                <a class=”btn btn-success” href=”{{ route(‘Note.create’) }}”>

                    Add New Note

                </a>

            </div>

        </div>

    </div>

    @if($message = Session::get(‘success’))

        <div class=”alert alert-success”>

            <p>{{ $message }}</p>

        </div>

    @endif

    <table class=”table table-bordered”>

        <tr>

            <th>No.</th>

            <th>Title</th>

            <th>Note</th>

            <th>Status</th>

            <th style=”width:280px”>Action</th>

        </tr>

        @foreach($Note as $note)

            <tr>

                <td>{{ ++$i }}</td>

                <td>{{ $note->title}}

                @if ($note->status == ‘deleted’)

                    <td><del>{{ $note->text }}</del></td>

                    <td>Deleted</td>

                @else

                    <td>{{ $note->text }}</td>

                    <td>Active

                @endif

                <td>

                    <form action=”{{ route(‘Note.destroy’, $note->id) }}” method=”POST”>

                        <a class=”btn btn-info”

                            href=”{{ route(‘Note.show’, $note->id) }}”>

                            Show

                        </a>

                        <a class=”btn btn-primary”

                            href=”{{ route(‘Note.edit’, $note->id) }}”>

                            Edit

                        </a>

                        {{– @csrf

                        @method(‘DELETE’)

                        –}}

                        {{ csrf_field() }}

                       {{ method_field(‘DELETE’) }}

                        <button type=”submit” class=”btn btn-danger”>

                            Edit Status

                        </button>

                    </form>

                </td>

            </tr>

        @endforeach

    </table>

    {!! $Note->links() !!}

@endsection

As we can see, this view is also very similar to the one we have seen in previous applications. Basically, here we only added the “title” print from the model, so for the status of the note we have that it is either deleted or active, which of course we can change by editing the note.

Next , we will also edit the create.blade.php file, i.e. the create view . We will enter the following code:

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

@extends(‘layout’)

@section(‘content’)

    <div class=”row”>

        <div class=”col-lg-12 margin-tb”>

            <div class=”pull-left”>

                <h2>Add new Note</h2>

            </div>

            <div class=”pull-right”>

                <a class=”btn btn-primary”

                    href=”{{ route(‘Note.index’) }}”>

                    Back

                </a>

            </div>

        </div>

    </div>

    @if ($errors->any())

        <div class=”alert alert-danger”>

            <strong>Problems!!!</strong>

            <ul>

                @foreach ($errors->all() as $error)

                    <li>{{ $error }}</li>

                @endforeach

            </ul>

        </div>

    @endif

    <form action=”{{ route(‘Note.store’) }}” method=”POST”>

        {{ csrf_field() }}

        <div class=”row”>

            <div class=”col-xs-12 col-sm-12 col-md-12″>

                <div class=”form-group”>

                    <strong>Title:</strong>

                    <input type=”text” name=”title” class=”form-control” placeholder=”Note title…”>

                </div>

                <div class=”form-group”>

                    <strong>Note:</strong>

                    <input type=”text” name=”text” class=”form-control” placeholder=”Note text…”>

                </div>

            </div>

            <div class=”col-xs-12 col-sm-12 col-md-12 text-center”>

                <button type=”submit” class=”btn btn-primary”>

                    Submit

                </button>

            </div>

        </div>

    </form>

@endsection

Here we see that this view is also pretty standard and involves a form inside which we will be able to enter the title and content of the note, which will be sent to the “store()” action inside our controller for execution when the form executes.

We will now also edit edit.blade.php, namely our view for editing notes. We will enter the following code:

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

@extends(‘layout’)

@section(‘content’)

    <div class=”row”>

        <div class=”col-lg-12 margin-tb”>

            <div class=”pull-left”>

                <h2>Edit Note</h2>

            </div>

            <div class=”pull-right”>

                <a class=”btn btn-primary”

                    href=”{{ route(‘Note.index’) }}”>

                    Back

                </a>

            </div>

        </div>

    </div>

    @if ($errors->any())

        <div class=”alert alert-danger”>

            <strong>Problems!</strong>

            <ul>

                @foreach($errors->all() as $error)

                    <li>{{ $error }}</li>

                @endforeach

            </ul>

        </div>

    @endif

    <form action=”{{ route(‘Note.update’, $Note->id) }}” method=”POST”>

    {{ csrf_field() }}

    {{ method_field(‘PATCH’) }}

    <div class=”row”>

        <div class=”col-xs-12 col-sm-12 col-md-12″>

            <div class=”form-group”>

                <strong>Note title:</strong>

                <input type=”text” name=”title” value=”{{ $Note->title }}”

                class=”form-control”>

            </div>

            <div class=”form-group”>

                <strong>Note text:</strong>

                <input type=”text” name=”text” value=”{{ $Note->text }}”

                class=”form-control”>

            </div>

        </div>

        <div class=”col-xs-12 col-sm-12 col-md-12″>

            <div class=”form-group”>

                <strong>Note status:</strong>

                <select name=”status” class=”form-select”>

                    @php

                    $statuses = [‘active’, ‘deleted’];

                    @endphp

                    @foreach ($statuses as $status)

                        @if($status === $Note->status)

                            <option selected value=”{{ $status }}”>{{ $status }} </option>

                        @else

                            <option value=”{{ $status }}”>{{ $status }} </option>

                        @endif

                    @endforeach

                </select>

            </div>

        </div>

        <div class=”col-xs-12 col-sm-12 col-md-12 text-center”>

            <button type=”submit” class=”btn btn-primary”>Submit</button>

        </div>

    </div>

</form>

@endsection

As we can see inside this view, which is quite familiar to us, the only difference is that we only added a field to edit the title of our note, with its content and the status of the note.

All that’s left is to edit the show.blade.php file, which is our view for displaying individual notes.

We will enter the following code:

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

@extends(‘layout’)

@section(‘content’)

    <div class=”row”>

        <div class=”col-lg-12 margin-tb”>

            <div class=”pull-left”>

                <h2>Show Note</h2>

            </div>

            <div class=”pull-right”>

                <a class=”btn btn-primary”

                    href=”{{ route(‘Note.index’)}}”>

                    Back

                </a>

            </div>

        </div>

    </div>

    <div class=”row”>

        <div class=”col-xs-12 col-sm-12 col-md-12″>

            <div class=”form-group”>

                {{ $Note->title }}

            </div>

            <div class=”form-group”>

                <strong>Note:</strong>

                @if ($Note->status === ‘active’)

                    {{ $Note->text }}

                @else

                    <del> {{ $Note->text }} </del>

                @endif

            </div>

            <div class=”form-group”>

                <strong>Status:</strong>

                @if ($Note->status === ‘active’)

                    Active

                @else

                    Deleted

                @endif

            </div>

        </div>

    </div>

@endsection

And here we see that, unlike the applications in the previous lessons, we only added the possibility to print the title of our note and everything else is basically the same.

What we could see in all the views is of course that we had to adapt everything to the controller name as well as the model names. Our model is called “Note”, as is our controller “NoteController”, which means “Note” when routing, so everything inside the view is mapped to that, which of course is assumed.

Now that we have created these views, all that remains is to connect these views with our controller and test our application.

Connecting views, models, and controllers

We will now go back to our controller and edit our actions so that they can work with our forms and the requests that we will send from the front end to our application. We’ll edit our actions to look like the code below:

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

92

93

<?php

namespace App\Http\Controllers;

use App\Models\Note;

use Illuminate\Http\Request;

class NoteController extends Controller

{

    public function index()

    {

       $Note = Note::latest()->paginate(5);

       return view(‘index’, compact(‘Note’))

        ->with(‘i’, (request()->input(‘page’, 1) – 1) * 5);

    }

    public function create()

    {

        return view(‘create’);

    }

    public function store(Request $request)

    {

        $request->validate([

            ‘title’ => ‘required’,

            ‘text’ => ‘required’

        ]);

        Note::create(array_merge($request->all(), [‘status’ => ‘active’]));

        $Note = Note::latest()->paginate(5);

        return view(‘index’, compact(‘Note’))

        ->with(‘i’, (request()->input(‘page’, 1) – 1) * 5)

        ->with(‘sucess’, ‘Note updated sucessfully!’);

    }

    public function show($id)

    {

        $Note = Note::find($id);

        return view(‘show’, compact(‘Note’));

    }

    public function edit($id)

    {

        $Note = Note::find($id);

        return view(‘edit’, compact(‘Note’, ‘id’));

    }

    public function update($id, Request $request)

    {

        $request->validate([

            ‘title’ => ‘required’,

            ‘text’ => ‘required’,

            ‘status’ => ‘required’

        ]);

        $Note = Note::find($id);

        $Note->title = request(‘title’);

        $Note->text = request(‘text’);

        $Note->status = request(‘status’);

        $Note->save();

        $Note = Note::latest()->paginate(5);

        return view(‘index’, compact(‘Note’))

        ->with(‘i’, (request()->input(‘page’, 1) – 1) * 5);

    }

    public function destroy($id)

    {

        $Note = Note::find($id);

        if($Note->status === ‘active’){

            $Note->status = ‘deleted’;

        }else{

            $Note->status = ‘active’;

        }

        $Note->save();

        $Note = Note::latest()->paginate(5);

        return view(‘index’, compact(‘Note’))

        ->with(‘i’, (request()->input(‘page’, 1) – 1) * 5);

    }

}

Here we see that we have extended our actions, very similar to the previous actions, that we can work with requests (Request) and that we can process data. Of course, everywhere we’ve also added the ability to work with the “title” field within our actions.

One more change, unlike the previous examples, is that in the destroy() action, instead of an actual delete, we just changed the state of the field, i.e. we didn’t do a real delete from the database.

With this, we’re basically done with our app and all that’s left to do is test it. Of course, you can do it yourself, in the video lesson you can see in detail how the application works.

Lesson and course summary

At the end of this lesson and the course, we would do well to remember the most important thing, which is independent practice. In addition to the assignment, after the knowledge acquired through the text and video lessons, it is very important to start using the knowledge you have on smaller applications that are quite similar in their basic elements in real  life . After reading and watching, really learning by writing code and building an app will speed up the process and help you be ready to build any app using Laravel very quickly.

 

Additional Information

You can find a list of small app ideas that you can make yourself at the following link:

https://flaviocopes.com/sample-app-ideas/.

Of course, we suggest you also use the phpsandbox.io app for easier learning and practice, but come back later to install and work with Laravel on your computer and operating system for full freedom and flexibility.

See you in one of the next courses!

Good luck creating new apps!

If we want all actions of an entity to be controlled by the controller, what command will we use when creating the controller so that all actions are created automatically?

php artisan make:controller NoteController –resource

php artisan make:controller NoteController –actions

php artisan make:controller NoteController –action

php artisan make:controller NoteController –methods

Leave a Reply

Your email address will not be published. Required fields are marked *