Начнём мы с модели административной части. В ней есть весь нам необходимый функционал. function getListQuery() это непосредственно запрос в базу данных. Код прокомментирован, всё в данных уроках упрощено для понимания материала, что какая функция делает можно почитать на официальном сайте. Что мы сделали мы вызвали ассоциативный массив для работы с полями, после указали что нужно сделать function populateState это и есть сортировка, дальше идёт запрос на выборку данных и в ней же указаны фильтры для сортировки. Откройте файл административной части models/mycomponents.php

<?php
/*Модель через неё идут запросы в базу, соответственно модель 
* работает на запись и вытаскивание данных,
*/

// Запрет к прямому доступу. Если кто то попытается обратиться к 
// файлу напрямую, joomla выдаст пустую страницу.
defined('_JEXEC') or die;

/**
 * Класс модели
 */
class MycomponentsModelMycomponents extends JModelList
{
	//Конструктор
	//Дополнительный ассоциативный массив параметров конфигурации.
	public function __construct($config = array())
	{
		if (empty($config['filter_fields'])) {
			$config['filter_fields'] = array(
				'id', 'a.id',
				'name', 'a.name',
				'adres', 'a.adres',				
				'ordering', 'a.ordering',
				'state', 'a.state'
			);
		}

		parent::__construct($config);
	}
	
	//Метод для автоматического заполнения model state
	//Примечание. Вызов GetState в этом методе приведет к рекурсии.
	protected function populateState($ordering = null, $direction = null)
	{
		$app = JFactory::getApplication('administrator');

		
		// Загрузите состояние фильтра.
		$search = $this->getUserStateFromRequest($this->context.'.filter.search', 
												'filter_search');
		$this->setState('filter.search', $search);
		
		$published = $this->getUserStateFromRequest($this->context.'.filter.state', 
												'filter_state', '', 'string');
		$this->setState('filter.state', $published);
		
		// Загрузка параметров
		$params = JComponentHelper::getParams('com_mycomponents');
		$this->setState('params', $params);

		// Список информации о состоянии
		parent::populateState('a.name', 'asc');
	}
	
	
	//Родные фильтры joomla с помощью них создаётся поиск и фильтрация опубликованных 
	// и неопубликованных данных
	protected function getStoreId($id = '')
	{
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.state');
		return parent::getStoreId($id);
	}	
	

	/**
	 * Метод для создания запросов SQL для загрузки данных списка.
	 *
	 * Возвращение строк запроса из бд.
	 */
	 
	protected function getListQuery()
	{
		// Создайте новый объект запроса.
		$db		= $this->getDbo();
		$query	= $db->getQuery(true);
		$user	= JFactory::getUser();

		// Выбираем нужные поля из таблицы
		$query->select(
		$this->getState('list.select','*'));
		
		$query->from($db->quoteName('#__mycomponent').' AS a');
				
		//Фильтры поиска				
		$search = $this->getState('filter.search');
		if (!empty($search)) {
			if (stripos($search, 'id:') === 0) {
				$query->where('a.id = '.(int) substr($search, 3));
			} else {
				$search = $db->Quote('%'.$db->escape($search, true).'%');
				$query->where('(a.name LIKE '.$search.')');
			}
		}		
				
				
		// Фильтр по состоянию публикации
		$published = $this->getState('filter.state');
		if (is_numeric($published)) {
			$query->where('a.state = '.(int) $published);
		} elseif ($published === '') {
			$query->where('(a.state IN (0, 1))');
		}
				
		
		// сортировка
		$orderCol	= $this->state->get('list.ordering');
		$orderDirn	= $this->state->get('list.direction');
		if ($orderCol == 'a.ordering' || $orderCol == 'category_title') {
			$orderCol = 'a.name '.$orderDirn.', a.ordering';
		}
		$query->order($db->escape($orderCol.' '.$orderDirn));

		return $query;
	}						
}

 

 

Теперь перейдём к контроллеру, он подключит модель и таблицу для вывода данных, своего рода это связующее звено. Откроем файл административной части controllers/mycomponents.php

<?php

// Запрет к прямому доступу. Если кто то попытается обратиться 
// к файлу напрямую, joomla выдаст пустую страницу.
defined('_JEXEC') or die;

/**
 * Класс контроллера
 */
class MycomponentsControllerMycomponents extends JControllerAdmin
{
	/**
	 * Прокси для getModel
	 */
	public function getModel($name = 'Mycomponent', 
						$prefix = 'MycomponentsModel', 
						$config = array('ignore_request' => true)
						)
	{
		$model = parent::getModel($name, $prefix, $config);
		return $model;
	}
	
