English spoken conference
Caution: You are browsing the legacy symfony 1.x part of this website.

Повысьте свою продуктивность

автор: Fabien Potencier; перевод на русский — BRIGADA

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

Ускоряем начало проекта: настройка процесса создания

Благодаря инструменту командной строки symfony, создание нового проекта происходит быстро и легко:

$ php /path/to/symfony generate:project foo --orm=Doctrine

Задача generate:project создаёт заданную по умолчанию структуру каталогов для вашего нового проекта, а также создаёт соответствующие конфигурационные файлы. Затем вы можете использовать другие задачи symfony для создания приложений, установки плагинов, конфигурирования модели и так далее.

Но первые шаги по созданию нового проекта почти всегда одни и те же: вы создаёте главное приложение, устанавливаете какой-то набор плагинов, настраиваете под себя некоторые конфигурационные файлы...

Начиная с symfony 1.3, процесс создания проекта может быть настроен и автоматизирован.

note

Поскольку все задачи symfony являются классами, их можно легко настроить и расширить. Предыдущая фраза не относится только к одной задаче — generate:project, так как на момент выполнения этой задачи проект ещё не существует.

Задача generate:project принимает опцию --installer, через которую задаётся исполняемый во время процесса создания проекта PHP-скрипт:

$ php /path/to/symfony generate:project --installer=/somewhere/my_installer.php

Скрипт /somewhere/my_installer.php выполняется в контексте экземпляра sfGenerateProjectTask, таким образом он имеет доступ к методам задачи через объект $this. Следующие разделы описывают все доступные методы, которые вы можете использовать для настройки процесса создания проекта.

tip

Если в своём php.ini вы включили возможность использования файлов по URL для функции include(), вы можете передавать в качестве установщика его URL (конечно же, следует быть очень осторожным, когда вы делаете это со скриптом, о котором ничего не знаете):

 $ symfony generate:project
 --installer=http://example.com/sf_installer.php

installDir()

Метод installDir() задаёт расположение структуры каталогов (которая состоит из подкаталогов и файлов) создаваемого проекта:

$this->installDir(dirname(__FILE__).'/skeleton');

runTask()

Метод runTask() выполняет задачу. В качестве параметров он принимает имя задачи и строку, представляющую собой передаваемые в задачу аргументы:

$this->runTask('configure:author', "'Fabien Potencier'");

Аргументы также можно передать в массиве:

$this->runTask('configure:author', array('author' => 'Fabien Potencier'));

tip

Сокращённая запись имени задачи также работает:

$this->runTask('cc');

Этот метод можно использовать при установке плагинов:

$this->runTask('plugin:install', 'sfDoctrineGuardPlugin');

Для установки определённой версии плагина необходимо передать соответствующие опции:

$this->runTask('plugin:install', 'sfDoctrineGuardPlugin', array('release' => '10.0.0', 'stability' => 'beta'));

tip

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

$this->reloadTasks();

Если вы создаёте новое приложение и хотите использовать задачи, которые зависят от определённой конфигурации (например, generate:module), вы должны самостоятельно её установить:

$this->setConfiguration($this->createConfiguration('frontend', 'dev'));

Логгеры

Чтобы реализовать взаимодействие с разработчиком, запустившим установочный скрипт, вы можете легко выводить в лог сообщения:

// простой лог
$this->log('какая-нибудь чушь про установку');
 
// лог блока
$this->logBlock('Чумовой Установщик Василия Пупкина', 'ERROR_LARGE');
 
// лог в разделе
$this->logSection('install', 'устанавливаем дикое количество файлов');

Взаимодействие с пользователем

Методы askConfirmation(), askAndValidate() и ask() позволяют вам задавать вопросы и, таким образом, реализовать динамически конфигурируемый процесс установки.

Если вам нужно простое подтверждение, используйте метод askConfirmation():

if (!$this->askConfirmation('Вы действительно хотите запустить этот дикий установщик?'))
{
  $this->logSection('install', 'Вы сделали правильный выбор! :)');
 
  return;
}

Также вы можете задавать пользователю любые вопросы и получать от него строковые ответы с помощью метода ask():

