#to avoid trailing slash problem
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
вторник, 25 августа 2009 г.
Symfony: avoid trailing slash problem
понедельник, 24 августа 2009 г.
Symfony: date selector (выбор даты рождения)
Нас не устраивает стандартный выбор даты в виде 3х листбоксов в формате месяц/день/год, да еще и месяцы указаны цифрами, что вызывает массу затруднений.
Мы хотим такой вид:

Решение:
Мы хотим такой вид:

Решение:
public function setup()
{
$years = range(1950, 2000); //Creates array of years between 1950-2000
$years_list = array_combine($years, $years); //Creates new array where key and value are both values from $years list
$this->setWidgets(array(
'id' => new sfWidgetFormInputHidden(),
'city' => new sfWidgetFormInput(),
'birthday' => new sfWidgetFormI18nDate(
array(
'culture' => 'ru',
'format' => '%day%.%month%.%year%',
'years' => $years_list,
),
array()
),
Symfony: sfWidgetFormInputFileEditable IE broken image
Положим, что мы хотим позволить пользователю прикреплять картинку к своему профилю.
Обратившись к JOBEET находим решение - виджет sfWidgetFormInputFileEditable
Используем его в своей форме:
Однако вскоре мы обнаруживаем, что когда пользователь не создает. а редактирует свой профиль, и при этом аватар у него не загружен, в форме появляется битый рисунок и предложение удалить несуществующую картинку:

Решение проблемы:
Ну и заинтересовавшимся для комплекта валидатор:
Обратившись к JOBEET находим решение - виджет sfWidgetFormInputFileEditable
Используем его в своей форме:
$this->setWidgets(array(
'id' => new sfWidgetFormInputHidden(),
...
'avatar' => new sfWidgetFormInputFileEditable(array(
'label' => 'Ваш аватар',
'file_src' => '/uploads/avatars/'.$this->getObject()->getAvatar(),
'is_image' => true,
'edit_mode' => !$this->isNew(),
)),
Однако вскоре мы обнаруживаем, что когда пользователь не создает. а редактирует свой профиль, и при этом аватар у него не загружен, в форме появляется битый рисунок и предложение удалить несуществующую картинку:

Решение проблемы:
'avatar' => new sfWidgetFormInputFileEditable(array(
'label' => 'Avatar for forum, blog, comments, etc...',
'file_src' => '/uploads/avatars/'.$this->getObject()->getAvatar(),
'is_image' => true,
'edit_mode' => ($this->getObject()->getAvatar() OR $this->isNew() ? true: false),
)),
Ну и заинтересовавшимся для комплекта валидатор:
$this->validatorSchema['avatar'] = new sfValidatorFile(array(
'required' => false,
'path' => sfConfig::get('sf_upload_dir').'/avatars',
'mime_types' => 'web_images',
'max_size' => '40960', //(40KB in bytes)
));
понедельник, 18 мая 2009 г.
Symfony: applications as subdomains
Мы хотим иметь такую конструкцию:
Изменяем index.php
Использованные материалы: Dynamically Loading Symfony Applications Via Subdomains
site.com = frontend.php
www.site.com = frontend.php
dev.www.site.com = frontend_dev.php
backend.site.com = backend.php
dev.backend.site.com = backend_dev.php
Изменяем index.php
require_once(dirname(__FILE__).'/../config/ProjectConfiguration.class.php');
// get the domain parts as an array
@list($tld, $domain, $subdomain, $subdomain2) = array_reverse(explode('.', $_SERVER['HTTP_HOST']));
// determine which subdomain we're looking at
$app = ($subdomain == 'webadmin') ? 'backend' : $subdomain;
$app = (empty($app) || $app == 'www' ) ? 'frontend' : $app;
$env = (empty($subdomain2) || $subdomain2 == 'www') ? 'prod' : $subdomain2;
// determine which app to load based on subdomain
if (!is_dir(realpath(dirname(__FILE__).'/..').'/apps/'.$app))
{
$configuration = ProjectConfiguration::getApplicationConfiguration('frontend', 'prod', false);
}
else
{
$configuration = ProjectConfiguration::getApplicationConfiguration($app, $env, false);
}
sfContext::createInstance($configuration)->dispatch();
Использованные материалы: Dynamically Loading Symfony Applications Via Subdomains
четверг, 23 апреля 2009 г.
Symfony: raw query, get years list for active posts
public function executeIndex(sfWebRequest $request)
{
//get years
$connection = Propel::getConnection();
$query = '
SELECT YEAR( %s ) AS myYear
FROM %s
WHERE %s = 1
GROUP BY YEAR( %s )
ORDER BY myYear DESC
';
$query = sprintf($query,
PostPeer::PUBLISHED_AT,
PostPeer::TABLE_NAME,
PostPeer::IS_PUBLISHED,
PostPeer::PUBLISHED_AT
);
$statement = $connection->prepare($query);
$statement->execute();
$years = array();
while($resultset = $statement->fetch(PDO::FETCH_OBJ))
{
$years[] = $resultset->myYear;
}
$this->years = $years;
}
returns array(2009, 2008, 2007...)
понедельник, 13 апреля 2009 г.
Symfony: filter by 2 fields in backend
Простая ситуация: в таблице 2 поля
Нам не важно в заголовке или в описании есть искомое поле, мы хотим в админке сделать фильтрацию по обоим полям. Берем исходник из кэша и модифицируем /backend/modules/post/actions/actions.class.php
sf_post:
_attributes: { phpName: Post }
id: ~
title: { type: varchar(255) }
content: { type: longvarchar }
...
Нам не важно в заголовке или в описании есть искомое поле, мы хотим в админке сделать фильтрацию по обоим полям. Берем исходник из кэша и модифицируем /backend/modules/post/actions/actions.class.php
protected function buildCriteria()
{
$filters = $this->getFilters();
if (is_null($this->filters))
{
$this->filters = $this->configuration->getFilterForm($this->getFilters());
}
$criteria = $this->filters->buildCriteria($this->getFilters());
$this->addSortCriteria($criteria);
$event = $this->dispatcher->filter(new sfEvent($this, 'admin.build_criteria'), $criteria);
$criteria = $event->getReturnValue();
if (!empty($filters['title']['text']))
{
//добавим так же фильтр по полю CONTENT
$c1 = $criteria->getNewCriterion(PostPeer::TITLE, '%'.$filters['title']['text'].'%', Criteria::LIKE);
$c2 = $criteria->getNewCriterion(PostPeer::CONTENT, '%'.$filters['title']['text'].'%', Criteria::LIKE);
$c1->addOr($c2);
$criteria->add($c1);
}
return $criteria;
}
Symfony: add jQuery to helper
Положим что наш самодельный helper должен использовать jQuery, загружен jQuery или нет, мы не знаем, поэтому самое простое в начале скрипта сделать
Но это может привести к многократной загрузке ядра jQuery браузером пользователя.
Что бы избежать этого используем простую проверку.
sfContext::getInstance()->getResponse()->addJavascript('jq/jquery-1.3.2.min.js');Но это может привести к многократной загрузке ядра jQuery браузером пользователя.
Что бы избежать этого используем простую проверку.
$jQueryPath = 'jq/jquery-1.3.2.min.js';
$jsLoaded = sfContext::getInstance()->getResponse()->getJavascripts();
if (!array_key_exists($jQueryPath, $jsLoaded))
{
sfContext::getInstance()->getResponse()->addJavascript($jQueryPath);
}
Подписаться на:
Сообщения (Atom)