	//Метод AJAX что бы сохранить представление записи.	
	public function saveOrderAjax()
	{

		$input = JFactory::getApplication()->input;
		$pks = $input->post->get('cid', array(), 'array');
		$order = $input->post->get('order', array(), 'array');

		JArrayHelper::toInteger($pks);
		JArrayHelper::toInteger($order);

		// Получаем модель
		$model = $this->getModel();

		// Сохранить порядок
		$return = $model->saveorder($pks, $order);

		if ($return)
		{
			echo "1";
		}

		// Закрыть приложение
		JFactory::getApplication()->close();
	}
	
}

 

Займёмся выводом, именно здесь мы получаем данные из модели, и формируем панель инструментов и кнопки. Код прокомментирован. Откройте файл views/mycomponents/view.html.php

<?php
// Запрет к прямому доступу. Если кто то попытается обратиться 
// к файлу напрямую, joomla выдаст пустую страницу.
defined('_JEXEC') or die;
 
/**
 * Вид компонента
 */
class MycomponentsViewMycomponents extends JViewLegacy
{
	
	protected $items;

	protected $pagination;

	protected $state;

	/**
	 * Отображение данных
	 */
	public function display($tpl = null)
	{
		$this->state		= $this->get('State');
		$this->items		= $this->get('Items');
		$this->pagination	= $this->get('Pagination');

		MycomponentsHelper::addSubmenu('mycomponents');

		// Проверить на наличие ошибок.
		if (count($errors = $this->get('Errors'))) {
			JError::raiseError(500, implode("\n", $errors));
			return false;
		}
		//Добавление навигации
		$this->addToolbar();
		$this->sidebar = JHtmlSidebar::render();
		parent::display($tpl);
	}

	/**
	 * Добавить заголовок страницы и панели инструментов.
	 *
	 * @since	1.6
	 */
	protected function addToolbar()
	{
		//Вывод навигации	
		require_once JPATH_COMPONENT.'/helpers/mycomponents.php';

		//Фильтры публикации		
		$state	= $this->get('State');
		$canDo	= MycomponentsHelper::getActions($state->get('filter.category_id'));
		$user	= JFactory::getUser();
		// Получить экземпляр объекта панели инструментов
		$bar = JToolBar::getInstance('toolbar');

		//Вывод панели инструментов, добавить, удалить, опубликовать, снять с публикации		
		JToolbarHelper::title(JText::_('COM_MYCOMPONENT'), 'mycomponents.png');
		if ($canDo->get('core.create')) {
			JToolbarHelper::addNew('mycomponent.add');
		}
		if ($canDo->get('core.edit')) {
			JToolbarHelper::editList('mycomponent.edit');
		}
		
			JToolbarHelper::publish('mycomponents.publish', 'JTOOLBAR_PUBLISH', true);
			JToolbarHelper::unpublish('mycomponents.unpublish', 'JTOOLBAR_UNPUBLISH', true);
		

			JToolbarHelper::deleteList('', 'mycomponents.delete');



		JHtmlSidebar::setAction('index.php?option=com_mycomponents&view=mycomponents');

		JHtmlSidebar::addFilter(
			JText::_('JOPTION_SELECT_PUBLISHED'),
			'filter_state',
			JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), 
												'value', 'text', 
												$this->state->get('filter.state'), 
												true)
		);
	}

	/**
	 * Возвращает массив полей таблицы можно сортировать
	 *
	 * Возвращение массива, содержащий имя поля для сортировки в качестве 
	 * ключа и текст на дисплее в качестве значения
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'a.ordering' => JText::_('JGRID_HEADING_ORDERING'),
			'a.state' => JText::_('JSTATUS'),
			'a.name' => JText::_('JGLOBAL_TITLE'),
			'a.adres' => JText::_('JGLOBAL_TITLE'),			
			'a.id' => JText::_('JGRID_HEADING_ID')
		);
	}
}

 

Конечно же это ещё не всё, сейчас мы приступим к созданию шаблона, и после уже займёмся файлом /helpers/mycomponents.php так как без него компонент выдаст ошибку. Откройте файл административной части views/mycomponents/tmpl/default.php

<?php

/*Это соновной шаблон главной страницы. Он зазбит на 3 части шапка, контент, и футер*/

