Magento 2 Development 23: Blog Listing

0

 

In this blog we will show the published and approved blogs on front-end. This will be our first public page since all of the pages before it required some kind of authentication either customer or admin. That means guest user also will be able to access this page.

The url for the blog listing page will be http://hostname/blog . For now you will have to directly browse the page. But in next blog we will add menus for this page.

So let’s create the controller file, Controller/Index/Index.php

<?php
namespace Webkul\BlogManager\Controller\Index;
use Magento\Framework\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;
class Index extends \Magento\Framework\App\Action\Action
{
public function __construct(
Context $context,
PageFactory $resultPageFactory
) {
$this->resultPageFactory = $resultPageFactory;
parent::__construct($context);
}
public function execute()
{
$resultPage = $this->resultPageFactory->create();
$resultPage->getConfig()->getTitle()->set(__('Blogs'));
$layout = $resultPage->getLayout();
return $resultPage;
}
}

One thing to note here is that we have extended \Magento\Framework\App\Action\Action and not the customer abstract account. That’s because this page will be accessible to guest users also.


Now the next step is to create the layout file view/frontend/layout/blogmanager_index_index.xml


<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<css src="Webkul_BlogManager::css/style.css"/>
</head>
<body>
<referenceContainer name="content">
<block class="Webkul\BlogManager\Block\Published\BlogList" name="blogmanager.blog.published.list" template="Webkul_BlogManager::published/list.phtml" />
</referenceContainer>
</body>
</page>

Note here we have used layout=”1column” instead of the 2 column layout pattern. Also we have not used the update handle code here because that was required to load base structure of customer account pages. And we have added the css node which will load the style file.


Let’s create the template file now view/frontend/templates/published/list.phtml

<?php
$blogs = $block->getCollection();
?>
<div class="blog-collection-wrapper">
<div class="blog-published">
<?php
foreach ($blogs as $blog) { ?>
<div class="blog-item">
<div class="blog-item-title">
<a href="<?= $block->getUrl('blog/index/view', ['id'=>$blog->getId()])?>"><?= $blog->getTitle(); ?></a>
</div>
<div class="blog-item-details">
<div><?= __("Created At:").' '.$block->getFormattedDate($blog->getCreatedAt()); ?></div>
<div><?= __("Author:").' '.$block->getAuthor($blog->getUserId()); ?></div>
</div>
<div class="blog-item-content">
<?= strlen($blog->getContent())<100 ? $blog->getContent() : substr($blog->getContent(),0,100).'...'; ?>
<div class="blog-item-view">
<a href="<?= $block->getUrl('blog/index/view', ['id'=>$blog->getId()])?>"><?= __('view'); ?></a>
</div>
</div>
</div>
<?php
} ?>
<?= $block->getPagerHtml(); ?>
</div>
</div>

We have loaded all the blogs with getCollection method, which we will create in block. Then we have looped over each blog to show data about them.

We have added links to view blog page which we will create in next blogs. Also we have used getFormattedDate and getAuthor which we will create in block. We have displayed first 100 characters of blog content.

Also we have called getPagerHtml to get the pagination when we have lots of blogs.


Now let’s see the block class Block/Published/BlogList.php

<?php
namespace Webkul\BlogManager\Block\Published;
class BlogList extends \Magento\Framework\View\Element\Template
{
public $blogCollection;
public $blogList;
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
\Webkul\BlogManager\Model\ResourceModel\Blog\CollectionFactory $blogCollection,
\Webkul\BlogManager\Helper\Data $helper,
\Magento\Customer\Model\CustomerFactory $customerFactory,
array $data = []
) {
$this->helper = $helper;
$this->blogCollection = $blogCollection;
$this->customerFactory = $customerFactory;
parent::__construct($context, $data);
}
public function getCollection()
{
if (!$this->blogList) {
$collection = $this->blogCollection->create();
$collection->addFieldToFilter('status', 1);
$collection->setOrder('created_at', 'DESC');
$this->blogList = $collection;
}
return $this->blogList;
}
protected function _prepareLayout()
{
parent::_prepareLayout();
if ($this->getCollection()) {
$pager = $this->getLayout()->createBlock(
\Magento\Theme\Block\Html\Pager::class,
'blogmanager.publishedblog.pager'
)
->setCollection(
$this->getCollection()
);
$this->setChild('pager', $pager);
$this->getCollection()->load();
}
return $this;
}
public function getPagerHtml()
{
return $this->getChildHtml('pager');
}
public function getAuthor($userId)
{
if ($userId) {
$customer = $this->customerFactory->create()->load($userId);
if ($customer && $customer->getId()) {
return $customer->getName();
}
}
return __('Admin');
}
public function getFormattedDate($date)
{
return $this->helper->getFormattedDate($date);
}
}

There are multiple things to notice here. First we have loaded the blogs based on status and sorted them by created date in getCollection method. After loading it we have set the collection in $this->blogList field variable. if (!$this->blogList) this ensure that we load the collection only once for a page load. Because if you see we have called the getCollection multiple times in _prepareLayout and also in the template file. So it will ensure that we load the collection only once and save the data for future function calls.

We need the _prepareLayout function so that the pagination works. Because we have not created code for pager but used magento’s pagination.

In getPagerHtml we have called for an child html called pager. This will be responsible for showing the pager based on the collection that we provide in prepare layout function.

The getAuthor is used to get the author name based on the id. We have loaded the customer model and get the name. If the id is 0 or if the customer with that id does not exist then it will return ‘Admin’.

For formatting dates I have created a function getFormattedDate which again calls a function of same from helper. We will create this function in helper.


Now let’s edit the helper class Helper/Data.php

<?php
namespace Webkul\BlogManager\Helper;
use Magento\Customer\Model\Session;
class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
public $customerSession;
public function __construct(
Session $customerSession,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $date,
\Magento\Framework\App\Helper\Context $context
) {
$this->date = $date;
$this->customerSession = $customerSession;
parent::__construct($context);
}
public function getCustomerId()
{
$customerId = $this->customerSession->getCustomerId();
return $customerId;
}
public function getFormattedDate($date='')
{
return $this->date->date($date)->format('d/m/y h:i A');
}
}

Here we have just added the function to format date.


We also need to do some styling so that the page looks good. So let’s edit the view/frontend/web/css/style.css

.blog-form .blog-form-field-container {
margin: 15px auto;
}
.blog-form .blog-form-action-container {
text-align: center;
}
.blog-form .blog-form-action-container .blog-form-action {
min-width: 150px;
padding: 10px;
font-size: 16px;
background: #2b4c8a;
color: white;
}
.blog-collection-wrapper {
max-width: 1000px;
margin: 0 auto;
}
.blog-published .blog-item-title {
font-size: 20px;
margin-bottom: 5px;
}
.blog-published .blog-item-title a:hover {
text-decoration: none;
}
.blog-published .blog-item-details div {
display: inline-block;
margin-right: 25px;
margin-bottom: 10px;
color: gray;
}
.blog-published .blog-item-content .blog-item-view {
margin-top: 5px;
text-decoration: underline;
}
.blog-published {
margin-top: -20px
}
.blog-published .blog-item {
border-bottom: 1px solid #cccccc;
padding-bottom: 20px;
padding-top: 30px;
}


Now when you browse the url. You should see all the blogs as shown below,

2021-08-03_18-11

Also you can see the pagination at the bottom,

2021-08-03_18-12-1


Post a Comment

0Comments
Post a Comment (0)
To Top