Get up to 80 % extra points for free! More info:

Lesson 11 - Simple CMS in Laravel - Working with the date

In the last lesson, Simple CMS in Laravel - Laravel Mix, we focused on the front-end part of our project. We also added Font Awesome :)

In today's lesson we will explain the work with the date and then we move on to developing a back-end. We will create the main page.

Working with the date

Surely you have already noticed that the data in our application is listed in the default form from the database in the format Y-m-d H:i:s. However, this is something we really don't want to have as it's not exactly intuitive for users. In addition, the data is stored in UTC format. The time zone should also be best localized where we live.

In pure PHP, we would always have to call the date() function and set the time format ourselves. At best, we would use a library for that. However, someone for us has already taken care of that, as Laravel uses the Carbon library by default. This library contains many useful methods and translations for countless languages. If you are interested in more, visit the official website of the Carbon Library.

Application locale settings

Carbon gets the values for the settings from the application configuration file, which is, as you probably already know, in the config/ folder, more precisely in the app.php file. In this case, we are interested in the following values:

  • timezone - Defines the time zone for our application. The default value is UTC. For Central Europe, we could easily use CET (C entral E uropean T ime), but unfortunately there is a problem with summer time. Therefore, we will use the opportunity to define a continent with a city. If you live for example in New York, set America/New_York, if you live in Paris, set Europe/Paris and so on.
  • locale - Abbreviation for the language that our application should use. The default value is en. However, if you speak for example French, set locale to fr. This will change the language configuration for the framework, but also for the given library. If a phrase cannot be found for that language, the default is used. The fallback language is defined by the fallback_locale configuration value. This value is set as the default to English (en).

If you don't know how is your timezone or locale abbreviation exactly called, check the time zones or language codes on Wikipedia.

The changes in the file can look like this:

/*
|--------------------------------------------------------------------------
| Application Timezone
|--------------------------------------------------------------------------
|
| Here you may specify the default timezone for your application, which
| will be used by the PHP date and date-time functions. We have gone
| ahead and set this to a sensible default for you out of the box.
|
*/

'timezone' => 'America/New_York',

/*
|--------------------------------------------------------------------------
| Application Locale Configuration
|--------------------------------------------------------------------------
|
| The application locale determines the default locale that will be used
| by the translation service provider. You are free to set this value
| to any of the locales which will be supported by the application.
|
*/

'locale' => 'en',

The changes are now applied to our application. If we try to edit an article, we will see that the date of the last change also fits the local time. But what doesn't fit yet is the date listing, as it still uses the default format. Let's fix it.

If these changes do not affect your application, run the php artisan config:cache command in the project root folder. This is because the configuration values are cached and populated with new values using this command.

Outputting data in views

Let's start by the view for an article, which can be found in the resources/views/article/ folder and file named show.blade.php. There we list only the date of the last change of the specific record in the footer of the article. So we will create a new object of the Carbon library class and then print the time difference compared to the last change using the localized diffForHumans() method:

@php
    $updatedAt = new Carbon\Carbon($article->updated_at);
@endphp
<footer>
    <p class="small text-secondary border-top pt-2 mt-4">
        <i class="fa fa-calendar"></i> {{ $updatedAt->diffForHumans() }}
    </p>
</footer>

In addition to the classic PHP tags, the Blade directive @php ... @endphp can be used. There is no difference between them, only (and perhaps other developers will forgive me for this comment) it is a matter of beautifying the code of a given view.

If we display an article now, we'll see output similar to this in the footer of the article:

The time difference in an article listing using the Carbon library in Laravel - Laravel Framework for PHP

Our application looks a little more professional again. Unfortunately, our solution is no longer so good. The procedure is, of course, flawless and works exactly as we would like. For example, imagine that you have 10 different data on one page, and you always have to create a new Carbon class object for all that data. This would be a bit lengthy and at the same time the code would become confusing.

Data of the record as an instance of the Carbon library

As you have probably noticed in previous lessons, everything can always be simplified. The same is true for data of the record, which is always represented in the model instance as an object of the Carbon class inheriting the PHP DateTime class. So we don't have to bother creating a new object and we can immediately access the methods of this library.

Other dates that should work on the same principle in a given model are defined in the $dates variable. The created_at and updated_at attributes are already automatically included. Therefore, if you want to define additional data, it is unnecessary to specify it again.

So we can adjust the part of the view with the footer to the following form:

<footer>
    <p class="small text-secondary border-top pt-2 mt-4">
        <i class="fa fa-calendar"></i> {{ $article->updated_at->diffForHumans() }}
    </p>
</footer>

Localized date

We will probably agree that the exact date should be displayed to the user in the article. We can use one of the many available methods, isoFormat(), because one of the advantages is localized output (which does not apply, for example, to the format() method):

<footer>
    <p class="small text-secondary border-top pt-2 mt-4">
        <i class="fa fa-calendar"></i> {{ $article->updated_at->isoFormat('LLL') }}
    </p>
</footer>

The output may look similar to this:

The localized time in the article listing using the Carbon library in Laravel - Laravel Framework for PHP

More options for localized output can be found in the official Carbon library documentation.

