•  
  •  
  •  
  •  
1 1 1 1 1 1 1 1 1 1 Рейтинг 5.00 (1 Голос)
Как происходит разработка расширений для Joomla! 3.0 – создание ядра (Статья 3) - 5.0 out of 5 based on 1 vote

Эта часть позволит нам сфокусироваться на рассмотрении деталей, создании тех функций и файлов, которыми будет представлено ядро для расширения.

Шаг 1:  Относительно деталей и функций моделей

Значит, мы уже обладаем базовыми файлами, поэтому мы перешли к созданию наших моделей. Сейчас задачей является определение моделей, которые будут наполняться с помощью функций. Обеспечим вас кратким обзором представленных моделей и функций:

Каким образом разрабатываются расширения для Joomla! 3.0 – создаем ядро (Статья 3)

Далее стоит заняться наполнением моделей. Перейдя к данному процессу, не стоит забывать о следующем принципе – нашему списку присуща динамичность. Для нас остается возможность возврата к списку и добавления или удаления функций, если есть в этом необходимость. Не следует бояться, при значительном прогрессе, заниматься пересмотром этого списка. Может быть, вам удастся его упростить путем добавления функции к определенной модели, а возможно возникнет необходимость в создании более абстрактной функции, которая будет нами добавлена в модель по умолчанию (default model). Необходимо не терять уверенность лишь в том, что нам не захочется вести постоянное переписывание одного и того же кода. Если у нас наблюдается подобное поведение, то следует задуматься над тем, каким образом добавить абстрактности коду с перенесением его к общей модели. Теперь следует начать создавать нашу модель.

Шаг 2: Создание модели

Одна статья является недостаточным объемом для рассмотрения всех моделей. Поэтому в фокусе окажутся лишь ключевые модели, которые обеспечивают демонстрацию большей части компонента. Мы не будем говорить о второстепенных моделях, о которых вы самостоятельно можете узнать из соответствующего GitHub репозитория.

Мы будем использовать модель "книга" (book). Во время размышлений над тем, что станет началом написания кода, мы решили воспользоваться конкретным примером для перехода к модели "библиотека" (library) и модели "профиль" (profile). Подобный подход обладает простым объяснением. Книга представляет собой наиболее маленький элемент, в библиотеку входят книги, а в профиле содержится библиотека. Но вначале нами будет создана модель по умолчанию (default model). Мы будем пользоваться ею для функций, которые пригодятся для всех наших моделей, а так как мы занимаемся написанием объектно-ориентированного кода, то нам вряд ли захочется работать над написанием одних и тех же функций в каждой модели.

models/default.php

<?php // no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );
 
class LendrModelsDefault extends JModelBase
{
    protected $__state_set = null;
    protected $_total = null;
    protected $_pagination = null;
    protected $_db = null;
    protected $id = null;
    protected $limitstart = 0;
    protected $limit = 10;
 
    function __construct()
    {
        parent::__construct();
    }
     
