Оригинал: Copyright © 2013 Akeeba Ltd
Перевод: Copyright © 2014 Фёдоров Александр

Содержание данной документации, являюется объектом авторского права и доступно согласно лицензии Joomla! Electronic Documentation License (JEDL), если не указано иное. Вы можете обратиться к разделу частые вопросы по JEDL, чтобы уточнить как вы можете использовать данный материал. Если у вас есть какие-либо вопросы, касающиеся лицензирования данного материала, или вы хотите сообщить о возможном нарушении условий лицензии на материалы данного сайта, пожалуйста, напишите по электронной почте: Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра..

Введение

Что такое FOF

FOF (Framework on Framework) - фреймворк быстрой разработки приложений для Joomla!. В отличие от других подобных решений это не автономный фреймворк, а расширение для Joomla! Он обладает собственными MVC-классами, сохраняя максимальную совместимость с существующим Joomla! API в парадигме MVC. Это означает, что вам не придется переучиваться писать расширения для Joomla!. Вместо этого, вы можете начать продуктивно работать с первого же дня использования этого фреймворка. Мы планируем поддерживать LTS версии Joomla! и не "ломать" обратную совместимость без четкого описания устаревшего функционала и путей миграции.

FOF совместим с технологиями баз данных, используемых в Joomla!: MySQL, SQL Server (включая Windows Azure SQL), PostgreSQL. В большинстве случаев вы можете разработать компонент для одной СУБД и запустить его на другой СУБД с минимальными изменениями (или вообще без них).

В настоящее время FOF используется как в бесплатных, так и в коммерческих компонентах Joomla! все большим числом разработчиков.

Свободное ПО означает сотрудничество

Основное преимущество FOSS (Free and Open Source Software) - это сотрудничество между разработчиками. FOF не является исключением, он существует благодаря разработчикам и для разработчиков Joomla!. Он распространяется бесплатно и обладает всеми возможностями и преимуществами, которые даёт GPL.

Если вы хотите обсудить фреймворк, можете принять участие в списке рассылки Google Groups.

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

Если у вас есть патч, не стесняйтесь создать форк проекта на GitHub и отправить pull request. Не забывайте прикладывать описание желаемого функционала, чтобы я мог быстрее проверить и одобрить ваш код.

Предисловие к настоящей документации

Вместо того, чтобы пытаться полностью заменить собственный API Joomla!, FOF основывается на нем и расширяет его. В итоге это позволяет быстро и безболезненно разрабатывать расширения для Joomla! CMS.

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

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

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

Эта документации не пытается быть полным справочником, эдакой библией разработчика и единственным источником информации по FOF. Наоборот, эта документация призвана стать началом вашего путешествия, быть как бы путеводителем. Самое главное - это само путешествие, разработка собственных расширений, основанных на FOF. В процессе создания вашего расширения вы столкнётесь с множеством вопросов. На большинство из них вы найдёте ответы самостоятельно, на некоторые есть ответы в Wiki, некоторые вопросы вы должны будете задать в списке рассылки. В итоге вы приобретаете новые знания. Если вы узнали и поняли что-то ценное, не забудьте поделиться этим и добавить описание в Wiki. Так мы все станем чуточку богаче и наше путешествие в разработку будет ещё увлекательнее.

Начало работы с FOF

Установка FOF

Можно скачать библиотеку FOF для Joomla! из нашего архива и установить её как и любое другое расширение для Joomla! версии 2.x и выше.

Если есть желание использовать самую последнюю разработческую версию, то можно клонировать доступный только для чтения Git - репозиторий. Проверьте, чтобы скопированная библиотека (напрямую или через символьную ссылку) располагалась в директории сайта libraries/fof. Кроме этого, мы публикуем dev-релизы в нашем специальном репозитории. Это пакеты для установки, но обратите внимание, что они могут быть устаревшими в сравнении с Git - репозиторием, т.к. создаются и публикуются не автоматически.

Использование FOF в вашем расширении

Рекомендуемый метод использования библиотеки FOF в вашем компоненте, модуле или плагине - это использовать нижеприведённый код сразу после объявления defined('_JEXEC') or die() (Joomla! версии 2.x и более поздних):

if (!defined('F0F_INCLUDED'))
{
    include_once JPATH_LIBRARIES . '/f0f/include.php';
}

Или можно уместить всё это в одну строку:

require_once JPATH_LIBRARIES . '/f0f/include.php';

Установка FOF вместе с вашим компонентом