$secret = $this->ask('Укажите уникальную строку для использования в CSRF-защите:');

А ещё вы можете проверять ответы при помощи метода askAndValidate():

$validator = new sfValidatorEmail(array(), array('invalid' => 'хм... кажется вы ввели не адрес email!'));
$email = $this->askAndValidate('Пожалуйста, укажите свой адрес электронной почты:', $validator);

Операции файловой системы

Если вы хотите изменить файловую систему, вы можете получить доступ к symfony-объекту файловой системы:

$this->getFilesystem()->...();

sidebar

Процесс создания песочницы (sandbox)

Песочница symfony — это подготовленный проект с готовой базой данных SQLite. Создать песочницу можно используя её установочный скрипт:

$ php symfony generate:project --installer=/path/to/symfony/data/bin/sandbox_installer.php

Скрипт symfony/data/bin/sandbox_installer.php является готовым примером установщика.

Скрипт установщика — это всего лишь PHP-файл. Посему, вы можете делать что пожелаете. Вместо того, чтобы при создании новых проектов снова и снова запускать определённые задачи, вы можете создать свой собственный скрипт установщика и настраивать процесс установки под себя. Создание нового проекта через скрипт ускоряет выполнение задачи и исключает использование вами одних и тех же действий. А ещё вы можете поделиться вашим скриптом с другими!

tip

В Главе 6 мы используем свой собственный установщик. Его код можно посмотреть в Приложении B.

Разрабатывайте быстрее

И при написании PHP-кода, и при написании задач командной строки, программирование подразумевает ввод больших объёмов кода. Давайте посмотрим, как можно сократить затрачиваемое на это время до минимума.

Подберите себе IDE

Использование интегрированной среды разработки (IDE) позволяет повысить продуктивности не одним способом.

Во-первых, большинство современных IDE поддерживают автозавершение для вводимого PHP-кода. Это означает, что вам необходимо набирать только первые несколько символов имени метода. Это также означает, что даже если вы не помните имя метода, вам всё ещё не нужно переключаться на чтение API, так как IDE может вывести список всех методов текущего объекта.

Во-вторых, некоторые IDE, например PHPEdit и Netbeans, знают о symfony несколько больше, и определённым образом интегрируются с symfony-проектами.

sidebar

Текстовые редакторы

Некоторые пользователи предпочитают в своей программистской работе использовать обыкновенные текстовые редакторы, так как работают они быстрее любой IDE. Безусловно, текстовый редактор обеспечивает меньше возможностей, чем полноценная IDE. Однако большинство популярных редакторов имеют возможность подключения плагинов/дополнений, расширяющих пользовательские возможности при разработке PHP и symfony-проектов.

Например, многие Linux-пользователи предпочитают использовать VIM. Этим пользователям доступно расширение vim-symfony. VIM-symfony — это набор VIM-скриптов, которые интегрируют symfony с их любимым редактором. Используя vim-symfony, можно легко создавать макросы и команды vim для упрощения разработки под symfony. Также, этот набор скриптов содержит набор команд, располагающих некоторые конфигурационные файлы "под кончиками пальцев" и позволяет легко переключаться от действий к шаблонам.

Некоторые пользователи MacOS X используют TextMate. Эти разработчики могут установить пакет, который добавит несколько макросов и ярлыков для повседневных задач.

Использование IDE, которая поддерживает symfony

Некоторые IDE, например PHPEdit 3.4 и NetBeans 6.8, имеют встроенную поддержку symfony, и обеспечивают полноценную интеграцию с этим фреймворком. Посмотрите их документацию для того чтобы узнать больше об этой поддержке и о том, как это может помочь вам вести свои разработки быстрее.

Помощь IDE

Автозавершение в IDE работает только для методов, которые явно определены в коде. Однако, если вы используете "волшебные" методы типа __call() или __get(), у IDE нет возможности показать вам доступные свойства и методы. Хорошая новость — в большинстве случаев, вы можете сами помочь IDE, указав методы и/или свойства в блоке PHPDoc (используя соответствующие комментарии @method и @property).