    public function store($data=null)
    {
        $data = $data ? $data : JRequest::get('post');
        $row = JTable::getInstance($data['table'],'Table');
         
        $date = date("Y-m-d H:i:s");
         
        // Bind the form fields to the table
        if (!$row->bind($data))
        {
            return false;
        }
     
        $row->modified = $date;
        if ( !$row->created )
        {
            $row->created = $date;
        }
         
        // Make sure the record is valid
        if (!$row->check())
        {
            return false;
        }
        // Store the web link table to the database
        if (!$row->store())
        {
            return false;
        }
     
        return $row;
     }

Большинством наших моделей будет осуществляться сохранение данных, то нами будет создана стандартная функция store(). Она будет подвергаться расширению при необходимости.

/**
* Modifies a property of the object, creating it if it does not already exist.
*
* @param string $property The name of the property.
* @param mixed $value The value of the property to set.
*
* @return mixed Previous value of the property.
*
* @since 11.1
*/
public function set($property, $value = null)
{
    $previous = isset($this->$property) ? $this->$property : null;
    $this->$property = $value;

    return $previous;
}

public function get($property, $default = null)
{
    return isset($this->$property) ? $this->$property : $default;
}

Мы часто будем заниматься установкой и получением переменных класса моделей из разных мест компонента. Вместо того, чтобы использовать прямую установку или ссылку на переменные, нами будет использована функция get и set.

/**
* Build a query, where clause and return an object
*
*/
public function getItem()
{
    $db = JFactory::getDBO();
     
    $query = $this->_buildQuery();
    $this->_buildWhere($query);
    $db->setQuery($query);
     
    $item = $db->loadObject();
     
    return $item;
}
 
/**
* Build query and where for protected _getList function and return a list
*
* @return array An array of results.
*/
public function listItems()
{
    $query = $this->_buildQuery();
    $query = $this->_buildWhere($query);
    $list = $this->_getList($query, $this->limitstart, $this->limit);
     
    return $list;
}

Этими двумя функциями представлены стандартные для получения элемента и получения списка элемента.

Каким образом разрабатываются расширения для Joomla! 3.0 – создаем ядро (Статья 3)

/**
* Gets an array of objects from the results of database query.
*
* @param string $query The query.
* @param integer $limitstart Offset.
* @param integer $limit The number of records.
*
* @return array An array of results.
*
* @since 11.1
*/
protected function _getList($query, $limitstart = 0, $limit = 0)
{
    $db = JFactory::getDBO();
    $db->setQuery($query, $limitstart, $limit);
    $result = $db->loadObjectList();
     
    return $result;
}
 
/**
* Returns a record count for the query
*
* @param string $query The query.
*
* @return integer Number of rows for query
*
* @since 11.1
*/
protected function _getListCount($query)
{
    $db = JFactory::getDBO();
    $db->setQuery($query);
    $db->query();
     
    return $db->getNumRows();
}

Этими двумя функциями пользуются для того, чтобы получить список из баз данных или получить количество элементов в списке.

/* Method to get model state variables
*
* @param string $property Optional parameter name
* @param mixed $default Optional default value
*
* @return object The property where specified, the state object where omitted
*
* @since 11.1
*/
public function getState($property = null, $default = null)
{
    if (!$this->__state_set)
    {
        // Protected method to auto-populate the model state.
        $this->populateState();
         
        // Set the model state set flag to true.
        $this->__state_set = true;
    }
 
    return $property === null ? $this->state : $this->state->get($property, $default);
}
 
/**
* Get total number of rows for pagination
*/
function getTotal()
{
    if ( empty ( $this->_total ) )
    {
        $query = $this->_buildQuery();
        $this->_total = $this->_getListCount($query);
    }

    return $this->_total;
}
 
/**
* Generate pagination
*/
function getPagination()
{
    // Lets load the content if it doesn't already exist
    if (empty($this->_pagination))
    {
        $this->_pagination = new JPagination( $this->getTotal(), $this->getState($this->_view.'_limitstart'), $this->getState($this->_view.'_limit'),null,JRoute::_('index.php?view='.$this->_view.'&layout='.$this->_layout));
    }

    return $this->_pagination;
}

Последними тремя функциями пользуются для обеспечения постраничной навигации. Нами они будут рассмотрены более тщательно в будущих публикациях.

models/book.php

<?php // no direct access
     
defined( '_JEXEC' ) or die( 'Restricted access' );
 
class LendrModelsBook extends LendrModelsDefault
{
 
    /**
    * Protected fields
    *
    */
    var $_book_id = null;
    var $_user_id = null;
    var $_library_id = null;
    var $_pagination = null;
    var $_total = null;
    var $_published = 1;
    var $_waitlist = FALSE;
     
     
    function __construct()
    {
        parent::__construct();
    }
 
   /**
    * Builds the query to be used by the book model
    * @return object Query object
    *
    */
    protected function _buildQuery()
    {
        $db = JFactory::getDBO();
        $query = $db->getQuery(TRUE);
         
        $query->select('b.book_id, b.user_id, b.isbn, b.title, b.author, b.summary, b.pages,
        b.publish_date, b.lent, b.lent_date, b.due_date');
        $query->from('#__lendr_books as b');
         
        $query->select('w.waitlist_id');
        $query->leftjoin('#__lendr_waitlists as w on w.book_id = b.book_id');
         
        return $query;
    }
     
    /**
    * Builds the filter for the query
    * @param object Query object
    * @return object Query object
    *
    */
    protected function _buildWhere(&$query)
    {
     
        if(is_numeric($this->_book_id))
        {
            $query->where('b.book_id = ' . (int) $this->_book_id);
        }
         
        if(is_numeric($this->_user_id))
        {
            $query->where('b.user_id = ' . (int) $this->_user_id);
        }
         
        if(is_numeric($this->_library_id))
        {
            $query->where('b.library_id = ' . (int) $this->_library_id);
        }
         
        if($this->_waitlist)
        {
            $query->where('w.waitlist_id > 0');
        }
         
        $query->where('b.published = ' . (int) $this->_published);
         
        return $query;
    }
}

models/library.php

<?php // no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );
 
class LendrModelsLibrary extends LendrModelsDefault
{  
    //Define class level variables
    var $_library_id = null;
    var $_user_id = null;
    var $_published = 1;
     