// Запрет к прямому доступу. Если кто то попытается обратиться 
// к файлу напрямую, joomla выдаст пустую страницу.
defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html');
JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$user		= JFactory::getUser();
$userId		= $user->get('id');
$listOrder	= $this->escape($this->state->get('list.ordering'));
$listDirn	= $this->escape($this->state->get('list.direction'));
$canOrder	= $user->authorise('core.edit.state', 'com_mycomponents.category');
$saveOrder	= $listOrder == 'a.ordering';
if ($saveOrder)
{
	$saveOrderingUrl = 'index.php?option=com_mycomponents&task=mycomponents.'.
							'saveOrderAjax&tmpl=component';
	JHtml::_('
				sortablelist.sortable', 
				'mycomponentList', 
				'adminForm', 
				strtolower($listDirn), 
				$saveOrderingUrl);
}
$sortFields = $this->getSortFields();
?>

<!--Параметры сортировки-->
<script type="text/javascript">
	Joomla.orderTable = function() {
		table = document.getElementById("sortTable");
		direction = document.getElementById("directionTable");
		order = table.options[table.selectedIndex].value;
		if (order != '<?php echo $listOrder; ?>') {
			dirn = 'asc';
		} else {
			dirn = direction.options[direction.selectedIndex].value;
		}
		Joomla.tableOrdering(order, dirn, '');
	}
</script>


<form action="<?php 
					echo JRoute::_('index.php?option=com_mycomponents&view=mycomponents'); 
				?>" method="post" name="adminForm" id="adminForm">


<?php if(!empty( $this->sidebar)): ?>
	<div id="j-sidebar-container" class="span2">
		<?php echo $this->sidebar; ?>
	</div>
	<div id="j-main-container" class="span10">
<?php else : ?>
	<div id="j-main-container">
	<?php endif;?>
		<div id="filter-bar" class="btn-toolbar">
			<div class="filter-search btn-group pull-left">
				<label for="filter_search" class="element-invisible">
					<?php echo JText::_('COM_MYCOMPONENT_SEARCH_IN_TITLE');?>
				</label>
				<input type="text" name="filter_search" id="filter_search" 
					placeholder="<?php echo JText::_('COM_MYCOMPONENT_SEARCH_IN_TITLE'); ?>" 
					value="<?php echo $this->escape($this->state->get('filter.search')); ?>" 
					title="<?php echo JText::_('COM_MYCOMPONENT_SEARCH_IN_TITLE'); ?>" />
			</div>
			<div class="btn-group pull-left">
				<button class="btn hasTooltip" type="submit" 
						title="<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?>">
					<i class="icon-search"></i>
				</button>
				<button class="btn hasTooltip" type="button" 
						title="<?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?>" 
						onclick="document.id('filter_search').value='';this.form.submit();">
					<i class="icon-remove"></i>
				</button>
			</div>
			<div class="btn-group pull-right hidden-phone">
				<label for="limit" class="element-invisible">
					<?php echo JText::_('JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC');?>
				</label>
				<?php echo $this->pagination->getLimitBox(); ?>
			</div>
			<div class="btn-group pull-right hidden-phone">
				<label for="directionTable" class="element-invisible">
					<?php echo JText::_('JFIELD_ORDERING_DESC');?>
				</label>
				<select name="directionTable" id="directionTable" 
					class="input-medium" onchange="Joomla.orderTable()">
					<option value=""><?php echo JText::_('JFIELD_ORDERING_DESC');?></option>
					<option value="asc" <?php if ($listDirn == 'asc') echo 'selected="selected"'; ?>>
						<?php echo JText::_('JGLOBAL_ORDER_ASCENDING');?>
					</option>
					<option value="desc" <?php if ($listDirn == 'desc') echo 'selected="selected"'; ?>>
						<?php echo JText::_('JGLOBAL_ORDER_DESCENDING');?>
					</option>
				</select>
			</div>
			<div class="btn-group pull-right">
				<label for="sortTable" class="element-invisible">
					<?php echo JText::_('JGLOBAL_SORT_BY');?>
				</label>
				<select name="sortTable" id="sortTable" 
						class="input-medium" onchange="Joomla.orderTable()">
					<option value=""><?php echo JText::_('JGLOBAL_SORT_BY');?></option>
					<?php echo JHtml::_('select.options', $sortFields, 'value', 
										'text', $listOrder);?>
				</select>
			</div>
		</div>
		<div class="clearfix"> </div>
		<table class="table table-striped" id="mycomponentList">
					<thead>


			<tr>
			<th width="5">
				<?php echo JHtml::_('grid.sort',  'COM_MYCOMPONENT_ID', 'a.id', 
								$listDirn, $listOrder); ?>
			</th>
			<th width="1%" class="hidden-phone">
				<input type="checkbox" name="checkall-toggle" 
						value="" title="<?php echo JText::_('JGLOBAL_CHECK_ALL'); ?>" 
						onclick="Joomla.checkAll(this)" />
			</th>		
			<th>
			<?php echo JHtml::_('grid.sort',  'COM_MYCOMPONENT_RAZDEL', 'a.name', $listDirn, 
										$listOrder); ?>
			</th>
			<th width="10%">
				<?php echo JHtml::_('grid.sort',  
									'COM_MYCOMPONENT_ORDERING', 
									'a.ordering', 
									$listDirn, $listOrder); ?>
				<?php echo JHtml::_('grid.order',  
									$this->items, 
									'filesave.png', 
									'mycomponents.saveorder'); ?>
			</th>
			<th>
			<?php echo JHtml::_('grid.sort', 'JSTATUS', 'a.state', $listDirn, $listOrder); ?>
			</th>
			</tr>
			</thead>

					<tfoot>
						<tr>
							<td colspan="10">
								<?php echo $this->pagination->getListFooter(); ?>
							</td>
						</tr>
					</tfoot>
				
			<tbody>
			<!--Запускаем цикл кторый выведет данные на странице-->
						<?php foreach ($this->items as $i => $item) :
						$ordering   = ($listOrder == 'a.ordering');
						$canCreate  = $user->authorise('core.create',     
											'com_mycomponents.category.' . $item->catid);
						$canEdit    = $user->authorise('core.edit',       
											'com_mycomponents.category.' . $item->catid);
						$canCheckin = $user->authorise('core.manage',     
											'com_checkin') || 
											$item->checked_out == $user->get('id') || 
											$item->checked_out == 0;
						$canChange  = $user->authorise('core.edit.state', 
											'com_mycomponents.category.' . $item->catid) 
										&& $canCheckin;
						?>
			<tr class="row<?php echo $i % 2; ?>">
			<!--Выводим id записей-->
			<td>
			<?php echo $item->id; ?>
			</td>
			<td>
			<?php echo JHtml::_('grid.id', $i, $item->id); ?>
			</td>
			<!--Заключаем название в ссылку, и присваиваем названию id что 
			бы при нажатии подгрузилась именно эта запись-->
			<td>
			<a href="/<?php 
					echo JRoute::_('index.php?option=com_mycomponents&task=mycomponent.edit&id='.
											(int) $item->id); ?>"><?php echo $item->name; ?></a>
			</td>
			<!--Параметры сортировки данных-->
			<td align="center">
			<input type="text" name="order[]" size="5" value="<?php echo $item->ordering;?>" 
										<?php echo $disabled ?> class="text-area-order" />
			</td>
			<!--Параметры публикации-->
			<td align="center">
			<?php echo JHtml::_('jgrid.published', $item->state, $i, 'mycomponents.', 
										$canChange, 'cb', $item->publish_up, $item->publish_down); ?>
			</td>
			</tr>
			<?php endforeach; ?>
			</tbody>

		</table>

		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<input type="hidden" name="filter_order" value="<?php echo $listOrder; ?>" />
		<input type="hidden" name="filter_order_Dir" value="<?php echo $listDirn; ?>" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>

 

