6 minutes reading time (1287 words)

How to create an author's page

How to... create an author page

If your website (or your client’s website) features blogs or articles by multiple authors, you may want to have author pages showing their bio and links to the articles they’ve written. Here’s how to do that with Joomla’s core contact component.

The contact component offers the possibility to create an author’s page displaying not only the contact details, but also a short description of the person and a list of their contributions.

In Joomla it is intended that the author of an article gets their own page using the Contacts Component. For it to work some settings are necessary. You have to create a contact that is linked to the respective user: 

Screenshot from contact

The plugin “Content - Contact” should be activated and pointing to the “Internal contact page”.

Screenshot from Conten - Contact plugin

You can also activate the plugin "User - Contact Creation" and a contact is automatically created when a user is created. Finally, you need to activate the linking of the author either in the Global Settings for articles or in the corresponding menu item.

Screenshot from the options to link the author

Now the author of an article is linked to their contact page:

Screenshot from a blog article with linked author 

You can edit the contact, upload an image/avatar and fill out all the fields you want to display. In this example I will use the field "More information” to write the author's bio.

Screenshot from More Information field in contact

To get nice URLs, we create a menu item "Authors" of type "List Contacts in a Category". The menu item can be visible or hidden.

The contact component has many settings, you can display or hide each field one by one. And since it is a contact component, a contact form is usually displayed. In this example I want to display the name, the website, the image, more information and the user articles. That is how the author’s page looks using Cassiopeia:

View of author page in frontend

Make it prettier!

This is not very appealing and not what you imagine for an author’s page. So we will need an override. Create overrides by clicking on System -> Site Templates -> Cassiopeia -> Create overrides. Find com_contact in the list and click on contact. Your overrides are now created in Cassiopeia’s html folder. 

To ensure that it is only for the authors, we will create an alternative layout. That means we have to rename our overrides so we can select them in the menu item. The view for contact consists of several files:

default.php
default-address.php
default articles.php
default-form.php
default.links.php
default profile.php
default-user-custom-fields.php

We rename “default” to “author”. Now we head back to our menu item and select “author” as our layout.

Layout option in menu item

For this example we will only modify author.php and author_articles.php, but you need to keep the other files too.

author.php

I moved some parts around and added Bootstrap classes. The code looks like this:

<?php

/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Helper\ContentHelper;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\FileLayout;
use Joomla\CMS\Layout\LayoutHelper;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Router\Route;
use Joomla\Component\Contact\Site\Helper\RouteHelper;

/** @var \Joomla\Component\Contact\Site\View\Contact\HtmlView $this */
$tparams = $this->item->params;
$canDo   = ContentHelper::getActions('com_contact', 'category', $this->item->catid);
$canEdit = $canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_by === $this->getCurrentUser()->id);
$htag    = $tparams->get('show_page_heading') ? 'h2' : 'h1';
$htag2   = ($tparams->get('show_page_heading') && $tparams->get('show_name')) ? 'h3' : 'h2';
$icon    = $this->params->get('contact_icons') == 0;
?>