    function __construct()
    {
        parent::__construct();
         
        $app = JFactory::getApplication();
        $this->_library_id = $app->input->get('library_id',null);
        $this->_user_id = $app->input->get('user_id',JFactory::getUser()->id);
    }
    
    function getItem()
    {
        $library = parent::getItem();
         
        $bookModel = new LendrModelsBook();
        $bookModel->set('_user_id',$this->_user_id);
        $library->books = $bookModel->listItems();
     
        return $library;
    } 
 
    function listItems()
    {
        $bookModel = new LendrModelsBook();
        $libraries = parent::listItems();
         
        $n = count($libraries);
     
        for($i=0;$i<$n;$i++)
        {
            $library = $libraries[$i];
            $bookModel->_library_id = $library->id;
            $library->books = $bookModel->listItems();
        }
     
        return $libraries;
    }    
 
    protected function _buildQuery()
    {
        $db = JFactory::getDBO();
        $query = $db->getQuery(TRUE);
         
        $query->select("l.library_id, l.name, l.description");
        $query->from("#__lendr_libraries as l");
         
        $query->select("u.username, u.name");
        $query->leftjoin("#__users as u ON u.id = l.user_id");
         
        $query->select("p.*");
        $query->leftjoin("#__user_profiles as p on p.user_id = u.id");
         
        return $query;
    }

