Help Авторизация
  

 
Еще не зарегистрированы?
Забыли пароль?
Добавить в избранное

Статьи

Sf
Symfony
Notation
Официальная документация
Notation
Плагины
Notation
Контроллеры
Notation
Базы данных
Php
PHP
Notation
Базы данных
Js
JavaScript
Notation
Разное
Notation
Prototype
Help Специалисты
Men Жариков Дмитрий
Help Консультации
Consult Весь список
Help Каталог работ
Web Специфичное
Web Брачные агенства
Web Каталоги продукции
Web Интернет-магазины
Web Бизнесс порталы
Web Сайты знакомств

sfPropelPagerI18n: расширяем sfPropelPager для поддержки i18n

15746f1e5f805785030204d076e8fcc0 Категория: Контроллеры,
Symfony


О работе "sfPropelPagerI18n: расширяем sfPropelPager для поддержки i18n"

sfPropelPagerI18n: расширяем sfPropelPager для поддержки i18n

Posted By ingvar On 24.08.2008 @ 02:26 In Symfony | 2 Comments

sfPropelPager - это встроенная в Propel функциональность, которая позволяет организовать Пейджинг (Propel Pager), т.е. разбивку на страницы. Работает великолепно, ознакомиться подробнее можно в статье[1] How to paginate a list. Описанные ниже действия проводились на Propel 1.3.

Принцип работы простой, сначала делается запрос на определение количества записей, а далее получаем данные с учетом количества их на странице. Например, имеем Propel ORM объекты News и NewsI18n.

Пример php-кода:

$c = new Criteria();
$c->addDescendingOrderByColumn(NewsPeer::PUBLISHED_AT);
$pager = new sfPropelPager('News', 10);
$pager->setPage($this->getRequestParameter('page', 1));
$pager->setCriteria($c);
$pager->init();
$this->pager = $pager;

Реальные SQL-запросы, что получились в итоге:

Первый запрос: определяем кол-во объектов

SELECT COUNT(*) FROM `news`

Выборка данных

SELECT news.* FROM `news` ORDER BY news.PUBLISHED_AT DESC LIMIT 10;

Вопрос: как заставить sfPropelPager работать с таблицей news_i18n?

Оказывается есть замечательные методы в sfPropelPager: setPeerMethod и setPeerCountMethod, которые можно переназначить. И все вроде должно быть в порядке. Как бы не так. Вот что имеем:

$c = new Criteria();
$c->addDescendingOrderByColumn(NewsPeer::PUBLISHED_AT);
$pager = new sfPropelPager('News', 10);
$pager->setPage($this->getRequestParameter('page', 1));
$pager->setPeerMethod('doSelectWithI18n');
$pager->setCriteria($c);
$pager->init();
$this->pager = $pager;

Журнал запросов:

Первый запрос: определяем кол-во объектов

SELECT COUNT(*) FROM `news`

Выборка данных

SELECT news.*, news_i18n.*, FROM `news`, `news_i18n` WHERE news_i18n.CULTURE='en' AND news.ID=news_i18n.ID
ORDER BY news.PUBLISHED_AT DESC LIMIT 10

После изучения принципов работы sfPropelPager выяснилось следующее: 1) Как в setPeerCountMethod указать правильный метод, которого кстати нет, чтобы выборка количества осуществлялась с учётом языка? 2) Как задать язык для формирования пейджинга? В оригинальном BaseNewsPeer.php метод doSelectWithI18n имеет следующий вид: public static function doSelectWithI18n(Criteria $c, $culture = null, PropelPDO $con = null). Тут есть $culture, а sfPropelPager никак не переназначает значение, значит, срабатывает следующий код:

if ($culture === null)
{
  $culture = sfPropel::getDefaultCulture();
}

В итоге устанавливается язык по умолчанию.

В связи с эти был написан класс, который позволяет решить данную проблему. За основу была взята идея [2] sfPropelPager with I18n и доработана до нормального состояния. Мой класс, который можно [3] скачать sfPropelPagerI18n. Файл надо положить в директорию lib.

<?php
/**
 * This class is the Propel implementation of sfPropelPager.  It interacts with the propel record set and
 * manages criteria.
 *
 * @package    symfony
 * @subpackage propel
 * @author     Igor Brovchenko
 */
class sfPropelPagerI18n extends sfPropelPager
{

  /**
* Constructor.
*
* @param string $class
* @param int $maxPerPage
* @param string $culture
* @param string $joinField default value 'ID'
* @return sfPropelPagerI18n
*/
public function __construct($class, $maxPerPage = 10, $culture = null, $joinField = 'ID')
{
if ($culture === null)
{
  $culture = sfPropel::getDefaultCulture();
}

$this->joinField       = $joinField;
$this->currentCulture  = $culture;

parent::__construct($class, $maxPerPage);

$this->setPeerMethod('doSelectWithI18n');
}

/**
 * Set Criteria for Pager.
*
* @param Criteria $c
*/
public function setCriteriaI18n($c)
{
 $this->criteria = $c;

$this->criteria->addJoin(
  constant($this->getClass() . 'Peer::' . $this->joinField),
  constant($this->getClass() . 'I18nPeer::' . $this->joinField),
  Criteria::INNER_JOIN
);
 $c->add(constant($this->getClass() . 'I18nPeer::CULTURE'), $this->currentCulture);
}

/**
* Returns the result of Pager.
*
*/
public function getResults()
{
  $c = $this->getCriteria();

  return call_user_func(array($this->getClassPeer(), $this->getPeerMethod()), $c, $this->currentCulture);
 }
}

Пример использования sfPropelPagerI18n:

$c = new Criteria();
$c->addDescendingOrderByColumn(NewsPeer::PUBLISHED_AT);
$c->add(NewsPeer::IS_PUBLISHED, true, Criteria::EQUAL);
// Создаем новый Pager вместо старого sfPropelPager, и указываем язык
$pager = new sfPropelPagerI18n('News', 1, 'ru');
$pager->setPage($this->getRequestParameter('page', 1));
// Критерий тоже новый
$pager->setCriteriaI18n($c);
$pager->init();
$this->pager = $pager;

Что же позволяет делать класс sfPropelPagerI18n: 1) Автоматически формируется запрос типа doCount с учётом i18n и всех дополнительных условий Criteria. 2) Указать свою culture или учитывается текущая. 3) Указать поле для связи таблицы, по умолчанию ‘ID’, но его можно переназначить.

Источник



Forum

Оставить отзыв

Рейтинг работы баллов

Голосовать могут только зарегистрированные пользователи

Регистрация

Вернуться