Displaying a single record at frontend
Files to create / update
update breed.php /site/models/breed.php
update breed.php /site/controllers/breed.php
create view.html.php /site/views/breed/view.html.php
create default.php /site/views/breed/tmpl/default.php
create default.xml /site/views/breed/tmpl/default.xml
File Details
/site/models/breed.php
<?php
// No direct access.
defined('_JEXEC') or die;
jimport('joomla.application.component.modelitem');
jimport('joomla.event.dispatcher');
use Joomla\Utilities\ArrayHelper;
class BreedModelBreed extends JModelItem
{
protected function populateState()
{
$app = JFactory::getApplication('com_breed');
// Load the parameters.
$params = $app->getParams();
$params_array = $params->toArray();
if (isset($params_array['item_id']))
{
$this->setState('breed.id', $params_array['item_id']);
}
$this->setState('params', $params);
}
public function &getData($id = null)
{
if ($this->_item === null)
{
$this->_item = false;
$id = JRequest::getVar('id');
if (empty($id))
{
$id = $this->getState('breed.id');
}
$table = $this->getTable();
if ($table->load($id))
{
// Check published state.
if ($published = $this->getState('filter.published'))
{
if ($table->state != $published)
{
return $this->_item;
}
}
// Convert the JTable to a clean JObject.
$properties = $table->getProperties(1);
$this->_item = ArrayHelper::toObject($properties, 'JObject');
}
}
if (isset($this->_item->created_by) )
{
$this->_item->created_by_name = JFactory::getUser($this->_item->created_by)->name;
}
$this->_item->breedcat = JText::_('COM_BREED_BREEDS_BREEDCAT_OPTION_' . $this->_item->breedcat);
return $this->_item;
}
public function getTable($type = 'Breed', $prefix = 'BreedTable', $config = array())
{
$this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_breed/tables');
return JTable::getInstance($type, $prefix, $config);
}
public function getItemIdByAlias($alias)
{
$table = $this->getTable();
$table->load(array('alias' => $alias));
return $table->id;
}
public function delete($id)
{
$table = $this->getTable();
return $table->delete($id);
}
}
On line 6 of above mentioned code, we have imported modelitem utility so that JModelItem class could be used. After that we have imported event dispatcher library to handle the dispatching of events. Working together with JEvent class,it utilizes the functionality for the Event-Dispatcher-Pattern. Next we have instantiated a class called BreedModelBreed which is extending the JModelItem class. In this class, our first method is the getData() which will give us ability to retrieve all the data regarding a specific record id by calling JTable load() method by passing it the id of record as argument. We have also implemnented some other features here in this method, like checking for the published state of the record and displaying the record creator user name by getting it through the user id.
Next we have created a method called getTable to get a table object by providing parameters like type, table class prefix and configuration array. In this method, we have provided the path to the tables folder and have returned an instance of JTable class.
The next method is, getItemIdByAlias which will get the id of a record through item alias which it will get from url when we are using sef urls.
The last method is the delete method, which will simply delete an item according to the provided item id. We have also put this functionality on the single record display page so that the user could be able to delete a record after going through its details. In this manner, he would not need to go back to the listing page, search the record again and then delete it.
/site/controllers/breed.php
<?php
// No direct access
defined('_JEXEC') or die;
require_once JPATH_COMPONENT . '/controller.php';
class BreedControllerBreed extends BreedController
{
public function edit()
{
$app = JFactory::getApplication();
$previousId = (int) $app->getUserState('com_breed.edit.breed.id');
$editId = $app->input->getInt('id', 0);
$app->setUserState('com_breed.edit.breed.id', $editId);
$model = $this->getModel('Breed', 'BreedModel');
// Redirect to the edit screen.
$this->setRedirect(JRoute::_('index.php?option=com_breed&view=breedform&layout=edit', false));
}
public function remove()
{
// Initialise variables.
$app = JFactory::getApplication();
$user = JFactory::getUser();
if ($user->authorise('core.delete', 'com_breed'))
{
$model = $this->getModel('Breed', 'BreedModel');
$id = $app->input->getInt('id', 0);
$return = $model->delete($id);
if ($return === false)
{
$this->setMessage(JText::sprintf('Delete failed', $model->getError()), 'warning');
}
else
{
$app->setUserState('com_breed.edit.breed.id', null);
$app->setUserState('com_breed.edit.breed.data', null);
$this->setMessage(JText::_('COM_BREED_ITEM_DELETED_SUCCESSFULLY'));
}
$menu = JFactory::getApplication()->getMenu();
$item = $menu->getActive();
$this->setRedirect(JRoute::_($item->link, false));
}
else
{
throw new Exception(500);
}
}
}
On the single record display page, we will also add toaction buttons, Edit and Delete. The reason to put these buttons on the record detail page as well is, if the user wants to make any edits or wants to delete the record, he should be able to do that after viewing the details. To implement these two functionalities. So, in our breed.php controller file, we have first created the BreedControllerBreed class extending through main BreedController class. The first method we have created here is the edit() method which job is to checkout an item for editing and redirecting the user to the edit page. What it is doing is, it is just getting the id of the record and assigns it to userstate and on the basis of this id, it performs the checkin and checkout functions by calling models checkin() and checkout() methods respectively.
The second method of our breed controller is the remove() method which is meant to delete a specific record on the basis of provided id. This method first gets the record id from the detail page and calls the models delete method to delete that record by passing id as argument. If the model fails to delete the record, it throws an error and if it is successful, it flushes out all the data related to that specific record from the userstate method and redirects the user to the items list page.
/site/views/breed/view.html.php
<?php
// No direct access
defined('_JEXEC') or die;
jimport('joomla.application.component.view');
class BreedViewBreed extends JViewLegacy
{
protected $state;
protected $item;
protected $form;
protected $params;
public function display($tpl = null)
{
$app = JFactory::getApplication();
$user = JFactory::getUser();
$this->state = $this->get('State');
$this->item = $this->get('Data');
$this->params = $app->getParams('com_breed');
if (!empty($this->item))
{
$this->form = $this->get('Form');
}
if (count($errors = $this->get('Errors')))
{
throw new Exception(implode("\n", $errors));
}
if ($this->_layout == 'edit')
{
$authorised = $user->authorise('core.create', 'com_breed');
if ($authorised !== true)
{
throw new Exception(JText::_('JERROR_ALERTNOAUTHOR'));
}
}
$this->_prepareDocument();
parent::display($tpl);
}
protected function _prepareDocument()
{
$app = JFactory::getApplication();
$menus = $app->getMenu();
$title = null;
$menu = $menus->getActive();
if ($menu)
{
$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
}
else
{
$this->params->def('page_heading', JText::_('COM_BREED_DEFAULT_PAGE_TITLE'));
}
if ($this->params->get('menu-meta_description'))
{
$this->document->setDescription($this->params->get('menu-meta_description'));
}
if ($this->params->get('menu-meta_keywords'))
{
$this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords'));
}
if ($this->params->get('robots'))
{
$this->document->setMetadata('robots', $this->params->get('robots'));
}
$title = $this->params->get('page_title', '');
if (empty($title))
{
$title = $app->get('sitename');
}
elseif ($app->get('sitename_pagetitles', 0) == 1)
{
$title = JText::sprintf('JPAGETITLE', $app->get('sitename'), $title);
}
elseif ($app->get('sitename_pagetitles', 0) == 2)
{
$title = JText::sprintf('JPAGETITLE', $title, $app->get('sitename'));
}
$this->document->setTitle($title);
}
}
This is our single breed view, view.html.php file which will fetch the data from model and layout from view default.php file and will send it to browser to display to the user. In the breed view class, we first have four protected properties named, $state, which will be assigned the current user state in the display method, $item will be assigned with the item or record related data from the model and $form will be assigned with the form, fetched from the model. Similarly $params would be used to handle all the parameter values from the component on which we are working.
If the record is attached to a menu item, we will fetch the page title, meta description, meta keywords and robots etc from the menu parameters and will assign them to breed detail page document.All of this menu parameters fetching and document assigning code will be enclosed in the _prepareDocument() helper method, which is then being called in the display method.
/site/views/breed/tmpl/default.php
<?php
// No direct access
defined('_JEXEC') or die;
$user = JFactory::getUser();
$userId = $user->get('id');
$app = JFactory::getApplication('site');
$componentParams = $app->getParams('com_breed');
$width = $componentParams->get('imgwidth', 200);
if ($this->item) : ?>
<div class="row" style="padding:24px;">
<h2> <?php echo JText::_('COM_BREED_FORM_LBL_BREED_BREEDNAME'); ?> :
<?php echo $this->item->breedname; ?> </h2> <br>
<div class="span4">
<?php
foreach ((array) $this->item->pic as $singleFile) :
if (!is_array($singleFile)) :
$uploadPath = 'components'.DIRECTORY_SEPARATOR.'com_breed'.DIRECTORY_SEPARATOR.'breedpic' . DIRECTORY_SEPARATOR . $singleFile;
echo '<a href="' . JRoute::_(JUri::root() . $uploadPath, false) . '" target="_blank"><img src="' . JRoute::_(JUri::root() . $uploadPath, false) . '" width="<?php echo $width; ?>px"></a> ';
endif;
endforeach;
?>
</div>
<div class="span7">
<b><?php echo JText::_('COM_BREED_FORM_LBL_BREED_BREEDCAT'); ?> : </b>
<?php echo $this->item->breedcat; ?> <br><br>
<b> <?php echo JText::_('COM_BREED_FORM_LBL_BREED_SHORTDESC'); ?> : </b>
<?php echo $this->item->shortdesc; ?>
<br><br>
<b> <?php echo JText::_('COM_BREED_FORM_LBL_BREED_DESC'); ?>: </b>
<?php echo $this->item->desc; ?>
</div>
</div>
<div style="width:99%;" align="center">
<?php if($userId){ ?>
<a class="btn" href="<?php echo JRoute::_('index.php?option=com_breed&task=breed.edit&id='.$this->item->id); ?>"><?php echo JText::_("COM_BREED_EDIT_ITEM"); ?></a>
<a class="btn" href="<?php echo JRoute::_('index.php?option=com_breed&task=breed.remove&id=' . $this->item->id, false, 2); ?>"><?php echo JText::_("COM_BREED_DELETE_ITEM"); ?></a>
<?php } ?>
</div>
<?php
else:
echo JText::_('COM_BREED_ITEM_NOT_LOADED');
endif;
This is the main default.php view file which will actually display the breed details including title, pictures, id, short and detailed description. To construct the layout, first we have create a table and inside it,we have organized the page in the form of columns and rows. After that, we have put the field labels and values inside these columns. The code is so much simple and easy to understand as we are just echoing the item related data. For the loggedin user, we will show the edit and delete buttons so that by looking at the details, if the user want to perform any edit or wants to delete the item, he can do so just from the record detail page.
/site/views/breed/tmpl/default.xml
<?xml version="1.0" encoding="utf-8"?>
<metadata>
<layout title="COM_BREED_TITLE_ITEM_VIEW_BREED" option="View">
<message>
<![CDATA[COM_BREED_TITLE_ITEM_VIEW_BREED_DESC]]>
</message>
</layout>
<fields name="params">
<fieldset
name="basic"
label="COM_BREED_FIELDSET_ITEM_ID_SELECT_LABEL">
<field
name="item_id"
query="SELECT `id` FROM #__breed_breed ORDER BY `id`"
type="sql"
key_field="id"
value_field="id"
label="COM_BREED_ITEM_ID_SELECT_LABEL"
require="true"
description="JGLOBAL_SHOW_TITLE_DESC">
</field>
</fieldset>
</fields>
</metadata>