<div class="com-contact contact">
    <?php if ($tparams->get('show_page_heading')) : ?>
        <h1>
            <?php echo $this->escape($tparams->get('page_heading')); ?>
        </h1>
    <?php endif; ?>

    <?php if ($canEdit) : ?>
        <div class="icons">
            <div class="float-end">
                <div>
                    <?php echo HTMLHelper::_('contacticon.edit', $this->item, $tparams); ?>
                </div>
            </div>
        </div>
    <?php endif; ?>

    <?php $show_contact_category = $tparams->get('show_contact_category'); ?>

    <?php if ($show_contact_category === 'show_no_link') : ?>
        <<?php echo $htag2; ?>>
            <span class="contact-category"><?php echo $this->item->category_title; ?></span>
        </<?php echo $htag2; ?>>
    <?php elseif ($show_contact_category === 'show_with_link') : ?>
        <?php $contactLink = RouteHelper::getCategoryRoute($this->item->catid, $this->item->language); ?>
        <<?php echo $htag2; ?>>
            <span class="contact-category"><a href="/<?php echo $contactLink; ?>">
                <?php echo $this->escape($this->item->category_title); ?></a>
            </span>
        </<?php echo $htag2; ?>>
    <?php endif; ?>

    <?php if ($tparams->get('show_contact_list') && count($this->contacts) > 1) : ?>
        <form action="#" method="get" name="selectForm" id="selectForm">
            <label for="select_contact"><?php echo Text::_('COM_CONTACT_SELECT_CONTACT'); ?></label>
            <?php echo HTMLHelper::_(
                'select.genericlist',
                $this->contacts,
                'select_contact',
                'class="form-select" onchange="document.location.href = this.value"',
                'link',
                'name',
                $this->item->link
            );
            ?>
        </form>
    <?php endif; ?>

    <?php if ($this->params->get('show_info', 1)) : ?>
        <div class="com-contact-author row gx-5">

            <?php if ($this->item->image && $tparams->get('show_image')) : ?>
                <div class="com-contact-author__image col-md-3">
                    <?php echo LayoutHelper::render(
                        'joomla.html.image',
                        [
                            'src'      => $this->item->image,
                            'alt'      => $this->item->name,
                            'class'    => 'rounded-circle',
                        ]
                    ); ?>
                </div>
            <?php endif; ?>

            <div class="author-info col-md-9">
                <?php if ($this->item->name && $tparams->get('show_name')) : ?>
                    <<?php echo $htag; ?>>
                        <?php if ($this->item->published == 0) : ?>
                            <span class="badge bg-warning text-light"><?php echo Text::_('JUNPUBLISHED'); ?></span>
                        <?php endif; ?>
                        <span class="contact-name"><?php echo $this->item->name; ?></span>
                    </<?php echo $htag; ?>>
                <?php endif; ?>

                <?php if ($this->item->misc && $tparams->get('show_misc')) : ?>

                    <div class="com-contact__miscinfo contact-miscinfo">
                        <?php echo $this->item->misc; ?>
                    </div>
                <?php endif; ?>

                <?php if ($this->item->con_position && $tparams->get('show_position')) : ?>
                    <dl class="com-contact__position contact-position dl-horizontal">
                        <dt><?php echo Text::_('COM_CONTACT_POSITION'); ?>:</dt>
                        <dd>
                            <?php echo $this->item->con_position; ?>
                        </dd>
                    </dl>
                <?php endif; ?>

                <div class="com-contact__info">
                    <?php echo $this->loadTemplate('address'); ?>

                    <?php if ($tparams->get('allow_vcard')) : ?>
                        <?php echo Text::_('COM_CONTACT_DOWNLOAD_INFORMATION_AS'); ?>
                        <a href="/<?php echo Route::_('index.php?option=com_contact&view=contact&catid=' . $this->item->catslug . '&id=' . $this->item->slug . '&format=vcf'); ?>">
                        <?php echo Text::_('COM_CONTACT_VCARD'); ?></a>
                    <?php endif; ?>
                </div>
            </div>
        </div>

    <?php endif; ?>

    <?php if ($tparams->get('show_email_form') && ($this->item->email_to || $this->item->user_id)) : ?>
        <?php echo '<' . $htag2 . '>' . Text::_('COM_CONTACT_EMAIL_FORM') . '</' . $htag2 . '>'; ?>

        <?php echo $this->loadTemplate('form'); ?>
    <?php endif; ?>

    <?php if ($tparams->get('show_links')) : ?>
        <?php echo '<' . $htag2 . '>' . Text::_('COM_CONTACT_LINKS') . '</' . $htag2 . '>'; ?>

        <?php echo $this->loadTemplate('links'); ?>
    <?php endif; ?>

    <?php if ($tparams->get('show_articles') && $this->item->user_id && $this->item->articles) : ?>
        <div class="mt-5">
            <?php echo '<' . $htag2 . '>' . Text::_('JGLOBAL_ARTICLES') . '</' . $htag2 . '>'; ?>

            <?php echo $this->loadTemplate('articles'); ?>
        </div>
    <?php endif; ?>

    <?php if ($tparams->get('show_profile') && $this->item->user_id && PluginHelper::isEnabled('user', 'profile')) : ?>
        <?php echo '<' . $htag2 . '>' . Text::_('COM_CONTACT_PROFILE') . '</' . $htag2 . '>'; ?>

        <?php echo $this->loadTemplate('profile'); ?>
    <?php endif; ?>

    <?php if ($tparams->get('show_user_custom_fields') && $this->contactUser) : ?>
        <?php echo $this->loadTemplate('user_custom_fields'); ?>
    <?php endif; ?>

    <?php echo $this->item->event->afterDisplayContent; ?>
