Lesson 7 - Simple CMS in Laravel - Article listing
In the last lesson, Simple CMS in Laravel - Migration, we focused on migrations and created a model layer for articles.
As I promised, in today's lesson we will continue to create a controller and start displaying the article.
Routing
Let's start by defining routes for articles. We will open the file
routes/web.php
and remove the default route for the main page, as
we will not need it in our project yet. Instead, we define that the CRUD
controller created by us will process requests for articles:
Route::resource('article', 'ArticleController');
We used the resource()
method to define routes for all CRUD
controller actions. We already know that these are actions for adding, viewing,
editing and deleting an article. We can verify the result with the command
php artisan route:list
:
+--------+-----------+------------------------+-----------------+------------------------------------------------+------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+-----------+------------------------+-----------------+------------------------------------------------+------------+ | | GET|HEAD | api/user | | Closure | api | | | | | | | auth:api | | | GET|HEAD | article | article.index | App\Http\Controllers\ArticleController@index | web | | | POST | article | article.store | App\Http\Controllers\ArticleController@store | web | | | GET|HEAD | article/create | article.create | App\Http\Controllers\ArticleController@create | web | | | GET|HEAD | article/{article} | article.show | App\Http\Controllers\ArticleController@show | web | | | PUT|PATCH | article/{article} | article.update | App\Http\Controllers\ArticleController@update | web | | | DELETE | article/{article} | article.destroy | App\Http\Controllers\ArticleController@destroy | web | | | GET|HEAD | article/{article}/edit | article.edit | App\Http\Controllers\ArticleController@edit | web | +--------+-----------+------------------------+-----------------+------------------------------------------------+------------+
In addition to the article actions, the table above contains the
API action defined in the routes/api.php
file. For us, it's
currently irrelevant route, so we will ignore it.
The routing table describes the following properties:
Domain
- For which domain the given route is intended. If the value is empty, the default domain applies.Method
- HTTP method of action. Since HTML forms do not supportPUT
,PATCH
orDELETE
methods, we will have to modify them a bit. But we will show this in the next lesson.URI
- URI of the action (in our case the part in the URL address after the domain).Name
- The name of the action used in the code to create the link via the helperroute()
function (for example,route('article.index')
will generatehttp://localhost:8000/article
).Action
- The controller method that handles the action.Middleware
- A list of middleware through which the request passes.
Also note that in actions, such as views, the
{article}
parameter is defined in the URI. If we use the same
parameter name as the variables in the controller method, we can then obtain an
instance of the article only thanks to dependency injection,
more further in this lesson.
Pre-prepared article
We will add an introductory article to our table of articles so that we have something to work with before we create anything.
According to the official procedure, we should prepare so-called seeders. But I want to save you
that for now. Instead, we'll show you a new Artisan command - the
tinker
. It's a PHP console through which we can perform any
operation, even with framework classes. Then we insert the following code into
the console, through which we create a new article:
$article = new App\Article(); $article->title = 'Introduction'; $article->url = 'introduction'; $article->description = 'Introductory article on the web in the Laravel framework.'; $article->content = '<p>Welcome to our website!</p><p>This site is built on <strong>simple content management system in the Laravel framework</strong>. This is an introductory article retrieved from the database.</p>'; $article->save();
Finally, the save()
method returns a boolean
success value:
Controller
Now we move to the controller. There we only modify the show()
action to return the view along with the article data:
/** * Obtain the article and pass its data to the template. * * @param Article $article * @return Application|Factory|View */ public function show(Article $article) { return view('article.show', ['article' => $article]); }
We will not forget to add imports for the classes mentioned in the documentation:
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\View\Factory; use Illuminate\View\View;
Views
In order to view the article, we will need a view to do so. However, before
we start creating one, please remove the generated view
resources/views/welcome.blade.php
, because we will not need it
Web template
We will start by modifying the overall appearance of our application. This
will provide the main view of base.blade.php
:
<!DOCTYPE html> <html lang="en-US"> <head> <meta charset="utf-8" /> <meta name="csrf-token" content="{{ csrf_token() }}" /> <meta name="description" content="@yield('description')" /> <title>@yield('title', env('APP_NAME'))</title> <link href="{{ asset('css/app.css') }}" rel="stylesheet" /> <script src="{{ asset('js/app.js') }}"></script> </head> <body> <div class="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom shadow-sm"> <h5 class="my-0 mr-md-auto font-weight-normal">{{ env('APP_NAME') }}</h5> <nav class="my-2 my-md-0 mr-md-3"> <a class="p-2 text-dark" href="#">Main page</a> <a class="p-2 text-dark" href="#">Articles</a> <a class="p-2 text-dark" href="#">Contact</a> </nav> </div> <div class="container"> @if ($errors->any()) <div class="alert alert-danger mb-4"> <ul class="mb-0"> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif @yield('content') <footer class="pt-4 my-md-5 border-top"> <p> Sample tutorial for a simple content management system in the Laravel framework from a programming social network <a href="http://www.ict.social" target="_blank">ict.social</a> </p> </footer> </div> @stack('scripts') </body> </html>
In the lesson Simple CMS in Laravel - Project Structure, we imported the CSS framework Bootstrap into the project. I used Bootstrap when I was creating this template. I downloaded one of their examples and modified it a bit so that our site looks at least a little good.
Also notice these Blade Directives on the template above:
@yield('hodnota')
- One value is expected to be passed from the view that inherits that view. For example, the title from the current subpage template is passed to the main template. We can also define a default value, which we use for the page title. The block value is assigned by the Blade directives@section
(or@endsection
).@stack
- This is a collection stack unlike@yield
. This is useful for adding scripts, as we can pass them in multiple views for one page. Values are added to the stack using the Blade directives@push
(or@endpush
)
View article
In the view for displaying the article, which we will create in the
resources/views/article
folder named show.blade.php
,
we will inherit our main template and then use the blocks we have defined:
@extends('base') @section('title', $article->title) @section('description', $article->description) @section('content') <h1>{{ $article->title }}</h1> {!! $article->content !!} @endsection
Since the framework protects us from XSS attack by escaping the
output text, we must use {!! !!}
instead of {{ }}
. It
also contains HTML code.
However, if we now try to view our introductory article via the web page
/article/introduction
, we will get a 404 error even though
everything looks functional. So where is the mistake?
Defining an attribute for the parameter of the route
By default, Laravel retrieves data from the database using its ID. To view
the introductory article, we would have to use the address
/article/1
. However, this is unwanted behavior of the application,
as each of our articles has its own unique URL and we want to use it.
In order to apply the article url
value in routes using the
Article
model (parameter {article}
), we will need to
override the contents of the getRouteKeyName()
method in our model,
which is inherited from the Model
class:
/** * Return the name of the attribute by which the article is retrieved from the parameter of the route. * * @return string */ public function getRouteKeyName() { return 'url'; }
Now when you visit the page /article/introduction
we will see
our introductory article:
We now have the complete basis of the articles.
In the next lesson, Simple CMS in Laravel - Article creation, we'll look at articles creation and viewing its list in the administration.
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 46x (44.44 MB)
Application includes source codes in language php