Предположим, у вас есть класс Message с динамическим свойством (message) и динамическим методом (getMessage()). Следующий код демонстрирует, как IDE сможет узнать о них без какого-либо явного определения в коде:

/**
 * @property clob $message
 *
 * @method clob getMessage() Returns the current message value
 */
class Message
{
  public function __get()
  {
    // ...
  }
 
  public function __call()
  {
    // ...
  }
}

Даже если метод getMessage() не существует, он распознаётся IDE благодаря аннотации @method. То же самое происходит и в случае со свойством message, для которого добавлена аннотация @property.

Эта техника используется задачей doctrine:build-model. Например, Doctrine-класс MailMessage с двумя столбцами (message и priority) выглядит следующим образом:

/**
 * BaseMailMessage
 *
 * This class has been auto-generated by the Doctrine ORM Framework
 *
 * @property clob $message
 * @property integer $priority
 *
 * @method clob        getMessage()  Returns the current record's "message" value
 * @method integer     getPriority() Returns the current record's "priority" value
 * @method MailMessage setMessage()  Sets the current record's "message" value
 * @method MailMessage setPriority() Sets the current record's "priority" value
 *
 * @package    ##PACKAGE##
 * @subpackage ##SUBPACKAGE##
 * @author     ##NAME## <##EMAIL##>
 * @version    SVN: $Id: Builder.php 6508 2009-10-14 06:28:49Z jwage $
 */
abstract class BaseMailMessage extends sfDoctrineRecord
{
    public function setTableDefinition()
    {
        $this->setTableName('mail_message');
        $this->hasColumn('message', 'clob', null, array(
             'type' => 'clob',
             'notnull' => true,
             ));
        $this->hasColumn('priority', 'integer', null, array(
             'type' => 'integer',
             ));
    }
 
    public function setUp()
    {
        parent::setUp();
        $timestampable0 = new Doctrine_Template_Timestampable();
        $this->actAs($timestampable0);
    }
}

Быстрый поиск документации

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

Онлайн-документация по API

Наибыстрейшим способом получения документации о классе или методе является просмотр online-версии API.

Ещё более интересным представляется использование встроенного в API поискового механизма. Он позволяет вам быстро находить класс или метод в несколько нажатий клавиш. После ввода нескольких букв в поисковую строку, открывается список соответствующих вариантов.

Вы можете выполнять поиск, введя только начало имени класса:

Поиск в API

или имени метода:

Поиск в API

или ввести за именем класса :: для получения списка доступных методов:

Поиск в API

или продолжить вводить имя метода:

Поиск в API

Если вы хотите получить список всех классов пакета, просто введите имя этого пакета и отправьте запрос.

Вы можете интегрировать поиск по API в свой браузер. В этом случае вам не придётся вначале переходить на сайт symfony, а затем выполнять поиск. Эта возможность доступна, так как мы обеспечиваем поддержку механизма OpenSearch.

Если вы используете Firefox, механизм поиска API можно автоматически встроить в поисковом меню. Для этого вам потребуется нажать ссылку "API OpenSearch" в соответствующем разделе документации и произойдёт добавление в поисковое меню вашего браузера.

note

Вы можете посмотреть видеоруководство, в котором демонстрируется интеграция поискового механизма в Firefox.

Диаграммы-шпаргалки

Если вы хотите иметь быстрый доступ к информации о главных частях фреймворка, у нас есть коллекция диаграмм-шпаргалок:

note

Некоторые из этих шпаргалок не обновлялись после появления symfony 1.3.

Бумажная документация

Вопросы конфигуририрования наиболее полно освещены в Справочнике по Symfony (Symfony Reference Guide). Это именно та книга, к которой вам стоит обращаться при возникновении вопросов, появляющихся по мере разработки для symfony. Она является наибыстрейшим способом получения всех возможных параметров конфигурации, благодаря подробному оглавлению, списку терминов и определений, перекрёстным ссылкам в главах, таблицам и многому другому.

Вы можете посмотреть эту книгу онлайн, купить отпечатанную копию, или скачать в виде PDF.

Онлайн-инструменты