</div>

author_articles.php

Here I have added some code to get the intro image, the introtext and the publishing date of the articles. I have again used some Bootstrap classes, so we don’t need to write CSS.

<?php

/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;
use Joomla\CMS\Router\Route;
use Joomla\Component\Content\Site\Helper\RouteHelper;

/** @var \Joomla\Component\Contact\Site\View\Contact\HtmlView $this */
?>
<?php if ($this->params->get('show_articles')) : ?>
    <div class="com-contact__articles contact-articles">
    <?php foreach ($this->item->articles as $article) : ?>
        <?php
            $images  = json_decode($article->images);
            $layoutAttr = [
                'src' => $images->image_intro,
                'alt' => empty($images->image_intro_alt) && empty($images->image_intro_alt_empty) ? false : $images->image_intro_alt,
            ];
        ?>
        <div class="contact-article row gx-5 py-4 border-bottom">
            <?php if (!empty($images->image_intro)) : ?>
                <div class="contact-image col-md-3">
                    <?php echo LayoutHelper::render('joomla.html.image', array_merge($layoutAttr, ['itemprop' => 'thumbnail'])); ?>
                </div>
            <?php endif; ?>
            <div class="contact-content col-md-9">
                <time class="article-date" datetime="<?php echo HTMLHelper::_('date', $article->publish_up, 'c'); ?>" itemprop="datePublished">
                    <?php echo Text::sprintf(HTMLHelper::_('date', $article->publish_up, Text::_('DATE_FORMAT_LC3'))); ?>
                </time>

                <h3 class="article-title" itemprop="name">
                    <?php echo HTMLHelper::_('link', Route::_(RouteHelper::getArticleRoute($article->slug, $article->catid, $article->language)), $this->escape($article->title)); ?>
                </h3>

                <?php echo $article->introtext; ?>

                <a class="readmore btn btn-secondary" href="/<?php echo Route::_(RouteHelper::getArticleRoute($article->slug, $article->catid, $article->language)); ?>" aria-label="<?php echo Text::sprintf('JGLOBAL_READ_MORE_TITLE', $this->escape($article->title)); ?>">
                    <?php echo Text::_('JGLOBAL_READ_MORE'); ?>
                </a>
            </div>
        </div>
    <?php endforeach; ?>
</div>
<?php endif; ?>

The result

Now we have a nice looking page for our authors:

Final view of the author's page

You can see a live example of a similar override on the website of the Joomla associations of the German-speaking countries (Germany, Austria, and Switzerland):

https://www.joomla.de/unsere-autoren/viviana-menzel 

Some articles published on the Joomla Community Magazine represent the personal opinion or experience of the Author on the specific topic and might not be aligned to the official position of the Joomla Project

6
The July issue
 

Comments

Already Registered? Login Here
No comments made yet. Be the first to submit a comment

By accepting you will be accessing a service provided by a third-party external to https://magazine.joomla.org/