This is part 2 of the “Laravel Guide”.

You can check the previous post here.

Create a website using laravel

This is my personal notes on laravel for future reference.

Writing posts like these help me learn quicker.

Where Credit is due

Laravel Guide - Part 2. Database, data & forms

This section will cover:

  • The Database
  • Creating the CRUD
  • Playing with our Data
  • Creating a form

Creating a Database

The Database

Let’s create a database for some posts.

We’ll begin by creating a database in phpmyadmin.

Make a database called laraveldb.

Make sure to update the .env file with the correct database information.

Create a Model

Now we’ll create a model:

php artisan make:model Post -m

We created Post (singular) model with the -m migration.

This will create a ‘date’…create_posts_table.php in the database/migrations folder.

There is a function called ‘up’ which adds info to our database upon creation.

We can add more columns in this table by adding:

$table->string('title');
$table->mediumText('body');

House keeping

With laravel 5.4 I also encountered an error with the database string length.

We need to make these changes in the Providers/AppServiceProvider.php file:

Add:

Use Illuminate\Support\Facades\Schema;

note these are backslashes

In the boot function add:

Schema::defaultStringLength(191);

Create the controller

Let’s create the controller for our posts:

php artisan make:controller PostsController --resource

This creates a controller for us with all the functions set up for our CRUD operations.

The routes

We can check all the routes in our site with this command:

php artisan route:list

Now we need to create the routes for all the post’s operation such as creating, viewing, updating and deleting the posts.

But instead of creating each post individually, we can add one line in the web.php file:

Route::resource('posts', 'PostsController');

This will create all the routes for our functions.

Run the route list command again to check all the routes:

php artisan route:list

We can see that all the routes are created for us.

Create some tables

Run the migrate command to create some tables:

php artisan migrate

We should now have the Posts table in our database with the additional columns we created.

Adding some data with tinker

We can add some dummy data in our database through phpmyadmin,

but let’s use tinker to add data via the command line:

php artisan tinker
App\Post::count()

We have entered a different mode and ran a command. We can see how many posts we have with the above.

Let’s add some data:

$post = new App\Post();
$post->title = 'Post One';
$post->body = 'This is some text';
$post->save();
App\Post::count()

You should now see a new table entry in phpmyadmin.

To exit tinker run:

quit

Handling our data

Eloquent data

So far we got values from other files.

This time we’ll retrieve data from the database.

Let’s set some rules in the app\Post.php file:

class Post extends Model
{
    // Table Name
    protected $table = 'posts';
    // Primary Key
    public $primaryKey ='id';
    // Timestamps
    public $timestamps = true;
}

Inside the Post class we can set things like what to use for the primary id.

Set up our Posts listings page

We will set up two routes in this section:

  • The index function which will display a list of our posts.
  • The show function that will display each individual post.

We’ll also bring in the model from the post.

In PostsController.php add:

use App\Post;

Also add the controller for our posts:

public function index()
    {
        $posts = Post::all(); //show all
        return view('posts.index')->with('posts', $posts);
    }

We are getting stuff from our database using: Post::all() and assigning it to $posts.

We can use this $posts to display data from our database in our view.

We also return the view to posts/index.blade.php with: return view(‘posts.index’).

Create the Posts page

Now we need to create the file in:

resources/views/posts/index.blade.php:

@extends('layouts.app')

@section('content')
    <h1>Posts</h1>
    @if(count($posts) > 0)
        @foreach($posts as $post)
            <div class="well">
                <h3><a href="/posts/{{$post->id}}">{{$post->title}}</a></h3>
                <small>written on {{$post->created_at}}</small>
            </div>
        @endforeach
    @else
        <p>No posts found</p>
    @endif
@endsection

Here we check whether we have any posts: @if(count($posts) > 0).

If we do, let’s run a loop for each post: @foreach($posts as $post).

Notice we can display values such as the id and post title: {{$post->id}} &{{$post->title}}.

We will use the id for generating a url for each post.

Next, we’ll set up our individual posts.

Before that, let’s quickly update our navigation menu.

views/inc/navbar.blade.php:

<nav class="navbar navbar-inverse">
  <div class="container">
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="/">{{config('app.name', 'LSAPP')}}</a>
    </div>
    <div id="navbar" class="collapse navbar-collapse">
      <ul class="nav navbar-nav">
        <li><a href="/">Home</a></li>
        <li><a href="/about">About</a></li>
        <li><a href="/services">Services</a></li>
        <li><a href="/posts">Blog</a></li>
      </ul>
    </div><!--/.nav-collapse -->
  </div>
</nav>

We just added a Blog link that will goto /posts.

The individual Post Page

Next, we will add some code in the show function of the PostsController:

public function show($id)
    {
        $post = Post::find($id);
        return view('posts.show')->with('post', $post);
    }

Next we need to create the view for this single post page.

We will create the file posts/show.blade.php and add:

@extends('layouts.app')

@section('content')
    <a href="/posts" class="btn btn-default">Go Back</a>
    <h1>{{$post->title}}</h1>
    <small>Written on {{$post->created_at}}</small>
    <hr>
    <div>
        {{$post->body}}
    </div>
@endsection

We should now have a working Posts page as well as a Single Post Page.

Order, Limit, Pagenate Posts

We can customize how are posts are displayed in the Posts page.

I’ll paste the additional examples in the PostController.php’s index function:

public function index()
    {
        // $posts = Post::all(); //show all
        // return Post::where('title', 'Post Two')->get(); //where clause
        // $posts = DB::select('SELECT * FROM posts'); //Using sql query
        // $posts = Post::orderby('created_at', 'desc')->take(1)->get(); //orderby & limit 1
        // $posts = Post::orderby('created_at', 'desc')->get(); //orderby
        $posts = Post::orderby('created_at', 'desc')->paginate(10); //paginate(add {{$posts->links()}} in view below loop)
        return view('posts.index')->with('posts', $posts);
    }

Note: if you want to use pagination, you need to add {{$posts->links()}} in the posts/index.blade.php file:

@extends('layouts.app')

@section('content')
    <h1>Posts</h1>
    @if(count($posts) > 0)
        @foreach($posts as $post)
            <div class="well">
                <h3><a href="/posts/{{$post->id}}">{{$post->title}}</h3></a>
                <small>written on {{$post->created_at}}</small>
            </div>
        @endforeach
        {{$posts->links()}}
    @else
        <p>No posts found</p>
    @endif
@endsection

I think we will end this section here.

In the next post we’ll learn about forms.