Как замечено в начале этой главы, symfony предоставляет хороший комплект инструментов, чтобы помочь вам вести свои разработки быстрее. Рано или поздно, вы закончите свой проект и настанет пора развернуть его.

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

Отлаживайте быстрее

Когда в отладочном окружении происходит ошибка, symfony отображает заполненную полезной информацией страницу исключения. Вы можете, например, посмотреть содержимое стека функций и увидеть задействованные файлы. Если вы установите настройку sf_file_link_format в конфигурационном файле settings.yml (см. ниже), вы даже сможете кликать на имена файлов, и соответствующие файлы будут открываться на нужной строке в вашем текстовом редакторе или IDE. Это великолепный пример того, как маленькая функция сохраняет массу вашего времени при отладке.

note

Панели log и view вэб-отладчика также отображают имена файлов (когда включён XDebug), а при установке sf_file_link_format они становятся ещё и кликабельными.

По умолчанию, sf_file_link_format имеет пустое значение, и symfony использует значение xdebug.file_link_format конфигурации PHP если оно существует (установка xdebug.file_link_format в php.ini для большинства версий XDebug добавляет ссылки для имён файлов в трассировке).

Значение sf_file_link_format зависит от вашей IDE и операционной системы. Например, если вы хотите открывать файлы в TextMate, добавьте следующие строки в файле settings.yml:

dev:
  .settings:
    file_link_format: txmt://open?url=file://%f&line=%l

Шаблон %f заменяется symfony на абсолютный путь к файлу, а %l — на номер строки.

Если вы используете VIM, конфигурация более запутанная и описана онлайн для symfony и XDebug.

note

Используйте свой любимый поисковик, чтобы узнать, как конфигурируется конкретно ваша IDE. Вы можете искать конфигурацию sf_file_link_format или xdebug.file_link_format — они работают одинаково.

Тестируйте быстрее

Пишите свои функциональные тесты

Функциональные тесты моделируют взаимодействие с пользователем, что позволяет протестировать интеграцию всех компонентов вашего приложения. Написание функциональных тестов является лёгкой, хотя и трудоёмкой задачей. Поскольку каждый файл функционального теста является сценарием, моделирующим поведение пользователя, который просматривает ваш сайт, и так как просмотр приложения происходит, очевидно, быстрее написания PHP-кода, то что, если вы запишете сессию просмотра сайта и будете иметь возможность конвертировать эту запись в PHP? К счастью, symfony имеет такой плагин. Он называется swFunctionalTestGenerationPlugin, и позволяет вам сгенерировать скелет теста буквально за минуты. Конечно, вам всё ещё надо будет добавить правильных вызовов тестера, но это всё равно экономит вам время.

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

functional_test:
  class: swFilterFunctionalTest

Далее, включите плагин в своём классе ProjectConfiguration:

// config/ProjectConfiguration.class.php
class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
    // ...
 
    $this->enablePlugin('swFunctionalTestGenerationPlugin');
  }
}

Так как плагин использует отладочную вэб-панель в качестве своего главного пользовательского интерфейса, убедитесь что она включена (обычно, панель включена по умолчанию в окружении dev)). Когда всё включено, становится доступно новое меню "Functional Test". В этой панели вы можете начать запись сессии кликом на ссылку "Activate", и сбросить текущую сессию кликом на "Reset". Когда вы закончите, скопируйте код из текстового поля в файл теста и приступайте к его модификации.

Запускайте свои тесты быстрее

Когда у вас есть большой набор тестов, достаточно трудоёмко запускать все тесты при проверке сделанных изменений, особенно если некоторые тесты перестали работать. Каждый раз, когда вы изменяете тест, вам необходимо снова и снова запускать весь комплекс тестов, чтобы гарантировать неповреждённость других тестов. Но до тех пор, пока вы не почините ошибочный тест, запускать другие тесты не требуется. Для ускорения этого процесса задача test:all имеет опцию --only-failed (или -f как сокращённая запись), которая позволяет ускорить задачу путём выполнения только тех тестов, которые провалились при предыдущем запуске:

$ php symfony test:all --only-failed

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