    protected function _buildWhere(&$query)
    {
     
        if(is_numeric($this->_user_id))
        {
            $query->where('l.user_id = ' . (int) $this->_user_id);
        }
         
        if(is_numeric($this->_library_id))
        {
            $query->where('l.library_id = ' . (int) $this->_library_id);
        }
         
            $query->where('l.published = '. (int) $this->_published);
         
            return $query;
    }
}

Это является прекрасным примером расширений стандартного класса. Следует обратить внимание, что мы обладаем функцией, название которой getItem. Функцию подобным названием получила и модель по умолчанию. Здесь нами получаются основные детали «компонента» (в данном примере они являются объектами библиотеки) благодаря родительской функции getItem, далее нами добавляется список книг. Стоит обратить внимание, что нами устанавливается user_id для моделей книг.

models/profile.php

<?php // no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

class LendrModelsProfile extends LendrModelsDefault
{
 
//Define class level variables
var $_user_id = null;
 
function __construct()
{
     
    $app = JFactory::getApplication();
     
    //If no User ID is set to current logged in user
    $this->_user_id = $app->input->get('profile_id', JFactory::getUser()->id);
     
    parent::__construct();
}
 
function getItem()
{
 
    $profile = JFactory::getUser($this->_user_id);
    $userDetails = JUserHelper::getProfile($this->_user_id);
    $profile->details = isset($userDetails->profile) ? $userDetails->profile : array();
     
    $libraryModel = new LendrModelsLibrary();
    $libraryModel->set('_user_id',$this->_user_id);
    $profile->library = $libraryModel->getItem();
     
    $waitlistModel = new LendrModelsWaitlist();
    $waitlistModel->set('_waitlist', TRUE);
    $profile->waitlist = $waitlistModel->getItem();
     
    $profile->isMine = JFactory::getUser()->id == $profile->id ? TRUE : FALSE;
     
    return $profile;
}

Эта функция позволяет нам не ссылаться на родительский метод getItem. Профиль является уникальным по своей структуре, а так как нами используется в качестве основы Joomla! 3 CMS, мы можем не включать набор таблиц и методов, которые относятся к пользователю и профилю.

Lendr будет обладать ограниченным числом полей профиля, и он нуждается только в определенных полях, доступных в плагине профиля Joomla!.

Получив профиль, переходим к инстанцированию нескольких вспомогательных моделей для получения связанных данных. Для нашего случая - модель библиотеки и списка ожиданий. Далее мы будем использовать эту функцию, и добавлять модели обзоров и избранного.

protected function _buildQuery()
    {
        $db = JFactory::getDBO();
        $query = $db->getQuery(TRUE);
         
        $query->select("u.id, u.username, u.name, u.email, u.registerDate");
        $query->from("#__users as u");
         
        $query->select("COUNT(b.book_id) as totalBooks");
        $query->leftjoin("#__lendr_books as b on b.user_id = u.id");
         
        $query->select("COUNT(r.review_id) as totalReviews");
        $query->leftjoin("#__lendr_reviews as r on r.user_id = u.id");
         
        return $query;
    }    
    protected function _buildWhere($query)
    {
        $query->group("u.id");
     
        return $query;
    }
     
}

Каким образом разрабатываются расширения для Joomla! 3.0 – создаем ядро (Статья 3)

Шаг 3: подключение дополнительных ресурсов

Наш компонент обладает некоторыми аспектами, для которых было хорошо воспользоваться сторонними возможностями, чтобы избежать повторного изобретения велосипеда. В упрощение и стилизации наших шаблонов нам поспособствует Bootstrap. Другим полезным ресурсом, который может быть добавлен к нашему компоненту, является Gravatar и Open Library. Если вам не известны эти инструменты, то они подробно описаны соответствующими сайтами. Ниже обеспечим вас кратким пояснением того, как мы их будем использовать в Lendr.

Gravatar

Gravatar является простым путем для получения изображения или аватара, связанного с адресом электронной почты. Lendr пользуется ним при отображении картинки профиля. Нами будет рассмотрен код подключения во время начала описывания шаблонов.

Open Library

Open Library обеспечивает нас прекрасной возможностью для получения обложек книг из ISBN. Это гарантирует нам легкий процесс включения обложки каждой книги, при котором нет необходимости в поддержке места хранения указанных обложек, загрузки изображений и прочего. Open Library обладает несколькими полями, которыми можно воспользоваться в процессе создания ссылки на обложку книги и возврата изображения. Lendr применяет ISBN в форме Add Book, которая будет нами рассмотрена ниже во время создания шаблонов.

Шаг 4: Создание шаблонов и стилей

Первейшая задача заключается в возвращении к нашей точке входа компонента, а именно до дефолтного контроллера, к которому мы ссылаемся в корневом файле lendr.php. Закончив создания нашей модели, мы поняли, что следует заняться обновлением места старта пользователя. Нами была изменена следующая строка контроллера controllers/default.php:

$layoutName = $app->input->getWord('layout', 'list');

Этим кодом будет перенаправляться пользователь к списку профилей. Оно является первым представлением, которое будет нами рассмотрено. Наша папка views обладает папкой profile, где применена следующая структура:

profile
    tmpl
        _entry.php
        index.html
        list.php
        profile.php
    html.php
    index.html
    phtml.php

Вначале займемся рассмотрением html.php файла. Файл этого типа используется Joomla! по умолчанию ввиду соглашения по именованию файлов. Нами отмечена базовая структура этих файлов во время написания предыдущего материала.

views/profile/html.php

<?php defined( '_JEXEC' ) or die( 'Restricted access' );

class LendrViewsProfileHtml extends JViewHtml
{
    function render()
    {
        $app = JFactory::getApplication();
        $layout = $app->input->get('layout');
         
        //retrieve task list from model
        $profileModel = new LendrModelsProfile();
         
        switch($layout) {
         
        case "profile":
        $this->profile = $profileModel->getItem();
        $this->_addBookView = LendrHelpersView::load('Book','_add','phtml');
         
        $this->_libraryView = LendrHelpersView::load('Library','_library','phtml');
        $this->_libraryView->library = $this->profile->library;
         
        $this->_waitlistView = LendrHelpersView::load('Waitlist','_waitlist','phtml');
        $this->_waitlistView->waitlist = $this->profile->waitlist;
        break;
         
        case "list":
        default:
        $this->profiles = $profileModel->listItems();
        $this->_profileListView = LendrHelpersView::load('Profile','_entry','phtml');
        break;
         
        }
         
        //display
        return parent::render();
    }
}

В этом файле содержится единственная функция render(), которая используется контроллерами. Файл позволяет нам определить переменные, которые будут применяться для определенных шаблонов. Здесь нами впервые используется LendrHelpersView. Наличие соглашения именования переменных, которые используются в Lendr, помогает для восприятия кода. Имена определенных переменных нами начаты нижним подчеркиванием и именем представления. Это призвано помочь в нескольких ситуациях.

Первое. Сразу можно отметить, что определенным переменным свойственно выступать в роли объектов представлений, если в них содержится имя представления. Нами может быть отображен объект там, где в этом возникает необходимость.

Второе. Благодаря нижнему подчеркиванию указывается факт того, что мы имеем дело с частичным шаблоном. Это обеспечивает запоминание того, что представление, вероятно, будет относится к другому представлению и не использоваться в качестве отдельного представления.

Каким образом разрабатываются расширения для Joomla! 3.0 – создаем ядро (Статья 3)

Так как нами вызван хелпер представления LendrHelpersView, то следует перейти к его рассмотрению.

helpers/view.php

<?php
// no direct access
defined('_JEXEC') or die('Restricted access');
 
class LendrHelpersView
{
    function load($viewName, $layoutName='default', $viewFormat='html', $vars=null)
    {
        // Get the application
        $app = JFactory::getApplication();
         
        $app->input->set('view', $viewName);
         
        // Register the layout paths for the view
        $paths = new SplPriorityQueue;
        $paths->insert(JPATH_COMPONENT . '/views/' . $viewName . '/tmpl', 'normal');
        $viewClass = 'LendrViews' . ucfirst($viewName) . ucfirst($viewFormat);
        $modelClass = 'LendrModels' . ucfirst($viewName);
         
        if (false === class_exists($modelClass))
        {
            $modelClass = 'LendrModelsDefault';
        }
         
        $view = new $viewClass(new $modelClass, $paths);
         
        $view->setLayout($layoutName);
        if(isset($vars))
        {
            foreach($vars as $varName => $var)
            {
                $view->$varName = $var;
            }
        }
        
        return $view;
    }
}

Этим файлом предоставляется функционал, который многими параметрами похож на контроллер по умолчанию. Мы обладаем более длинным списком параметров, а также foreach для назначения переменных, но остальное роднит его с контроллером. Этот хелпер представления полезен, когда вызываются классы представления и назначения переменных с помощью нашего частичного шаблона и других частей компонента.

Рассматривая оригинальный html-файл представления, присмотритесь к его параметрам, которые нами передаются в функцию load хелпера. Первый параметр сообщает хелперу, какой папкой нам необходимо воспользоваться. Вторым параметром указывается на файл шаблона. Третий параметр позволяет нам передать тип формата страницы.

Нами также создан файл phtml.php, чтобы отображать частичный html.php. Мы пользуемся этим файлом вместо обычного html представления, так как внутри файла html.php будет производиться вызов различных функций. Так как чаще всего для частичных шаблонов мы нуждаемся лишь в функции render(), то нам не следует нагружать их лишним кодом, который связан со стандартным файлом представления.

views/porfile/phtml.php

<?php
// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );
 
//Display partial views
class LendrViewsProfilePhtml extends JViewHTML
{
    function render()
    {
        return parent::render();
    }
}

views/porfile/tmpl/_entry.php

<div>
    <a href="/<?php echo JRoute::_('index.php?option=com_lendr&view=profile&layout=profile&id='.$this->profile->id); ?>">
        <img src="http://www.gravatar.com/avatar/<?php echo md5(strtolower(trim($this->profile->email))); ?>?s=60" />
    </a>
    <div>
        <h4><a href="/<?php echo JRoute::_('index.php?option=com_lendr&view=profile&layout=profile&profile_id='.$this->profile->id); ?>"><?php echo $this->profile->name; ?></a></h4>
        <p><strong><?php echo JText::_('COM_LENDR_TOTAL_BOOKS'); ?></strong>: <?php echo $this->profile->totalBooks; ?><br />
            <strong><?php echo JText::_('COM_LENDR_TOTAL_REVIEWS'); ?></strong>: <?php echo $this->profile->totalReviews; ?>
        </p>
    </div>
</div>

Как мы ранее упоминали, нами используется Gravatar API для того, чтобы отображать аватары пользователей. Следует внимательно присмотреться к широкому использованию стилей и разметки Bootstrap.

views/porfile/tmpl/list.php

<h2><?php echo JText::_('COM_LENDR_PROFILES'); ?></h2>
<div>
    <?php for($i=0, $n = count($this->profiles);$i<$n;$i++) {
        $this->_profileListView->profile = $this->profiles[$i];
        echo $this->_profileListView->render();
    } ?>
</div>

Этот файл относится к главным файлам. Он по умолчанию будет отдавать пользователю компонент. Представление списка включает стандартный html.php, расположенный в папке представления профиля, а также к нему относится частичный шаблона _profileListView. Говоря иначе, нами вызывается это представление, которое загружает контейнер для списка профилей. Внутри этого представления нами вызывается представление, которое представлено частичным шаблоном (_entry.php). Оно отобразит шаблон каждого отдельно взятого профиля.

Каким образом разрабатываются расширения для Joomla! 3.0 – создаем ядро (Статья 3)

views/porfile/tmpl/profile.php

<a href="/<?php echo JRoute::_('index.php?option=com_lendr&view=profile&layout=list'); ?>"><i></i> <?php echo JText::_('COM_LENDR_BACK'); ?></a>
<h2><?php echo $this->profile->name; ?></h2>
<div>
    <div>
        <img src="http://www.gravatar.com/avatar/<?php echo md5(strtolower(trim($this->profile->email))); ?>?s=180" />
    </div>
    <div>
        <dl>
            <dt><?php echo JText::_('COM_LENDR_PROFILE_NAME'); ?></dt>
            <dd><?php echo $this->profile->name; ?></dd>
            <dt><?php echo JText::_('COM_LENDR_PROFILE_JOIN'); ?></dt>
            <dd><?php echo JHtml::_('date', $this->profile->registerDate, JText::_('DATE_FORMAT_LC3')); ?></dd>
            <dt><?php echo JText::_('COM_LENDR_PROFILE_BIO'); ?></dt>
            <dd><?php if(isset($this->profile->details['aboutme'])) echo $this->profile->details['aboutme']; ?></dd>
        </dl>
    </div>
</div>
<br />
<div>
    <div>
        <ul>
            <li><a href="#libraryTab" data-toggle="tab"><?php echo JText::_('COM_LENDR_LIBRARY'); ?></a></li>
            <li><a href="#wishlistTab" data-toggle="tab"><?php echo JText::_('COM_LENDR_WISHLIST'); ?></a></li>
            <li><a href="#waitlistTab" data-toggle="tab"><?php echo JText::_('COM_LENDR_WAITLIST'); ?></a></li>
        </ul>
        <div>
            <div id="libraryTab">
                <?php if($this->profile->isMine) { ?>
                <a href="#newBookModal" role="button" data-toggle="modal"><i></i> <?php echo JText::_('COM_LENDR_ADD_BOOK'); ?></a>
                <?php } ?>
                <h2><?php echo JText::_('COM_LENDR_LIBRARY'); ?></h2>
                <?php echo $this->_libraryView->render(); ?>
            </div>
            <div id="wishlistTab">
                <h2><?php echo JText::_('COM_LENDR_WISHLIST'); ?></h2>
            </div>
            <div id="waitlistTab">
                <h2><?php echo JText::_('COM_LENDR_WAITLIST'); ?></h2>
                <?php echo $this->_waitlistView->render(); ?>
            </div>
        </div>
    </div>
</div>
     
<?php echo $this->_addBookView->render(); ?>

Данный шаблон профиля выступает в роли представления, которое видно пользователю при переходе к конкретному профилю. Так же как и с представлением списка, нами широко используются возможности частичных шаблонов, чтобы обеспечить повторное использование кода. Мы опять прибегаем к Gravatar для картинки профиля, а также различным bootstrap-функциям (tabs, buttons, wells, description blocks). Следует отметить, что каждой нашей вкладкой используется частичный шаблон, чтобы отображать соответствующий контент.

Остальные шаблоны

Нами были рассмотрены все типы шаблонов, которые находятся на вкладке profile, но в процессе внутри профиля будет происходить отображение дополнительных шаблонов. Чтобы сократить статью нами не будет рассматриваться код каждого представления. Вместо этого вы можете посмотреть его на GitHub репозитории.

Шаг 5: Javascript и CSS

Последняя часть из того, что нами будет рассмотрено посредством этой статьи – это начало разработки Javascript и CSS нашего компонента. Так как Lendr применяет Bootstrap и jQuery, модальное окно по добавлению книги, которое было рассмотрено во время предыдущего шага, будет включено автоматически. Но многие места компонента нами будут использованы для функций, требующих написания JavaScript кода, а также написания CSS стилей. Нами будет добавлен следующий хелпер, чтобы подключить стили и скрипты:

helpers/style.php

<?php
// no direct access
defined('_JEXEC') or die('Restricted access');
 
class LendrHelpersStyle
{
    function load()
    {
        $document = JFactory::getDocument();
         
        //stylesheets
        $document->addStylesheet(JURI::base().'components/com_lendr/assets/css/style.css');
         
        //j-avascripts
        $document->addScript(JURI::base().'components/com_lendr/assets/js/lendr.js');
    }
}

Здесь нами указывается весь css и javascript, который относится к нашему компоненту. Данный хелпер файл располагается в папке helpers и использует соглашение именования классов. Этот класс подключается автоматическим образом ввиду регистрации префикса Lendr в корневом файле компонента. Нами вызывается данный класс с помощью того же корневого файла благодаря следующему коду:

lendr.php

//Load styles and javascripts
LendrHelpersStyle::load();

Теперь мы завершили подключение наших скриптов и CSS. Поэтому, следует заняться добавлением функций. Вначале нами будет добавлена функция, которая связана с модальным окном добавления книги. Заполнив формы, пользователем отправляется форма при помощи клавиши “Add”. Нажав на эту клавишу, будет вызван javascript функции addBook():

assets/js/lendr.js

//add a book
function addBook()
{
    var bookInfo = {};
    jQuery("#bookForm :input").each(function(idx,ele){
        bookInfo[jQuery(ele).attr('name')] = jQuery(ele).val();
    });
     
    jQuery.ajax({
        url:'index.php?option=com_lendr&controller=add&format=raw&tmpl=component',
        type:'POST',
        data:bookInfo,
        dataType:'JSON',
        success:function(data)
        {
            if ( data.success ){
                jQuery("#book-list").append(data.html);
                jQuery("#newBookModal").modal('hide');
            }else{
             
            }
        }
    });
}

Эта функция нами вначале использует jQuery, чтобы создать объект bookInfo, в котором содержаться все переменные нашей формы. Как только они нами будут помещены в единую форму, мы сможем перейти к созданию ajax запроса, опять воспользовавшись jQuery. Следует обратить внимание, что нами указывались детали в URL, которые включают контроллер, формат и tmpl-тип. Так как Lendr - это расширение Joomla! 3.x, то наши контроллеры выступают в роли контроллеров с одной функцией execute(). Она и будет выполняться при отправке запроса. Формат применяется для возвращения лишь чистых данных из контроллера, а tmpl сообщает шаблону Joomla! каким файлом следует воспользоваться (component.php или index.php).

Дальше, контроллером (теперь уже add.php) обработается отправка формы, которая передается в корректную модель для сохранения и возвращения результата. Результат заключается в массиве  формата JSON, где установлена переменная success. Приводим код данного контроллера:

controllers/add.php

<?php defined( '_JEXEC' ) or die( 'Restricted access' );
 
class LendrControllersAdd extends JControllerBase
{
    public function execute()
    {
     
        $return = array("success"=>false);
         
        $model = new LendrModelsBook();
        if ( $row = $model->store() )
        {
            $return['success'] = true;
            $return['msg'] = JText::_('COM_LENDR_BOOK_SAVE_SUCCESS');
             
            $bookView = LendrHelpersView::load('Book','_entry','phtml');
            $bookView->book = $row;
             
            ob_start();
            echo $bookView->render();
            $html = ob_get_contents();
            ob_clean();
             
            $return['html'] = $html;
        }else{
            $return['msg'] = JText::_('COM_LENDR_BOOK_SAVE_FAILURE');
        }
        echo json_encode($return);
    }
}

Каким образом разрабатываются расширения для Joomla! 3.0 – создаем ядро (Статья 3)

При возвращении к javascript функции, нами определяется результат AJAX запроса и парсится ответ:

if ( data.success )
{
    jQuery("#book-list").append(data.html);
    jQuery("#newBookModal").modal('hide');
}else{
    ...
}

Здесь нами берется html (который мы вводили в контроллере и использовали как переменную html) и добавляется к таблице. Далее, нами скрывается модальное окно. На данный момент у нас остался пустой else, который будет заполнен позднее с помощью подходящего сообщения.

В итоге

Вам удалось осилить данную часть? Она, естественно, обладает большим объемом деталей и кода, которые было представлено в предыдущих статья. Но это сделано для обеспечения достаточного подхода к разработке расширений коммерческого уровня, основываясь на стандартах, применяя новейший MVC функционал, а также пользуясь другими уникальными возможностями Joomla! 3.x.

Следующая статья будет направлена на продолжение заполнения моделей и контроллеров, представления и javascript, необходимых при разработке расширения.

Все статьи цикла:

  1. Каким образом разрабатываются расширения для Joomla! 3.0 – подготовка (Статья 1)
  2. Каким образом разрабатываются расширения для Joomla! 3.0 – начинаем разработку (Статья 2)
  3. Текущая статья
  4. Каким образом разрабатываются расширения для Joomla! 3.0 – больше функционала (Статья 4)
  5. Каким образом разрабатываются расширения для Joomla! 3.0 – интерфейс администратора и доработка кода (Статья 5)
Портфолио
Память о Вас и Ваших близких на многие поколения
Подробнее
Прокат металла
Подробнее
Интернет-магазин кожи и меха
Подробнее
100% оригинальная парфюмерия в Москве
Подробнее
Вьетнамский ресторан премиум класса
Подробнее
Внедрение информационных систем
Подробнее
Организация международных конференций
Подробнее
Производство молочной продукции
Подробнее
Спортивный сайт
Подробнее
Интернет-магазин мебели и аксессуаров
Подробнее
Интернет-магазин электротранспорта
Подробнее
Сайт института актуальной экономики
Подробнее
Наши клиенты
Парк развлечений Boom Zoom
Алгор
Норбит
Molga Consulting
Metrotile
Нетология
Monqi
Премиум Пак
Aasha Herbals
Аджва
Салон красоты Сударушка
Пава
ТЦ &quot;Панфиловский&quot;
Фитнес Лаборатория
Система Главбух
Vanguard
GoAsia
ТЦ «Солнечный ветер»
Teledoc
Tchernov Cable
Отзывы
Благодарю компанию web-now.pro за помощь в разработке и запуске проекта POLITSECRETS.RU. Перед нами стояла задача – внедрить проект в сжатые сроки и по оптимальной цене. Порадовало то, что мне подроб...
Вера БлашенковаСекреты успешных выборов, Москва... апр.2016
Мне очень понравился подход с которым нас встретили "Ваша задача заниматься бизнесом, наша - сделать Вам представительство в сети". После этого ребята разработали полное тз на проект, мы внесли пожела...
МаксимIT-TASK, Москва... янв.2016
Работа проделана хорошо! Дизайнер и менеджер на отлично. Надеюсь на сотрудничество в дальнейшем. Есть шероховатости в деталях по задачам, но приятно сказывается оперативность и желание исправить, внес...
БруноСоциальная сеть След Жизни, Москва... янв.2016
Работой остались очень довольны. К работе подходят ответственно, аккуратно, открыто. Проект был сдан чуть раньше срока, по ходу работы возникали изменения, все они принимались безоговорочно, работа вы...
ЕвгенийМагазин текстиля, Москва... дек.2015
Сотрудничаем с 2007 года и сделали не один проект. Самое главное - команда умеет отстаивать своё мнение и постоянно развивается.
МарияМеждународные конференции, Москва... дек.2015
Спасибо всему коллективу компании! Разработали красивый и что самое главной рабочий интернет магазин! Реклама настроена и запущена, продажи идут, бизнес развивается! Нам постоянно подсказывают о новых...
ВадимИнтернет магазин Aromatic.pro, Москва... сен.2015
Большое спасибо команде за оперативность, качественные работы, отличный креатив и привлекательные цены!
Виктория, ОАО "Фармстандарт... июль.2015
Здравствуйте уважаемые партнеры! С наступающим Новым Годом! Желаю Вам дальнейшего процветания и успехов в Вашей благородной работе! С вами приятно сотрудничать! Очень благодарен Вам за своевременное о...
Сергей ЮрченкоКинотруд, Москва... дек.2014
Благодарим команду Brand Now и лично Дениса Логинова за оригинальное видение,разнообразие идей, четкость взаимодействия и безукоризненное соблюдение сроков выполнения проекта! Планируем продолжить сот...
ТатьянаBizness Linkerz... июль.2014
Компания КУН выражает благодарность за сотрудничество: непростая задача была выполнена в требуемые сроки и полностью удовлетворила заявленному ТЗ. Приятно удивила готовность Генерального директора нач...
Мария, Компания КУНhttp://www.kuhn.com/... апр.2014
Все отзывы
Добавить отзыв