Windwalker
$ php bin/windwalker generator init com_flower sakura.sakuras [--client] [--tmpl]
Joomla
# None...
Windwalker has a powerful extension generator, you can generate components, modules and plugins by default template or customize your templates.
$ php bin/windwalker generator init com_flower sakura.sakuras [--client] [--tmpl]
# None...
Simpler component entry than Joomla native. You can override component initialise process in your Component object.
// No direct access defined('_JEXEC') or die; include_once JPATH_COMPONENT_ADMINISTRATOR . '/src/init.php'; echo with(new FlowerComponent)->execute();
// No direct access to this file defined('_JEXEC') or die('Restricted access'); // require helper files JLoader::register('FlowerHelper', dirname(__FILE__) . '/helpers/flower.php'); $controller = JControllerLegacy::getInstance('Flower'); $controller->execute(JFactory::getApplication()->input->get('task')); $controller->redirect();
Tasks like: display, save, update, reorder and delete etc. They are all has default controllers in Windwalker. You don't need to write them out, just override it if you require a new process.
// Use default controller
// No direct access to this file defined('_JEXEC') or die('Restricted access'); class FlowerControllerflower extends JControllerAdmin { public function getModel($name = 'flowers', $prefix = 'FlowerModel') { $model = parent::getModel($name, $prefix, array('ignore_request' => true)); return $model; } }
Tired to write getItem(), getPagination() and other methods again and again? Windwalker auto loaded them in View object. You can also override default behavior.
protected function prepareData() { // Use default }
public function display($tpl = null) { $this->state = $this->get('State'); $this->items = $this->get('Items'); $this->pagination = $this->get('Pagination'); WeblinksHelper::addSubmenu('flowers'); // Check for errors. if (count($errors = $this->get('Errors'))) { JError::raiseError(500, implode("\n", $errors)); return false; } $this->addToolbar(); $this->sidebar = JHtmlSidebar::render(); parent::display($tpl); }
Setting toolbar in Joomla is very bother, Windwalker prepared a set of default buttons. You can just configure them to decide which should show on page. Also, the ACL has auto handled.
protected function configureToolbar($buttonSet = array(), $canDo = null) { // Get default button set. $buttonSet = parent::configureToolbar($buttonSet, $canDo); // In debug mode, we remove trash button but use delete button instead. if (JDEBUG) { $buttonSet['trash']['access'] = false; $buttonSet['delete']['access'] = true; } return $buttonSet; }
protected function addToolbar() { require_once JPATH_COMPONENT . '/helpers/flower.php'; $state = $this->get('State'); $canDo = JHelperContent::getActions('com_weblinks', 'category', $state->get('filter.category_id')); $user = JFactory::getUser(); $bar = JToolBar::getInstance('toolbar'); JToolbarHelper::title(JText::_('COM_WEBLINKS_MANAGER_WEBLINKS'), 'link weblinks'); if (count($user->getAuthorisedCategories('com_weblinks', 'core.create')) > 0) { JToolbarHelper::addNew('weblink.add'); } if ($canDo->get('core.edit')) { JToolbarHelper::editList('weblink.edit'); } if ($canDo->get('core.edit.state')) { JToolbarHelper::publish('weblinks.publish', 'JTOOLBAR_PUBLISH', true); JToolbarHelper::unpublish('weblinks.unpublish', 'JTOOLBAR_UNPUBLISH', true); JToolbarHelper::archiveList('weblinks.archive'); JToolbarHelper::checkin('weblinks.checkin'); } if ($state->get('filter.state') == -2 && $canDo->get('core.delete')) { JToolbarHelper::deleteList('', 'weblinks.delete', 'JTOOLBAR_EMPTY_TRASH'); } elseif ($canDo->get('core.edit.state')) { JToolbarHelper::trash('weblinks.trash'); } // Add a batch button if ($user->authorise('core.create', 'com_weblinks') && $user->authorise('core.edit', 'com_weblinks') && $user->authorise('core.edit.state', 'com_weblinks')) { JHtml::_('bootstrap.modal', 'collapseModal'); $title = JText::_('JTOOLBAR_BATCH'); // Instantiate a new JLayoutFile instance and render the batch button $layout = new JLayoutFile('joomla.toolbar.batch'); $dhtml = $layout->render(array('title' => $title)); $bar->appendButton('Custom', $dhtml, 'batch'); } if ($user->authorise('core.admin', 'com_weblinks')) { JToolbarHelper::preferences('com_weblinks'); } JToolbarHelper::help('JHELP_COMPONENTS_WEBLINKS_LINKS'); }
Windwalekr Grid system is very smart, you can configure search, filter and batch in XML files. Save you from the query building hell.
<form> <!-- Batch --> <fields name="batch"> <field name="access" type="accesslevel" label="JLIB_HTML_BATCH_ACCESS_LABEL" description="JLIB_HTML_BATCH_ACCESS_LABEL_DESC" labelclass="control-label" class="input-xlarge inputbox" > <option>JLIB_HTML_BATCH_NOCHANGE</option> </field> <field name="language" type="contentlanguage" label="JLIB_HTML_BATCH_LANGUAGE_LABEL" description="JLIB_HTML_BATCH_LANGUAGE_LABEL_DESC" labelclass="control-label" class="input-xlarge inputbox" > <option>JLIB_HTML_BATCH_LANGUAGE_NOCHANGE</option> </field> <field name="created_by" type="winduser" label="JAUTHOR" description="JLIB_HTML_BATCH_USER_LABEL_DESC" labelclass="control-label" class="input-xlarge inputbox" > <option>JSELECT</option> </field> <field name="catid" type="category" label="JLIB_HTML_BATCH_MENU_LABEL" description="" extension="com_flower" labelclass="control-label" class="input-xlarge inputbox" action="true" > <option>JOPTION_SELECT_CATEGORY</option> </field> <field name="task" type="radio" label="JLIB_RULES_ACTION" description="" labelclass="control-label" class="combo btn-group" default="sakuras.batch.move" > <option value="sakuras.batch.move">JLIB_HTML_BATCH_MOVE</option> <option value="sakuras.batch.copy">JLIB_HTML_BATCH_COPY</option> </field> </fields> </form>
// No, you have to use php to write Batch in controller yourself
Windwalekr provides a powerful QueryHelper and FilterHelper, you don't need to configure so much terrible things in ModelList.
class FlowerModelSakuras extends ListModel { /** * Some default filter fields will be merged to * the auto-generated fields */ protected $filterFields = array('sakura.start_date'); protected function configureTables() { $queryHelper = $this->getContainer()->get('model.sakuras.helper.query', Container::FORCE_NEW); $queryHelper->addTable('sakura', '#__flower_sakuras') ->addTable('category', '#__categories', 'sakura.catid = category.id') ->addTable('user', '#__users', 'sakura.created_by = user.id') ->addTable('viewlevel', '#__viewlevels', 'sakura.access = viewlevel.id') ->addTable('lang', '#__languages', 'sakura.language = lang.lang_code'); // Auto generate filter fields, you can also write it manually $this->filterFields = array_merge( $this->filterFields, $queryHelper->getFilterFields() ); } protected function populateState($ordering = 'id', $direction = 'ASC') { // All filter and search will be handled by parent. parent::populateState($ordering, $direction); } protected function processFilters(\JDatabaseQuery $query, $filters = array()) { if (!isset($filters['sakura.state']) && property_exists($this->getTable(), 'state')) { $query->where($query->quoteName('sakura.state') . ' >= 0'); } return parent::processFilters($query, $filters); } protected function configureFilters($filterHelper) { // Override filter behavior here } protected function configureSearches($searchHelper) { // Override search behavior here } }
class FlowerModelSakuras extends JModelList { public function __construct($config = array()) { if (empty($config['filter_fields'])) { $config['filter_fields'] = array( 'id', 'a.id', 'title', 'a.title', 'alias', 'a.alias', 'checked_out', 'a.checked_out', 'checked_out_time', 'a.checked_out_time', 'catid', 'a.catid', 'category_title', 'state', 'a.state', 'access', 'a.access', 'access_level', 'created', 'a.created', 'created_by', 'a.created_by', 'ordering', 'a.ordering', 'featured', 'a.featured', 'language', 'a.language', 'hits', 'a.hits', 'publish_up', 'a.publish_up', 'publish_down', 'a.publish_down', 'url', 'a.url', ); } parent::__construct($config); } protected function populateState($ordering = null, $direction = null) { $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); $this->setState('filter.search', $search); $accessId = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', null, 'int'); $this->setState('filter.access', $accessId); $published = $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'string'); $this->setState('filter.state', $published); $categoryId = $this->getUserStateFromRequest($this->context . '.filter.category_id', 'filter_category_id', ''); $this->setState('filter.category_id', $categoryId); $language = $this->getUserStateFromRequest($this->context . '.filter.language', 'filter_language', ''); $this->setState('filter.language', $language); $tag = $this->getUserStateFromRequest($this->context . '.filter.tag', 'filter_tag', ''); $this->setState('filter.tag', $tag); $params = JComponentHelper::getParams('com_Sakuras'); $this->setState('params', $params); parent::populateState('a.title', 'asc'); } protected function getListQuery() { // Create a new query object. $db = $this->getDbo(); $query = $db->getQuery(true); $user = JFactory::getUser(); $query->select( 'a.id, a.title, a.alias, a.checked_out, a.checked_out_time, a.catid,' . 'a.hits,' . 'a.state, a.access, a.ordering,' . 'a.language, a.publish_up, a.publish_down' ); $query->from($db->quoteName('#__flower_sakuras') . ' AS a'); $query->select('l.title AS language_title') ->join('LEFT', $db->quoteName('#__languages') . ' AS l ON l.lang_code = a.language') ->select('uc.name AS editor') ->join('LEFT', '#__users AS uc ON uc.id=a.checked_out') ->select('ag.title AS access_level') ->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access') ->select('c.title AS category_title') ->join('LEFT', '#__categories AS c ON c.id = a.catid'); if ($access = $this->getState('filter.access')) { $query->where('a.access = ' . (int) $access); } if (!$user->authorise('core.admin')) { $groups = implode(',', $user->getAuthorisedViewLevels()); $query->where('a.access IN (' . $groups . ')'); } $published = $this->getState('filter.state'); if (is_numeric($published)) { $query->where('a.state = ' . (int) $published); } elseif ($published === '') { $query->where('(a.state IN (0, 1))'); } $categoryId = $this->getState('filter.category_id'); if (is_numeric($categoryId)) { $query->where('a.catid = ' . (int) $categoryId); } $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.title LIKE ' . $search . ' OR a.alias LIKE ' . $search . ')'); } } if ($language = $this->getState('filter.language')) { $query->where('a.language = ' . $db->quote($language)); } $orderCol = $this->state->get('list.ordering'); $orderDirn = $this->state->get('list.direction'); if ($orderCol == 'a.ordering' || $orderCol == 'category_title') { $orderCol = 'c.title ' . $orderDirn . ', a.ordering'; } $query->order($db->escape($orderCol . ' ' . $orderDirn)); return $query; } }
$ php composer.phar create-project windwalker/phoenix libraries/windwalker 2.*
This document is for Windwalker Joomla RAD, if you are finding Windwalker PHP framework, please see: Windwalker Framework