Завершающий этап создания первой страницы админки! Это файл /helpers/mycomponents.php если мы его не заполним то компонент выдаст ошибку, этот файл нужен для создания навигации по компоненту. Когда установите компонент вы увидите маленькую панель вверху. При расширении компонента, вносите туда другие страницы.

<?php
// Запрет к прямому доступу. Если кто то попытается обратиться 
// к файлу напрямую, joomla выдаст пустую страницу.
defined('_JEXEC') or die;

/**
 * Класс помощи.
 */
class MycomponentsHelper
{
	/**
	 * Установка панели ссылок.
	 */
	public static function addSubmenu($vName = 'mycomponents')
	{
		JHtmlSidebar::addEntry(JText::_('COM_MYCOMPONENT_RAZDEL'), 
			'index.php?option=com_mycomponents&view=mycomponents', $vName == 'mycomponents');
	}
	
	/**
	 * Получение действий
	 */
	public static function getActions($messageId = 0)
	{
		$user	= JFactory::getUser();
		$result	= new JObject;

		if (empty($messageId)) {
			$assetName = 'com_mycomponents';
		}
		else {
			$assetName = 'com_mycomponents.message.'.(int) $messageId;
		}

		$actions = array(
			'core.admin', 'core.manage', 'core.create', 'core.edit', 'core.delete'
		);

		foreach ($actions as $action) {
			$result->set($action,	$user->authorise($action, $assetName));
		}

		return $result;
	}
}

 

Вот и всё можете установить компонент и посмотреть. У нас появится страница с данными, но не всё в нём будет работать, а именно публикация, создание данных. Всем этим займёмся в следующей части.