К сожалению, Joomla! на данный момент не позволяет проверять версию установленной библиотеки. Поэтому обязанность проверить версию библиотеки на сайте перед установкой расширения ложится на плечи разработчика. Далее описан пример реализации подобной проверки в компоненте для Joomla! 2.x / 3.x.

Включите директорию под названием fof в ваш инсталляционный файл. Директория должна содержать файлы установочного пакета FOF. Далее в скрипте установки вашего компонента script.mycomponent.php добавьте следующий метод:

/**
 * Check if FOF is already installed and install if not
 *
 * @param   object  $parent  class calling this method
 *
 * @return  array            Array with performed actions summary
 */
private function _installFOF($parent)
{
    $src = $parent->getParent()->getPath('source');

    // Load dependencies
    JLoader::import('joomla.filesystem.file');
    JLoader::import('joomla.utilities.date');
    $source = $src . '/fof';

    if (!defined('JPATH_LIBRARIES'))
    {
        $target = JPATH_ROOT . '/libraries/f0f';
    }
    else
    {
        $target = JPATH_LIBRARIES . '/f0f';
    }
    $haveToInstallFOF = false;

    if (!is_dir($target))
    {
        $haveToInstallFOF = true;
    }
    else
    {
        $fofVersion = array();

        if (file_exists($target . '/version.txt'))
        {
            $rawData = JFile::read($target . '/version.txt');
            $info    = explode("\n", $rawData);
            $fofVersion['installed'] = array(
                'version'   => trim($info[0]),
                'date'      => new JDate(trim($info[1]))
            );
        }
        else
        {
            $fofVersion['installed'] = array(
                'version'   => '0.0',
                'date'      => new JDate('2011-01-01')
            );
        }

        $rawData = JFile::read($source . '/version.txt');
        $info    = explode("\n", $rawData);
        $fofVersion['package'] = array(
            'version'   => trim($info[0]),
            'date'      => new JDate(trim($info[1]))
        );

        $haveToInstallFOF = $fofVersion['package']['date']->toUNIX() > $fofVersion['installed']['date']->toUNIX();
    }

    $installedFOF = false;

    if ($haveToInstallFOF)
    {
        $versionSource = 'package';
        $installer = new JInstaller;
        $installedFOF = $installer->install($source);
    }
    else
    {
        $versionSource = 'installed';
    }

    if (!isset($fofVersion))
    {
        $fofVersion = array();

        if (file_exists($target . '/version.txt'))
        {
            $rawData = JFile::read($target . '/version.txt');
            $info    = explode("\n", $rawData);
            $fofVersion['installed'] = array(
                'version'   => trim($info[0]),
                'date'      => new JDate(trim($info[1]))
            );
        }
        else
        {
            $fofVersion['installed'] = array(
                'version'   => '0.0',
                'date'      => new JDate('2011-01-01')
            );
        }

        $rawData = JFile::read($source . '/version.txt');
        $info    = explode("\n", $rawData);
        $fofVersion['package'] = array(
            'version'   => trim($info[0]),
            'date'      => new JDate(trim($info[1]))
        );
        $versionSource = 'installed';
    }

    if (!($fofVersion[$versionSource]['date'] instanceof JDate))
    {
        $fofVersion[$versionSource]['date'] = new JDate;
    }

    return array(
        'required'  => $haveToInstallFOF,
        'installed' => $installedFOF,
        'version'   => $fofVersion[$versionSource]['version'],
        'date'      => $fofVersion[$versionSource]['date']->format('Y-m-d'),
    );
}

Этот метод надо вызвать из метода postflight(). Например:

/**
 * Method to run after an install/update/uninstall method
 *
 * @param   object  $type    type of change (install, update or discover_install)
 * @param   object  $parent  class calling this method
 *
 * @return void
 */
function postflight($type, $parent)
{
        $fofInstallationStatus = $this->_installFOF($parent);
}

Из-за ошибки в Joomla! 1.6 и далее, манифест компонента должен начинаться с буквы, стоящей в алфавите раньше L, иначе Joomla! решит, что lib_fof.xml это XML манифест вашего расширения и установит FOF вместо самого расширения. Мы настоятельно рекомендуем придерживаться соглашений о наименовании компонента в стиле com_yourComponentName.xml, например com_todo.xml. Патч на исправление этой ошибки есть в трекере Joomla!'s, и надеемся, что со временем эту ошибку исправят.