Subsequently, we will also adjust the display of data in the article administration so that these outputs are unified. So we open the view resources/views/article/index.blade.php and modify the following part of the table:

<td>{{ $article->description }}</td>
<td>{{ $article->created_at->isoFormat('LLL') }}</td>
<td>{{ $article->updated_at->isoFormat('LLL') }}</td>
<td>

Main page

We will end the improvement of our application by creating a main page (homepage) for our website. For now, it will suffice for us to contain only a list of the latest articles.

Let's start with the controller first.

Single action controller

As we have already said, the controller for displaying the main page will define only one action. However, we pause at the method name for the given controller action. What should we name it? Names like show() or index() are not very suitable, as it is not a CRUD controller working with one instance of the model (on the main page we do not have to display only a list of articles and we also have one CRUD controller for the given model). You may come up with something like getHome(), but that's not the best approach either.

For such cases Laravel defines so called Controllers single action (Single Action Controllers). These controllers are characterized by the fact that they define only a single __invoke() method, which can accept parameters just like any other action.

Let's now create such a controller via the Artisan make:controller command. But before that, let's look at its possibilities:

php artisan help make:controller
The help text for the artisan make:controller command in the Laravel framework - Laravel Framework for PHP

We already know the --model[=MODEL] option from previous lessons. However, this time we will be interested in the --invokable option, which will create a single action controller. We will call it WelcomeController:

php artisan make:controller --invokable WelcomeController

The newly generated controller can be found in the folder with the controllers app/Http/Controllers/ and contains only the mentioned method __invoke():

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;

class WelcomeController extends Controller
{
    /**
     * Handle the incoming request.
     *
     * @param  Request $request
     * @return Response
     */
    public function __invoke(Request $request)
    {
        //
    }
}

We will use this method to display the main page. So it will be enough for us to return the view to which we pass the collection of the latest articles using the Eloquent method latest():

/**
 * Display the main page of the site.
 *
 * @param  Request $request
 * @return Response
 */
public function __invoke(Request $request)
{
    return view('welcome', ['articles' => Article::latest()->get()]);
}

We must not forget to import our model and classes mentioned in the documentation:

use App\Article;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\View\View;

Routing

The routing of single-action controllers is a bit different - we do not define the method of the given controller, but only its name. To display the main page using this controller, we need to add the following call to the get() method of the routing class Route to the routes/web.php routing file:

Route::get('', 'WelcomeController');

As you can see, we only define an empty string as a URI action. Thus we achieve that when you view the site without any other parameters in the URL executes method __invoke() controller for the main page WelcomeController.

We must also not forget to link the main page in the menu of our main template resources/views/base.blade.php. To do this, we use the helper function url():

<nav class="my-2 my-md-0 mr-md-3">
    <a class="p-2 text-dark" href="{{ url('') }}">Main page</a>
    <a class="p-2 text-dark" href="{{ route('article.index') }}">Articles</a>
    <a class="p-2 text-dark" href="#">Contact</a>
</nav>

View

We end the main page by creating a view named welcome.blade.php in the folder with views resources/views/. At the moment, he will not be in charge of anything other than listing all the articles from our database that we have submitted in the event controller method:

@extends('base')

@section('title', 'Simple content management system in Laravel')
@section('description', 'Sample tutorial for a simple content management system in the Laravel framework from the programming social network itnetwork.cz')

@section('content')
    <h1 class="text-center mb-4">Simple content management system in Laravel</h1>

    @forelse ($articles as $article)
        <article class="article mb-5">
            <header>
                <h2>
                    <a href="{{ route('article.show', ['article' => $article]) }}">{{ $article->title }}</a>
                </h2>
            </header>

            <p class="article-content mb-1">{{ $article->description }}</p>

            <footer>
                <p class="small text-secondary">
                    <i class="fa fa-calendar"></i> Last modified {{ $article->updated_at->diffForHumans() }}
                </p>
            </footer>
        </article>
    @empty
        <p>There are no articles yet.</p>
    @endforelse
@endsection

If we now open the main page via a link in the menu or by entering the URL of our application (in the case of the built-in web server http://127.0.0.1:8000/), we will see a list of the latest articles along with a link to them and their last modified date:

Main page in a simple content management system in the Laravel framework - Laravel Framework for PHP

Now we completed the improvement of our project. If you did not succeed, you can download the project from the attached archive or ask in the comments below.

In the next lesson, Simple CMS in Laravel - Contact form, we will create a new page, more precisely a contact form. Let's see how you can work with emails in the Laravel framework.


 

Did you have a problem with anything? Download the sample application below and compare it with your project, you will find the error easily.

Download

By downloading the following file, you agree to the license terms

Downloaded 10x (49.77 MB)
Application includes source codes in language php

 

Previous article
Simple CMS in Laravel - Laravel Mix
All articles in this section
Laravel Framework for PHP
Skip article
(not recommended)
Simple CMS in Laravel - Contact form
Article has been written for you by Lishaak
Avatar
User rating:
No one has rated this quite yet, be the first one!
Author is interested in programming mostly at web development, sometimes he does funny video edits from his vacations. He also loves memes and a lot of TV series :)
Activities