Начиная с FOF 2.4.0 вы можете создать установочный скрипт расширяющий F0FUtilsInstallscript, а затем поместить последнюю стабильную версию FOF в корневую папку компонента в подпапку fof. F0FUtilsInstallscript установить FOF автоматически. В качестве примера можете посмотреть установочный скрипт компонента Akeeba Backup Core.

Примеры приложений

FOF поставляется с двумя примерами приложений: To-Do и Contact Us. Они были разработаны на разных этапах развития фреймворка, находятся в процессе постоянных улучшений и, конечно, демонстрируют только часть возможностей FOF.

Ещё один хороший способ изучить приёмы FOF - это изучение существующих приложений, разработанных с использованием FOF. Только помните, что мы все живые люди и иногда наш код далёк от идеального ;)

Основные возможности

Соглашения вместо конфигурации (Convention over configuration), Rails-стиль

Вместо того, чтобы реализовывать каждый кусочек компонента в коде, достаточно придерживаться соглашений при наименовании. Например, если компонент называется com_example, то вид foobar будет читать данные из таблицы #__example_foobars, в которой ключевое поле называется example_foobar_id. Большинство рутинных операций с контроллерами, моделями, таблицами и представлениями тоже уже готово, что уменьшает необходимый объём кода.

HMVC уже сегодня, без необходимости переучиваться разработке компонентов

Ведётся много разговоров о необходимости перехода в разработке Joomla! от парадигмы MVC к HMVC. А что, если уже сейчас можно было бы использовать существующие MVC-классы в HMVC-парадигме? Это возможно с FOF! На самом деле было возможно уже с сентября 2011. Для сомневающихся сразу отметим: да, это реальный HMVC, что доказывается существованием класса F0FDispatcher.

Простое повторное использование файлов шаблонов без вызова include().

Часто возникает желание использовать файлы шаблона в различных представлениях. "Традиционный" путь - использовать include() или require(). Это правда означает, что перестанут работать переопределения шаблонов. Теперь нет! Используя метод loadAnyTemplate() класса F0FView можно загружать любой шаблон из пользовательской или административной части любого компонента, конечно же с соблюдением всех переопределений.

Автоматическая загрузка языковых файлов

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

Переопределение медиа файлов (работает также как и переопределение файлов шаблона)

Вы можете переопределить вид шаблона Joomla!, но что насчёт переопределения CSS или Javascript файлов? Обычно это требует "хака ядра", т.е. модификации PHP файлов представления, переводя их в разряд неподдерживаемых, необновляемых и потенциально небезопасных. Хватит! Используя F0FTemplateUtils::addCSS и F0FTemplateUtils::addJS можно загружать собственные CSS и JS-файлы напрямую из файла представления шаблона. Хочется ещё? Разработчикам шаблонов можно разрешить создавать свои переопределения для этих файлов. Достаточно создать папку templates/your_template/media/com_example, чтобы переопределить файлы, обычно расположенные в media/com_example. Всё просто!

Автоматическая генерация JSON и CSV без кодирования (также полезно для веб-сервисов)

Задумались об удалённом API для компонента? FOF делает данные любого вида доступными в JSON-формате, открывая мир новых возможностей для компонентов Joomla! (использование данных в мобильных приложениях, в плитках Metro-стиля Windows 8, расширениях браузера, смешанных веб-приложениях и т.д.).

Автоматическая генерация CSV работает по такому же принципу, только выходные данные идут в формате CSV, подходящем для импорта данных в электронные таблицы и последующего анализа. Заметили, что мы имеем практически готовую реализацию RESTful веб-сервисов?

Представления шаблонов без кода

Не надоело ли вам писать код для каждого представления шаблона (на PHP и HTML) под разные версии Joomla!? Не надоело ли объяснять не разработчикам как не сломать компонент при каждом обновлении? Мы чувствует вашу боль. Именно поэтому FOF поддерживает использование XML в представлениях шаблонов, автоматически генерируя преобразуя их в HTML. Не только формы, всё - списки и единичные записи. Более того, можно выбирать что использовать: традиционные PHP/HTML или XML или их комбинацию в одном и том же представлении.

Разграничение прав, конфигурация приложения и последовательность вызовов в приложении

Начиная с FOF 2.1 последовательность вызовов в приложении, разграничение прав доступа и общую конфигурацию можно определять используя понятные XML-файлы. Никогда раньше не было так просто получить расширение для Joomla! с минимальным количеством PHP-кода.