<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-7017927848434571082</atom:id><lastBuildDate>Sun, 29 Jan 2012 18:13:50 +0000</lastBuildDate><category>embedded</category><category>unique</category><category>subdomain</category><category>propel</category><category>jQuery</category><category>slug</category><category>admin</category><category>icons</category><category>php</category><category>instalation</category><category>ajax</category><category>utf-8</category><category>usefull</category><category>symfony1.2</category><category>date</category><category>application</category><category>validator</category><category>improvements</category><category>query</category><category>filter</category><category>Doctrine</category><category>feedback</category><category>css</category><category>helper</category><category>upload</category><category>log</category><category>forms</category><category>lamp</category><category>htaccess</category><category>symfony</category><category>backend</category><category>ubuntu</category><category>file</category><category>widget</category><category>generator</category><title>nOOb vs Symfony</title><description>"всю жизнь приходится учиться"</description><link>http://vit228.blogspot.com/</link><managingEditor>noreply@blogger.com (Vit228)</managingEditor><generator>Blogger</generator><openSearch:totalResults>39</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/noob_vs_symfony" /><feedburner:info uri="noob_vs_symfony" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-7717609003276228980</guid><pubDate>Thu, 19 Jan 2012 11:56:00 +0000</pubDate><atom:updated>2012-01-19T15:56:01.140+04:00</atom:updated><title>Symfony: short commands in terminal</title><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;h2&gt;Save time and reduce typing errors on working in console&lt;/h2&gt;
&lt;pre&gt;$ nano /usr/local/bin/sf

if [ -z "$1" ]; then
    echo "Missing parameters."
    echo "Usage: $0 --midiff, --mi or --buall"
    exit 0
fi

case "$1" in
    "--cc" )
    php symfony cc
    ;;

    "--midiff" )
    php symfony doctrine:generate-migrations-diff
    ;;

    "--mi" )
    php symfony doctrine:migrate
    ;;

    "--buall" )
    php symfony doctrine:build --all-classes
    ;;

    "--busql" )
    php symfony doctrine:build-sql
    ;;

    "--inssql" )
    php symfony doctrine:insert-sql
    ;;

    "--puass" )
    php symfony plugin:publish-assets
    ;;

esac
exit 0
&lt;/pre&gt;
&lt;h2&gt;
Usage:&lt;/h2&gt;
&lt;p&gt;For example: you need modify your schema, migrate, rebuild all classes and clear cache.&lt;/p&gt;
&lt;pre&gt;$ sf --midiff
$ sf --mi
$ sf --buall
$ sf --cc
&lt;/pre&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-7717609003276228980?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/ounzTJRNnRw/symfony-short-commands-in-terminal.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total><feedburner:origLink>http://vit228.blogspot.com/2012/01/symfony-short-commands-in-terminal.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-7442938231051691627</guid><pubDate>Mon, 21 Feb 2011 23:04:00 +0000</pubDate><atom:updated>2011-02-22T02:08:01.380+03:00</atom:updated><title>Symfony: doctrine custom sql order</title><description>&lt;pre&gt;    $this-&gt;data = Doctrine_Query::create()&lt;br /&gt;            -&gt;from('Category c')&lt;br /&gt;            -&gt;innerJoin('c.Product p')&lt;br /&gt;            -&gt;whereIn('c.slug', array('cpu', 'mainboards', 'ram', 'hdd', 'videocards', 'cases'))&lt;br /&gt;            -&gt;addWhere('p.is_published = ?', true)&lt;br /&gt;            -&gt;addOrderBy('FIELD(c.slug, "cpu", "mainboards", "ram", "hdd", "videocards", "cases")')&lt;br /&gt;            -&gt;execute()&lt;br /&gt;    ;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-7442938231051691627?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/JRsBhDGvp9s/symfony-doctrine-custom-sql-order.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total><feedburner:origLink>http://vit228.blogspot.com/2011/02/symfony-doctrine-custom-sql-order.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-2488848207396729643</guid><pubDate>Sun, 06 Feb 2011 23:20:00 +0000</pubDate><atom:updated>2011-02-07T02:24:08.906+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">file</category><category domain="http://www.blogger.com/atom/ns#">upload</category><title>Symfony: upload file, save original name</title><description>&lt;pre&gt;&lt;br /&gt;public function generatePicFilename($file = null)&lt;br /&gt;{&lt;br /&gt;  if (null === $file) {&lt;br /&gt;    return null;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; return $file-&gt;getOriginalName();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-2488848207396729643?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/U4ae7PNas6o/symfony-upload-file-save-original-name.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total><feedburner:origLink>http://vit228.blogspot.com/2011/02/symfony-upload-file-save-original-name.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-2823226399410992286</guid><pubDate>Wed, 02 Feb 2011 14:41:00 +0000</pubDate><atom:updated>2011-02-02T23:31:29.957+03:00</atom:updated><title>Symfony: Doctrine IndexBy field</title><description>&lt;pre&gt;&lt;br /&gt;    $posts = Doctrine_Query::create()&lt;br /&gt;           -&gt;from('Post p INDEXBY id')&lt;br /&gt;           -&gt;fetchArray()&lt;br /&gt;    ;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;на выходе получаем массив индексированный по реальным значениям id, &lt;br /&gt;а не [0 =&gt; array(), 1 =&gt; array() ... ]&lt;br /&gt;&lt;br /&gt;p.s. спасибо develop7 за наводку&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-2823226399410992286?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/BQL9pxulVFs/symfony-doctrine-indexby-field.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total><feedburner:origLink>http://vit228.blogspot.com/2011/02/symfony-doctrine-indexby-field.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-524805008717040341</guid><pubDate>Sat, 29 Jan 2011 14:51:00 +0000</pubDate><atom:updated>2011-01-29T18:05:11.590+03:00</atom:updated><title>Symfony: doctrine raw sql, get alphabet from i18n model</title><description>Задача: получить алфавит из i18n модели, для разных языков.&lt;br /&gt;Показать только те буквы на которые начинаются имена.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;in actions.class.php&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;div&gt;&lt;div&gt;    $lang = $request-&gt;getParameter('lang', 'ru');&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;    $query = "&lt;/div&gt;&lt;div&gt;      SELECT substring(`name`,1,1) as firstletter&lt;/div&gt;&lt;div&gt;      FROM `xxx_translation` &lt;/div&gt;&lt;div&gt;      WHERE `lang` = '".$lang."' AND&lt;/div&gt;&lt;div&gt;        substring(`name`,1,1) &lt;&gt; ''&lt;/div&gt;&lt;div&gt;      GROUP BY substring(`name`,1,1)&lt;/div&gt;&lt;div&gt;    ";&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    $pdo = Doctrine_Manager::getInstance()-&gt;getCurrentConnection()-&gt;getDbh();&lt;/div&gt;&lt;div&gt;    $stmt = $pdo-&gt;prepare($query);&lt;/div&gt;&lt;div&gt;    $stmt-&gt;execute();&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    $this-&gt;abc = $stmt-&gt;fetchAll(PDO::FETCH_COLUMN, 0);&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;in template&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; &amp;lt;?php if ($abc): ?&amp;gt;&lt;br /&gt;   &amp;lt;ul id="abcList"&amp;gt;&lt;br /&gt;     &amp;lt;?php foreach ($abc as $letter): ?&amp;gt;&lt;br /&gt;       &amp;lt;li&amp;gt;&amp;lt;?php echo link_to($letter, '@user_list?search='.$letter.'&amp;amp;pos=start')?&amp;gt; &amp;lt;/li&amp;gt;&lt;br /&gt;     &amp;lt;?php endforeach; ?&amp;gt;&lt;br /&gt;   &amp;lt;/ul&amp;gt;&lt;br /&gt;   &amp;lt;br clear="all" /&amp;gt;&lt;br /&gt; &amp;lt;?php endif; ?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Css&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ul#abcList li {&lt;br /&gt;  float: left;&lt;br /&gt;  display: inline;&lt;br /&gt;  list-style: none;&lt;br /&gt;  padding: 4px;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-524805008717040341?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/8-qjApNgUHc/symfony-doctrine-raw-sql-get-alphabet.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total><feedburner:origLink>http://vit228.blogspot.com/2011/01/symfony-doctrine-raw-sql-get-alphabet.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-5084790878072002495</guid><pubDate>Mon, 27 Sep 2010 19:32:00 +0000</pubDate><atom:updated>2010-09-27T23:34:10.869+04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">lamp</category><category domain="http://www.blogger.com/atom/ns#">ubuntu</category><title>Ubuntu: install LAMP + APC + phpMyAdmin</title><description>&lt;pre&gt;sudo aptitude install php5 apache2 php-pear php5-xdebug php-apc mysql-server phpmyadmin&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-5084790878072002495?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/jCO_1Tob11c/ubuntu-install-lamp-apc-phpmyadmin.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>4</thr:total><feedburner:origLink>http://vit228.blogspot.com/2010/09/ubuntu-install-lamp-apc-phpmyadmin.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-7607732136998512467</guid><pubDate>Tue, 21 Sep 2010 16:01:00 +0000</pubDate><atom:updated>2010-09-22T01:00:01.691+04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">improvements</category><category domain="http://www.blogger.com/atom/ns#">admin</category><title>Symfony: backend pager</title><description>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_ZX6AxddT59s/TJjYms5aA2I/AAAAAAAAAI8/VWmSAdFkn5U/s1600/backend-pager.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 264px; height: 154px;" src="http://3.bp.blogspot.com/_ZX6AxddT59s/TJjYms5aA2I/AAAAAAAAAI8/VWmSAdFkn5U/s400/backend-pager.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5519399502741111650" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Что бы получше выделить текущую страницу в пейджере далаем небольшие изменения:&lt;br /&gt;&lt;br /&gt;1. CSS&lt;br /&gt;&lt;pre&gt;.currentPage {&lt;br /&gt;  border: 1px solid #ff9900;&lt;br /&gt;  padding: 4px;&lt;br /&gt;  background: #eeeeff;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;2. layout.php&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;jQuery(document).ready(function($){&lt;br /&gt;&lt;br /&gt;  // try to find pager&lt;br /&gt;  pager = $('.sf_admin_pagination').html();&lt;br /&gt;  if (pager) {&lt;br /&gt;    var re = /(\s+)(\d+)(\s)+/;&lt;br /&gt;    var newstr = pager.replace(re, "&lt;span class=\"currentPage\"&gt;$2&lt;/span&gt;");&lt;br /&gt;    $('.sf_admin_pagination').html(newstr);&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-7607732136998512467?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/G0iBnW2Ie-c/symfony-backend-pager.html</link><author>noreply@blogger.com (Vit228)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_ZX6AxddT59s/TJjYms5aA2I/AAAAAAAAAI8/VWmSAdFkn5U/s72-c/backend-pager.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://vit228.blogspot.com/2010/09/symfony-backend-pager.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-2761812065138396772</guid><pubDate>Mon, 14 Dec 2009 14:13:00 +0000</pubDate><atom:updated>2009-12-27T11:19:56.352+03:00</atom:updated><title>Symfony: settings</title><description>Нередко требуется часть настроек из app.yml сделать редактируемыми в backend, напишем простенький класс.&lt;br /&gt;Схема:&lt;br /&gt;&lt;pre&gt;Config:&lt;br /&gt;  tableName: sf_config&lt;br /&gt;  columns:&lt;br /&gt;    id:             { type: integer(4), primary: true, autoincrement: true }&lt;br /&gt;    name:           { type: string(32) }&lt;br /&gt;    value:          { type: string(32) }&lt;br /&gt;    description:    { type: string(1024) }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Класс &lt;span style="font-weight:bold;"&gt;/lib/myConfig.class.php&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;class myConfig extends sfConfig&lt;br /&gt;{&lt;br /&gt;  public static function get($name, $default = null, $description = null)&lt;br /&gt;  {&lt;br /&gt;    if (!sfConfig::get($name))&lt;br /&gt;    {&lt;br /&gt;      $res = Doctrine::getTable('Config')-&gt;findOneByName($name);&lt;br /&gt;      if (!$res)&lt;br /&gt;      {&lt;br /&gt;        $c = new Config();&lt;br /&gt;        $c-&gt;setName($name);&lt;br /&gt;        $c-&gt;setValue($default);&lt;br /&gt;        $c-&gt;setDescription($description);&lt;br /&gt;        $c-&gt;save();&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return (isSet(self::$config[$name]) ? self::$config[$name] : $default);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Данный класс не находя в настройках требуемого параметра, проверяет его наличие в таблице, и в случаее отсутствия добавляет его.&lt;br /&gt;&lt;br /&gt;Фильтр &lt;span style="font-weight:bold;"&gt;/lib/filters/myConfigFilter.class.php&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;class myConfigFilter extends sfFilter&lt;br /&gt;{&lt;br /&gt;  public function execute ($filterChain)&lt;br /&gt;  {&lt;br /&gt;    $configs = Doctrine::getTable('Config')-&gt;findAll();&lt;br /&gt;    foreach ($configs as $config)&lt;br /&gt;    {&lt;br /&gt;      sfConfig::set($config-&gt;getName(), $config-&gt;getValue());&lt;br /&gt;    }&lt;br /&gt;    $filterChain-&gt;execute();&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Фильтр экспортирует из БД настройки в sfConfig.&lt;br /&gt;&lt;br /&gt;Добавляем в &lt;span style="font-weight:bold;"&gt;fontend/config/filters.yml&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;myConfig:&lt;br /&gt;  class:    myConfigFilter&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Используем:&lt;br /&gt;&lt;pre&gt;$postDirName = sfConfig::get('sf_upload_dir').'/'.myConfig::get('posts_dir', 'posts');&lt;br /&gt;'max_size' =&gt; myConfig::get('post_max_icon_size', '10', 'size in KBytes')*1024, //(10*1024=10KB in bytes)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Сгенерируем управление из backend&lt;br /&gt;&lt;pre&gt;$ symfony doctrine:generate-admin backend Config&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Используем &lt;span style="font-weight:bold;"&gt;backend_dev.php/config&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-2761812065138396772?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/kOVwmAAEd98/symfony-settings.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total><feedburner:origLink>http://vit228.blogspot.com/2009/12/symfony-settings.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-245815160841872624</guid><pubDate>Mon, 26 Oct 2009 20:55:00 +0000</pubDate><atom:updated>2010-09-30T00:10:46.530+04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">symfony</category><category domain="http://www.blogger.com/atom/ns#">slug</category><title>Symfony: Doctrine slugify кириллица</title><description>&lt;span style="font-weight:bold;"&gt;/lib/Slugify.class.php&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;class SlugifyClass {&lt;br /&gt;  static function Slugify($title) {&lt;br /&gt;    $gost = array(&lt;br /&gt;     "Є"=&gt;"EH","І"=&gt;"I","і"=&gt;"i","№"=&gt;"#","є"=&gt;"eh",&lt;br /&gt;     "А"=&gt;"A","Б"=&gt;"B","В"=&gt;"V","Г"=&gt;"G","Д"=&gt;"D",&lt;br /&gt;     "Е"=&gt;"E","Ё"=&gt;"JO","Ж"=&gt;"ZH",&lt;br /&gt;     "З"=&gt;"Z","И"=&gt;"I","Й"=&gt;"JJ","К"=&gt;"K","Л"=&gt;"L",&lt;br /&gt;     "М"=&gt;"M","Н"=&gt;"N","О"=&gt;"O","П"=&gt;"P","Р"=&gt;"R",&lt;br /&gt;     "С"=&gt;"S","Т"=&gt;"T","У"=&gt;"U","Ф"=&gt;"F","Х"=&gt;"KH",&lt;br /&gt;     "Ц"=&gt;"C","Ч"=&gt;"CH","Ш"=&gt;"SH","Щ"=&gt;"SHH","Ъ"=&gt;"'",&lt;br /&gt;     "Ы"=&gt;"Y","Ь"=&gt;"","Э"=&gt;"EH","Ю"=&gt;"YU","Я"=&gt;"YA",&lt;br /&gt;     "а"=&gt;"a","б"=&gt;"b","в"=&gt;"v","г"=&gt;"g","д"=&gt;"d",&lt;br /&gt;     "е"=&gt;"e","ё"=&gt;"jo","ж"=&gt;"zh",&lt;br /&gt;     "з"=&gt;"z","и"=&gt;"i","й"=&gt;"jj","к"=&gt;"k","л"=&gt;"l",&lt;br /&gt;     "м"=&gt;"m","н"=&gt;"n","о"=&gt;"o","п"=&gt;"p","р"=&gt;"r",&lt;br /&gt;     "с"=&gt;"s","т"=&gt;"t","у"=&gt;"u","ф"=&gt;"f","х"=&gt;"kh",&lt;br /&gt;     "ц"=&gt;"c","ч"=&gt;"ch","ш"=&gt;"sh","щ"=&gt;"shh","ъ"=&gt;"",&lt;br /&gt;     "ы"=&gt;"y","ь"=&gt;"","э"=&gt;"eh","ю"=&gt;"yu","я"=&gt;"ya","«"=&gt;"","»"=&gt;"","—"=&gt;"-"," "=&gt;"-"&lt;br /&gt;    );&lt;br /&gt;&lt;br /&gt;    $iso = array(&lt;br /&gt;     "Є"=&gt;"YE","І"=&gt;"I","Ѓ"=&gt;"G","і"=&gt;"i","№"=&gt;"#","є"=&gt;"ye","ѓ"=&gt;"g",&lt;br /&gt;     "А"=&gt;"A","Б"=&gt;"B","В"=&gt;"V","Г"=&gt;"G","Д"=&gt;"D",&lt;br /&gt;     "Е"=&gt;"E","Ё"=&gt;"YO","Ж"=&gt;"ZH",&lt;br /&gt;     "З"=&gt;"Z","И"=&gt;"I","Й"=&gt;"J","К"=&gt;"K","Л"=&gt;"L",&lt;br /&gt;     "М"=&gt;"M","Н"=&gt;"N","О"=&gt;"O","П"=&gt;"P","Р"=&gt;"R",&lt;br /&gt;     "С"=&gt;"S","Т"=&gt;"T","У"=&gt;"U","Ф"=&gt;"F","Х"=&gt;"X",&lt;br /&gt;     "Ц"=&gt;"C","Ч"=&gt;"CH","Ш"=&gt;"SH","Щ"=&gt;"SHH","Ъ"=&gt;"'",&lt;br /&gt;     "Ы"=&gt;"Y","Ь"=&gt;"","Э"=&gt;"E","Ю"=&gt;"YU","Я"=&gt;"YA",&lt;br /&gt;     "а"=&gt;"a","б"=&gt;"b","в"=&gt;"v","г"=&gt;"g","д"=&gt;"d",&lt;br /&gt;     "е"=&gt;"e","ё"=&gt;"yo","ж"=&gt;"zh",&lt;br /&gt;     "з"=&gt;"z","и"=&gt;"i","й"=&gt;"j","к"=&gt;"k","л"=&gt;"l",&lt;br /&gt;     "м"=&gt;"m","н"=&gt;"n","о"=&gt;"o","п"=&gt;"p","р"=&gt;"r",&lt;br /&gt;     "с"=&gt;"s","т"=&gt;"t","у"=&gt;"u","ф"=&gt;"f","х"=&gt;"x",&lt;br /&gt;     "ц"=&gt;"c","ч"=&gt;"ch","ш"=&gt;"sh","щ"=&gt;"shh","ъ"=&gt;"",&lt;br /&gt;     "ы"=&gt;"y","ь"=&gt;"","э"=&gt;"e","ю"=&gt;"yu","я"=&gt;"ya","«"=&gt;"","»"=&gt;"","—"=&gt;"-"," "=&gt;"-"&lt;br /&gt;    );&lt;br /&gt;&lt;br /&gt;    $rtl_standard = sfConfig::get('rtl_standard', 'gost') ;&lt;br /&gt;&lt;br /&gt;    //to lower case&lt;br /&gt;&lt;br /&gt;    $name = mb_strtolower($name, 'UTF-8');&lt;br /&gt;&lt;br /&gt;    switch ($rtl_standard) {&lt;br /&gt;      case 'off':&lt;br /&gt;          return $title;&lt;br /&gt;      case 'gost':&lt;br /&gt;          return trim(strtr($title, $gost), '-');&lt;br /&gt;      default:&lt;br /&gt;          return trim(strtr($title, $iso), '-');&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Использование&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Post:&lt;br /&gt;  actAs:&lt;br /&gt;    Timestampable: ~&lt;br /&gt;    Taggable: ~&lt;br /&gt;    Sluggable:&lt;br /&gt;      unique: true&lt;br /&gt;      fields: [title]&lt;br /&gt;      canUpdate: true&lt;br /&gt;      builder: [SlugifyClass, Slugify]&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-245815160841872624?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/5p-OhuLslr0/symfony-doctrine-slugify.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>5</thr:total><feedburner:origLink>http://vit228.blogspot.com/2009/10/symfony-doctrine-slugify.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-8282527422476229929</guid><pubDate>Tue, 29 Sep 2009 18:01:00 +0000</pubDate><atom:updated>2009-09-29T22:07:50.095+04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">symfony</category><category domain="http://www.blogger.com/atom/ns#">Doctrine</category><title>Symfony: Doctrine order by calculated field</title><description>Положим нам нужно вывести 10 наиболее комментируемых постов.&lt;br /&gt;Кусок схемы:&lt;br /&gt;&lt;pre&gt;Post:&lt;br /&gt;  tableName: blog_post&lt;br /&gt;  actAs:&lt;br /&gt;    Timestampable: ~&lt;br /&gt;    Taggable: ~&lt;br /&gt;  columns:&lt;br /&gt;    id:           { type: integer(4), primary: true, autoincrement: true }&lt;br /&gt;    title:        { type: string(255) }&lt;br /&gt;    extract:      { type: string(1024) }&lt;br /&gt;    content:      { type: string(4096) }&lt;br /&gt;    is_published: { type: boolean, default: false }&lt;br /&gt;&lt;br /&gt;Comment:&lt;br /&gt;  tableName: blog_comment&lt;br /&gt;  actAs:&lt;br /&gt;    Timestampable: ~&lt;br /&gt;  columns:&lt;br /&gt;    id:           { type: integer(4), primary: true, autoincrement: true }&lt;br /&gt;    post_id:      { type: integer(4), notnull: true }&lt;br /&gt;    name:         { type: string(100) }&lt;br /&gt;    email:        { type: string(100) }&lt;br /&gt;    content:      { type: string(4096) }&lt;br /&gt;    subscribe:    { type: boolean, default: false }&lt;br /&gt;  relations:&lt;br /&gt;    Post:&lt;br /&gt;      class: Post&lt;br /&gt;      local: post_id&lt;br /&gt;      foreign: id&lt;br /&gt;      foreignAlias: PostComments&lt;br /&gt;      type: one&lt;br /&gt;      foreignType: many&lt;br /&gt;      onDelete: CASCADE&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Получим популярные посты одним запросом:&lt;br /&gt;&lt;pre&gt;  public function executeGetMostCommentedBlogPosts()&lt;br /&gt;  {&lt;br /&gt;    $q = Doctrine_Query::create()&lt;br /&gt;      -&gt;select('p.*')&lt;br /&gt;      -&gt;addSelect('(SELECT count(*) FROM PostComments pc WHERE pc.post_id = p.id) as comments_count')&lt;br /&gt;      -&gt;from('Post p')&lt;br /&gt;      -&gt;where('p.is_published', true)&lt;br /&gt;      -&gt;orderBy('comments_count DESC')&lt;br /&gt;      -&gt;addOrderBy('d.created_at DESC')&lt;br /&gt;      -&gt;limit(10);&lt;br /&gt;&lt;br /&gt;    $this-&gt;posts = $q-&gt;execute();&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-8282527422476229929?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/Clkfxb35Mzw/symfony-doctrine-order-by-calculated.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>1</thr:total><feedburner:origLink>http://vit228.blogspot.com/2009/09/symfony-doctrine-order-by-calculated.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-8944666059630867529</guid><pubDate>Tue, 25 Aug 2009 10:12:00 +0000</pubDate><atom:updated>2009-08-25T14:29:01.583+04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">symfony</category><category domain="http://www.blogger.com/atom/ns#">htaccess</category><title>Symfony: avoid trailing slash problem</title><description>&lt;pre&gt;&lt;br /&gt;  #to avoid trailing slash problem&lt;br /&gt;  RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-8944666059630867529?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/kA43Ka89VZo/symfony-avoid-trailing-slash-problem.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>1</thr:total><feedburner:origLink>http://vit228.blogspot.com/2009/08/symfony-avoid-trailing-slash-problem.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-3682889818505508845</guid><pubDate>Sun, 23 Aug 2009 21:12:00 +0000</pubDate><atom:updated>2009-08-24T02:13:27.758+04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">symfony</category><category domain="http://www.blogger.com/atom/ns#">date</category><title>Symfony: date selector (выбор даты рождения)</title><description>Нас не устраивает стандартный выбор даты в виде 3х листбоксов в формате месяц/день/год, да еще и месяцы указаны цифрами, что вызывает массу затруднений.&lt;br /&gt;Мы хотим такой вид:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_ZX6AxddT59s/SpGxgxRxleI/AAAAAAAAAF8/msFvMD2NppM/s1600-h/birth-date.gif"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 333px; height: 118px;" src="http://4.bp.blogspot.com/_ZX6AxddT59s/SpGxgxRxleI/AAAAAAAAAF8/msFvMD2NppM/s400/birth-date.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5373271006971532770" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Решение:&lt;br /&gt;&lt;pre&gt;  public function setup()&lt;br /&gt;  {&lt;br /&gt;    $years = range(1950, 2000); //Creates array of years between 1950-2000&lt;br /&gt;    $years_list = array_combine($years, $years); //Creates new array where key and value are both values from $years list&lt;br /&gt;&lt;br /&gt;    $this-&gt;setWidgets(array(&lt;br /&gt;      'id'           =&gt; new sfWidgetFormInputHidden(),&lt;br /&gt;      'city'         =&gt; new sfWidgetFormInput(),&lt;br /&gt;      'birthday'     =&gt; new sfWidgetFormI18nDate(&lt;br /&gt;        array(&lt;br /&gt;          'culture' =&gt; 'ru',&lt;br /&gt;          'format'  =&gt; '%day%.%month%.%year%',&lt;br /&gt;          'years'   =&gt; $years_list,&lt;br /&gt;        ),&lt;br /&gt;        array()&lt;br /&gt;      ),&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-3682889818505508845?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/e5bOrIVJ3v4/symfony.html</link><author>noreply@blogger.com (Vit228)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_ZX6AxddT59s/SpGxgxRxleI/AAAAAAAAAF8/msFvMD2NppM/s72-c/birth-date.gif" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://vit228.blogspot.com/2009/08/symfony.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-3413639722777377931</guid><pubDate>Sun, 23 Aug 2009 20:48:00 +0000</pubDate><atom:updated>2009-08-24T02:05:45.373+04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">symfony</category><category domain="http://www.blogger.com/atom/ns#">widget</category><category domain="http://www.blogger.com/atom/ns#">upload</category><title>Symfony: sfWidgetFormInputFileEditable IE broken image</title><description>Положим, что мы хотим позволить пользователю прикреплять картинку к своему профилю.&lt;br /&gt;Обратившись к JOBEET находим решение - виджет &lt;span style="font-weight: bold;"&gt;sfWidgetFormInputFileEditable&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Используем его в своей форме:&lt;br /&gt;&lt;pre&gt;    &lt;br /&gt;$this-&gt;setWidgets(array(&lt;br /&gt;  'id'           =&gt; new sfWidgetFormInputHidden(),&lt;br /&gt;  ...&lt;br /&gt;  'avatar'       =&gt; new sfWidgetFormInputFileEditable(array(&lt;br /&gt;    'label'     =&gt; 'Ваш аватар',&lt;br /&gt;    'file_src'  =&gt; '/uploads/avatars/'.$this-&gt;getObject()-&gt;getAvatar(),&lt;br /&gt;    'is_image'  =&gt; true,&lt;br /&gt;    'edit_mode' =&gt; !$this-&gt;isNew(),&lt;br /&gt;  )),&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Однако вскоре мы обнаруживаем, что когда пользователь не создает. а редактирует свой профиль, и при этом аватар у него не загружен, в форме появляется битый рисунок и предложение удалить несуществующую картинку:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_ZX6AxddT59s/SpGtnl8OTBI/AAAAAAAAAF0/TFAsgeFJRWs/s1600-h/brocken-image.gif"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 333px; height: 118px;" src="http://4.bp.blogspot.com/_ZX6AxddT59s/SpGtnl8OTBI/AAAAAAAAAF0/TFAsgeFJRWs/s400/brocken-image.gif" alt="" id="BLOGGER_PHOTO_ID_5373266726140922898" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Решение проблемы:&lt;br /&gt;&lt;pre&gt;   'avatar'       =&gt; new sfWidgetFormInputFileEditable(array(&lt;br /&gt;     'label'     =&gt; 'Avatar for forum, blog, comments, etc...',&lt;br /&gt;     'file_src'  =&gt; '/uploads/avatars/'.$this-&gt;getObject()-&gt;getAvatar(),&lt;br /&gt;     'is_image'  =&gt; true,&lt;br /&gt;     &lt;span style="font-weight: bold;"&gt;'edit_mode' =&gt; ($this-&gt;getObject()-&gt;getAvatar() OR $this-&gt;isNew() ? true: false),&lt;/span&gt;&lt;br /&gt;   )),&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ну и заинтересовавшимся для комплекта валидатор:&lt;br /&gt;&lt;pre&gt;    $this-&gt;validatorSchema['avatar'] = new sfValidatorFile(array(&lt;br /&gt;      'required'   =&gt; false,&lt;br /&gt;      'path'       =&gt; sfConfig::get('sf_upload_dir').'/avatars',&lt;br /&gt;      'mime_types' =&gt; 'web_images',&lt;br /&gt;      'max_size' =&gt; '40960', //(40KB in bytes)&lt;br /&gt;    ));&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-3413639722777377931?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/5e0BV_YvWZI/symfony-sfwidgetforminputfileeditable.html</link><author>noreply@blogger.com (Vit228)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_ZX6AxddT59s/SpGtnl8OTBI/AAAAAAAAAF0/TFAsgeFJRWs/s72-c/brocken-image.gif" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://vit228.blogspot.com/2009/08/symfony-sfwidgetforminputfileeditable.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-6421500947724432661</guid><pubDate>Mon, 18 May 2009 10:54:00 +0000</pubDate><atom:updated>2009-05-18T15:04:16.992+04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">symfony</category><category domain="http://www.blogger.com/atom/ns#">application</category><category domain="http://www.blogger.com/atom/ns#">subdomain</category><title>Symfony: applications as subdomains</title><description>Мы хотим иметь такую конструкцию:&lt;br /&gt;&lt;pre&gt;site.com             = frontend.php&lt;br /&gt;www.site.com         = frontend.php&lt;br /&gt;dev.www.site.com     = frontend_dev.php&lt;br /&gt;backend.site.com     = backend.php&lt;br /&gt;dev.backend.site.com = backend_dev.php&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Изменяем index.php&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;require_once(dirname(__FILE__).'/../config/ProjectConfiguration.class.php');&lt;br /&gt;&lt;br /&gt;// get the domain parts as an array&lt;br /&gt;@list($tld, $domain, $subdomain, $subdomain2) = array_reverse(explode('.', $_SERVER['HTTP_HOST']));&lt;br /&gt;&lt;br /&gt;// determine which subdomain we're looking at&lt;br /&gt;$app = ($subdomain == 'webadmin') ? 'backend' : $subdomain;&lt;br /&gt;$app = (empty($app) || $app == 'www' ) ? 'frontend' : $app;&lt;br /&gt;$env = (empty($subdomain2) || $subdomain2 == 'www') ? 'prod' : $subdomain2;&lt;br /&gt;&lt;br /&gt;// determine which app to load based on subdomain&lt;br /&gt;if (!is_dir(realpath(dirname(__FILE__).'/..').'/apps/'.$app))&lt;br /&gt;{&lt;br /&gt; $configuration = ProjectConfiguration::getApplicationConfiguration('frontend', 'prod', false);&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt; $configuration = ProjectConfiguration::getApplicationConfiguration($app, $env, false);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sfContext::createInstance($configuration)-&gt;dispatch();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Использованные материалы: &lt;a href="http://blog.mirthlab.com/2008/03/04/dynamically-loading-symfony-applications-via-subdomains/"&gt;Dynamically Loading Symfony Applications Via Subdomains&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-6421500947724432661?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/stq2I3CGJow/symfony-applications-as-subdomains.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total><feedburner:origLink>http://vit228.blogspot.com/2009/05/symfony-applications-as-subdomains.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-8630462305025573528</guid><pubDate>Thu, 23 Apr 2009 12:32:00 +0000</pubDate><atom:updated>2009-04-23T16:36:14.591+04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">symfony</category><category domain="http://www.blogger.com/atom/ns#">propel</category><category domain="http://www.blogger.com/atom/ns#">query</category><title>Symfony: raw query, get years list for active posts</title><description>&lt;pre&gt;public function executeIndex(sfWebRequest $request)&lt;br /&gt;  {&lt;br /&gt;    //get years&lt;br /&gt;   $connection = Propel::getConnection();&lt;br /&gt;   $query = '&lt;br /&gt;     SELECT YEAR( %s ) AS myYear&lt;br /&gt;     FROM %s&lt;br /&gt;     WHERE %s = 1&lt;br /&gt;     GROUP BY YEAR( %s )&lt;br /&gt;     ORDER BY myYear DESC&lt;br /&gt;   ';&lt;br /&gt;&lt;br /&gt;   $query = sprintf($query,&lt;br /&gt;     PostPeer::PUBLISHED_AT,&lt;br /&gt;     PostPeer::TABLE_NAME,&lt;br /&gt;     PostPeer::IS_PUBLISHED,&lt;br /&gt;     PostPeer::PUBLISHED_AT&lt;br /&gt;   );&lt;br /&gt;   $statement = $connection-&gt;prepare($query);&lt;br /&gt;   $statement-&gt;execute();&lt;br /&gt;   $years = array();&lt;br /&gt;   while($resultset = $statement-&gt;fetch(PDO::FETCH_OBJ))&lt;br /&gt;   {&lt;br /&gt;     $years[] = $resultset-&gt;myYear;&lt;br /&gt;   }&lt;br /&gt;   $this-&gt;years = $years;&lt;br /&gt;  }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;returns array(2009, 2008, 2007...)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-8630462305025573528?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/lbyv-CrwA7g/symfony-raw-query-get-years-list-for.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>2</thr:total><feedburner:origLink>http://vit228.blogspot.com/2009/04/symfony-raw-query-get-years-list-for.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-2876753764335323880</guid><pubDate>Mon, 13 Apr 2009 11:34:00 +0000</pubDate><atom:updated>2009-04-13T15:44:59.402+04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">symfony</category><category domain="http://www.blogger.com/atom/ns#">filter</category><category domain="http://www.blogger.com/atom/ns#">backend</category><title>Symfony: filter by 2 fields in backend</title><description>Простая ситуация: в таблице 2 поля&lt;br /&gt;&lt;pre&gt;  sf_post:&lt;br /&gt;   _attributes:  { phpName: Post }&lt;br /&gt;   id:           ~&lt;br /&gt;   title:        { type: varchar(255) }&lt;br /&gt;   content:      { type: longvarchar }&lt;br /&gt;   ...&lt;/pre&gt;&lt;br /&gt;Нам не важно в заголовке или в описании есть искомое поле, мы хотим в админке сделать фильтрацию по обоим полям. Берем исходник из кэша и модифицируем /backend/modules/post/actions/actions.class.php&lt;br /&gt;&lt;pre&gt;  protected function buildCriteria()&lt;br /&gt; {&lt;br /&gt;   $filters = $this-&gt;getFilters();&lt;br /&gt;   if (is_null($this-&gt;filters))&lt;br /&gt;   {&lt;br /&gt;     $this-&gt;filters = $this-&gt;configuration-&gt;getFilterForm($this-&gt;getFilters());&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   $criteria = $this-&gt;filters-&gt;buildCriteria($this-&gt;getFilters());&lt;br /&gt;&lt;br /&gt;   $this-&gt;addSortCriteria($criteria);&lt;br /&gt;&lt;br /&gt;   $event = $this-&gt;dispatcher-&gt;filter(new sfEvent($this, 'admin.build_criteria'), $criteria);&lt;br /&gt;   $criteria = $event-&gt;getReturnValue();&lt;br /&gt;&lt;br /&gt;   if (!empty($filters['title']['text']))&lt;br /&gt;   {&lt;br /&gt;     //добавим так же фильтр по полю CONTENT&lt;br /&gt;     $c1 = $criteria-&gt;getNewCriterion(PostPeer::TITLE, '%'.$filters['title']['text'].'%', Criteria::LIKE);&lt;br /&gt;     $c2 = $criteria-&gt;getNewCriterion(PostPeer::CONTENT, '%'.$filters['title']['text'].'%', Criteria::LIKE);&lt;br /&gt;     $c1-&gt;addOr($c2);&lt;br /&gt;     $criteria-&gt;add($c1);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return $criteria;&lt;br /&gt; }&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-2876753764335323880?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/aWuMdgFScBo/symfony-filter-by-2-fields-in-backend.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>1</thr:total><feedburner:origLink>http://vit228.blogspot.com/2009/04/symfony-filter-by-2-fields-in-backend.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-2710493123584631849</guid><pubDate>Mon, 13 Apr 2009 10:40:00 +0000</pubDate><atom:updated>2009-04-13T14:47:58.715+04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">helper</category><category domain="http://www.blogger.com/atom/ns#">symfony1.2</category><category domain="http://www.blogger.com/atom/ns#">jQuery</category><title>Symfony: add jQuery to helper</title><description>Положим что наш самодельный helper должен использовать jQuery, загружен jQuery или нет, мы не знаем, поэтому самое простое в начале скрипта сделать&lt;br /&gt;&lt;pre&gt;sfContext::getInstance()-&gt;getResponse()-&gt;addJavascript('jq/jquery-1.3.2.min.js');&lt;/pre&gt;&lt;br /&gt;Но это может привести к многократной загрузке ядра jQuery браузером пользователя.&lt;br /&gt;Что бы избежать этого используем простую проверку.&lt;br /&gt;&lt;pre&gt;  $jQueryPath = 'jq/jquery-1.3.2.min.js';&lt;br /&gt;  $jsLoaded = sfContext::getInstance()-&gt;getResponse()-&gt;getJavascripts();&lt;br /&gt;  if (!array_key_exists($jQueryPath, $jsLoaded))&lt;br /&gt;  {&lt;br /&gt;    sfContext::getInstance()-&gt;getResponse()-&gt;addJavascript($jQueryPath);&lt;br /&gt;  }&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-2710493123584631849?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/dqcZVfruQnI/symfony-add-jquery-to-helper.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total><feedburner:origLink>http://vit228.blogspot.com/2009/04/symfony-add-jquery-to-helper.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-167587719925157414</guid><pubDate>Wed, 08 Apr 2009 16:13:00 +0000</pubDate><atom:updated>2009-04-08T20:19:12.209+04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">usefull</category><category domain="http://www.blogger.com/atom/ns#">utf-8</category><category domain="http://www.blogger.com/atom/ns#">php</category><title>PHP substr + utf-8</title><description>Положим нам надо в списке показывать кусок сообщения длиной не более 100символов, если сообщение больше 100символов, в конце добавить троеточие.&lt;br /&gt;В кодировке UTF простое обрезание строки &lt;span style="font-weight: bold;"&gt;substr($str, 0, 100)&lt;/span&gt;, приводит к появлению нераспознанных символов. Нам помогут функции &lt;span style="font-weight: bold;"&gt;mb_&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;public function getSubContent()&lt;br /&gt;{&lt;br /&gt;  $str = strip_tags($this-&gt;getContent());&lt;br /&gt;  return mb_substr($str, 0, 100, 'utf-8').&lt;br /&gt;    (mb_strlen($str, 'utf-8') &gt; 100 ? '...' : '');&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-167587719925157414?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/QrpiYL0wAQU/php-substr-utf-8.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>5</thr:total><feedburner:origLink>http://vit228.blogspot.com/2009/04/php-substr-utf-8.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-120520384967509521</guid><pubDate>Tue, 07 Apr 2009 20:26:00 +0000</pubDate><atom:updated>2009-10-31T23:17:17.541+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">symfony</category><category domain="http://www.blogger.com/atom/ns#">admin</category><category domain="http://www.blogger.com/atom/ns#">forms</category><category domain="http://www.blogger.com/atom/ns#">embedded</category><title>Symfony 1.2 tabular(embedded) subforms</title><description>Довольно часто при редактировании требуется вывести N дочерних записей в виде таблицы.&lt;br /&gt;К сожалению стандартными средствами Symfony этого сделать не получилось, в первую очередь из за того, что Symfony в каждой строке оставляет место для сообщений об ошибках валидации.&lt;br /&gt;Постараемся с минимумом усилий сделать таблицу с подчиненными записями.&lt;br /&gt;Для примера возьмем очень простую ситуацию - в нашем интернет-магазине каждый товар может иметь 0-N рекомендованных товаров.&lt;br /&gt;&lt;br /&gt;Кусок схемы:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;propel:&lt;br /&gt;  pc_product:&lt;br /&gt;    _attributes:   { phpName: Product }&lt;br /&gt;    id:           ~&lt;br /&gt;    name:         varchar(255)&lt;br /&gt;    price1:       float&lt;br /&gt;    price2:       float&lt;br /&gt;    description:  longvarchar&lt;br /&gt;    pic:          varchar(255)&lt;br /&gt;    is_published: boolean&lt;br /&gt;    category_id:  { type: integer, foreignReference: id, foreignTable: pc_category, onDelete: cascade, onUpdate: cascade, required: true }&lt;br /&gt;&lt;br /&gt;  pc_product_recommended:&lt;br /&gt;    _attributes:  { phpName: ProductRecommended }&lt;br /&gt;    id:           ~&lt;br /&gt;    product_id:   { type: integer, foreignReference: id, foreignTable: pc_product, onDelete: cascade, onUpdate: cascade, required: true }&lt;br /&gt;    recommend_product_id: { type: integer, foreignReference: id, foreignTable: pc_product, onDelete: cascade, onUpdate: cascade, required: true }&lt;br /&gt;    note:         { type: varchar(512), default: null }&lt;br /&gt;    pos:          integer&lt;br /&gt;&lt;br /&gt;pc_category:&lt;br /&gt;    _attributes:   { phpName: Category, treeMode: NestedSet }&lt;br /&gt;    id:            ~&lt;br /&gt;    name:         varchar(255)&lt;br /&gt;    alias:        varchar(1024)&lt;br /&gt;    lft:          { type: integer, required: false, default: 0, nestedSetLeftKey: 'true'}&lt;br /&gt;    rgt:          { type: integer, required: false, default: 0, nestedSetRightKey: 'true'}&lt;br /&gt;    scope:        { type: integer, required: false, default: 0, treeScopeKey: 'true'}&lt;br /&gt;    parent:       { type: integer }&lt;br /&gt;    is_published:  { type: boolean }&lt;br /&gt;    deleted_at:    { type: date }&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Изменяем /lib/forms/ProductForm.class.php&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class ProductForm extends BaseProductForm&lt;br /&gt;{&lt;br /&gt;  public function configure()&lt;br /&gt;  {&lt;br /&gt;    $this-&gt;setWidgets(array(&lt;br /&gt;      'category_id'  =&gt; new sfWidgetFormPropelChoice(array('model' =&gt; 'Category', 'add_empty' =&gt; false)),&lt;br /&gt;      'id'           =&gt; new sfWidgetFormInputHidden(),&lt;br /&gt;      'name'         =&gt; new sfWidgetFormInput(),&lt;br /&gt;      'price1'       =&gt; new sfWidgetFormInput(),&lt;br /&gt;      'price2'       =&gt; new sfWidgetFormInput(),&lt;br /&gt;      'pic'          =&gt; new myWidgetFormInputFileEditable(),&lt;br /&gt;      'is_published' =&gt; new sfWidgetFormInputCheckbox(),&lt;br /&gt;    ));&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    $this-&gt;setValidators(array(&lt;br /&gt;      'id'           =&gt; new sfValidatorPropelChoice(array('model' =&gt; 'Product', 'column' =&gt; 'id', 'required' =&gt; false)),&lt;br /&gt;      'name'         =&gt; new sfValidatorString(array('max_length' =&gt; 255, 'required' =&gt; false)),&lt;br /&gt;      'price1'       =&gt; new sfValidatorNumber(array('required' =&gt; false)),&lt;br /&gt;      'price2'       =&gt; new sfValidatorNumber(array('required' =&gt; false)),&lt;br /&gt;      'is_published' =&gt; new sfValidatorBoolean(array('required' =&gt; false)),&lt;br /&gt;      'category_id'  =&gt; new sfValidatorPropelChoice(array('model' =&gt; 'Category', 'column' =&gt; 'id')),&lt;br /&gt;      'pic'          =&gt; new sfValidatorFile(array(&lt;br /&gt;            'required' =&gt; false,&lt;br /&gt;            'max_size' =&gt; '102400', // bytes (1MB)&lt;br /&gt;            'mime_types' =&gt; array('image/png', 'image/jpeg', 'image/gif',)&lt;br /&gt;       )),&lt;br /&gt;    ));&lt;br /&gt;  &lt;br /&gt;    $this-&gt;widgetSchema-&gt;setNameFormat('product[%s]');&lt;br /&gt;&lt;br /&gt;    $this-&gt;errorSchema = new sfValidatorErrorSchema($this-&gt;validatorSchema);&lt;br /&gt;&lt;br /&gt;    $this-&gt;validatorSchema-&gt;setOption('allow_extra_fields', true);&lt;br /&gt;    $this-&gt;validatorSchema-&gt;setOption('filter_extra_fields', false);&lt;br /&gt;&lt;br /&gt;    //получим дочерние записи&lt;br /&gt;    $c = new Criteria();&lt;br /&gt;    $c-&gt;add(ProductRecommendedPeer::PRODUCT_ID, $this-&gt;getObject()-&gt;getId());&lt;br /&gt;    $c-&gt;addAscendingOrderByColumn(ProductRecommendedPeer::ID);&lt;br /&gt;    $rps = ProductRecommendedPeer::doSelect($c);&lt;br /&gt;    //цикл по дочерним записям&lt;br /&gt;    foreach ($rps as $index =&gt; $rProduct)&lt;br /&gt;    {&lt;br /&gt;      $rProductForm = new ProductRecommendedForm($rProduct);&lt;br /&gt;      $rProductForm-&gt;setWidget('product_id', new sfWidgetFormInputHidden());&lt;br /&gt;      $rProductForm-&gt;setWidget('del_me', new sfWidgetFormInputCheckbox());&lt;br /&gt;      $rProductForm-&gt;setValidator('del_me', new sfValidatorBoolean(array('required' =&gt; false)));&lt;br /&gt;      $rProductForm-&gt;widgetSchema-&gt;moveField('del_me', sfWidgetFormSchema::FIRST);&lt;br /&gt;&lt;br /&gt;      $this-&gt;embedForm('rProduct-'.$index, $rProductForm);&lt;br /&gt;      $this-&gt;widgetSchema-&gt;setLabel('rProduct-'.$index, $index+1);&lt;br /&gt;    }&lt;br /&gt;    $rProductForm = new ProductRecommendedForm();&lt;br /&gt;&lt;br /&gt;    $rProductForm-&gt;setWidget('product_id', new sfWidgetFormInputHidden());&lt;br /&gt;    //добавляем дополнительный чекбокс, для удаления записи&lt;br /&gt;    $rProductForm-&gt;setWidget('del_me', new sfWidgetFormInputCheckbox(&lt;br /&gt;        array(),&lt;br /&gt;        array('disabled' =&gt; true)&lt;br /&gt;    ));&lt;br /&gt;    if (!$this-&gt;getObject()-&gt;isNew())&lt;br /&gt;    {&lt;br /&gt;      //добавим пустой элемент в списке, на случай если мы не хотим добавлять новую запись&lt;br /&gt;      $rProductForm-&gt;setWidget('recommend_product_id', new sfWidgetFormPropelChoice(&lt;br /&gt;          array('model' =&gt; 'Product', 'add_empty' =&gt; true)));&lt;br /&gt;&lt;br /&gt;      $rProductForm-&gt;setDefaults(array('product_id' =&gt; $this-&gt;getObject()-&gt;getId()));&lt;br /&gt;      //отключим обязательный выбор значения листбокса&lt;br /&gt;      $rProductForm-&gt;setValidator('recommend_product_id', new sfValidatorInteger(array('required' =&gt; false)));&lt;br /&gt;      //переносим чекбокс для удаления записи наверх&lt;br /&gt;      $rProductForm-&gt;widgetSchema-&gt;moveField('del_me', sfWidgetFormSchema::FIRST);&lt;br /&gt;&lt;br /&gt;      $this-&gt;embedForm('new-rec', $rProductForm);&lt;br /&gt;      $this-&gt;widgetSchema-&gt;setLabel('new-rec', 'new record');&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public function updateObject($values = null)&lt;br /&gt;  {&lt;br /&gt;    $object = parent::updateObject();&lt;br /&gt;    $path = sfConfig::get('sf_root_dir').DIRECTORY_SEPARATOR.&lt;br /&gt;      sfConfig::get('sf_web_dir_name').DIRECTORY_SEPARATOR.sfConfig::get('sf_upload_dir');&lt;br /&gt;    $object-&gt;setPic(str_replace($path.'/', '', $object-&gt;getPic()));&lt;br /&gt;    return $object;&lt;br /&gt;  }&lt;br /&gt;  /*&lt;br /&gt;   *  do save&lt;br /&gt;   */&lt;br /&gt;  protected function doSave($con = null){&lt;br /&gt;    $values = $this-&gt;getValues();&lt;br /&gt;&lt;br /&gt;    $path = sfConfig::get('sf_root_dir').'/'.&lt;br /&gt;      sfConfig::get('sf_web_dir_name').'/'.sfConfig::get('sf_upload_dir');&lt;br /&gt;&lt;br /&gt;    if (isset($values['pic_delete'])){&lt;br /&gt;      $currentFile = $path.'/'.$this-&gt;getObject()-&gt;getPic();&lt;br /&gt;      if (is_file($currentFile)){&lt;br /&gt;        unlink($currentFile);&lt;br /&gt;      }&lt;br /&gt;      $this-&gt;getObject()-&gt;setPic('');&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    $file = $values['pic'];&lt;br /&gt;&lt;br /&gt;    if(!empty($file)){&lt;br /&gt;      if (file_exists(sfConfig::get('sf_upload_dir').'/'.$this-&gt;getObject()-&gt;getPic())){&lt;br /&gt;        @unlink($this-&gt;getObject()-&gt;getPic());&lt;br /&gt;      }&lt;br /&gt;      $filename = sha1($file-&gt;getOriginalName()).$file-&gt;getExtension($file-&gt;getOriginalExtension());&lt;br /&gt;      $path = sfConfig::get('sf_root_dir').DIRECTORY_SEPARATOR.sfConfig::get('sf_web_dir_name').DIRECTORY_SEPARATOR.sfConfig::get('sf_upload_dir');&lt;br /&gt;      $file-&gt;save($path.'/'.$filename);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return parent::doSave($con);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Если в /generator.yml настройки форм по умолчанию:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   form: ~&lt;br /&gt;   edit: ~&lt;br /&gt;   new:  ~&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;мы видим внизу формы редактирования доп.форму с добавлением записи&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_ZX6AxddT59s/SdvUskpjS6I/AAAAAAAAAEo/ewcoN1fWD8E/s1600-h/sf-tabular-forms-1.gif"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 190px;" src="http://3.bp.blogspot.com/_ZX6AxddT59s/SdvUskpjS6I/AAAAAAAAAEo/ewcoN1fWD8E/s400/sf-tabular-forms-1.gif" alt="" id="BLOGGER_PHOTO_ID_5322081246885661602" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;она даже работает ;) но внешний вид нас не устраивает, и по работе тоже есть нарекания, при каждом обновлении родительской формы без указания нового рекомендованного товара, у нас добавляется пустая запись, а так же еще не работает удаление записей.&lt;br /&gt;&lt;br /&gt;Давайте исправим внешний вид и логику добавления-удаления.&lt;br /&gt;&lt;br /&gt;Редактируем в config/generator.yml настройки формы указываем поля для отображения:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   form:&lt;br /&gt;     display:      [ name, price1, price2, pic, is_published ]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Такая небольшая настройка приводит к тому, что исчезают наши встроенные формы, подробнее об этом явлении как нибудь позже...&lt;br /&gt;При этом форма перестает работать, что неудивительно, т.к. мы к форме прикрепили массу валидаторов для подчиненных форм.&lt;br /&gt;Теперь мы в ручную отобразим подформы в табличном виде.&lt;br /&gt;Заходим в кэш и копируем&lt;br /&gt;/cache/backend/.../autoProduct/templates/_form.php в&lt;br /&gt;apps/backend/modules/product/templates/_form.php&lt;br /&gt;&lt;br /&gt;Далее заменяем содежимое этого файла на:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;div class="sf_admin_form"&amp;gt;&lt;br /&gt;  &amp;lt;?php echo form_tag_for($form, '@product') ?&amp;gt;&lt;br /&gt;    &amp;lt;?php echo $form-&amp;gt;renderHiddenFields() ?&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;?php if ($form-&amp;gt;hasGlobalErrors()): ?&amp;gt;&lt;br /&gt;      &amp;lt;?php echo $form-&amp;gt;renderGlobalErrors() ?&amp;gt;&lt;br /&gt;    &amp;lt;?php endif; ?&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;?php foreach ($configuration-&amp;gt;getFormFields($form, $form-&amp;gt;isNew() ? 'new' : 'edit') as $fieldset =&amp;gt; $fields): ?&amp;gt;&lt;br /&gt;      &amp;lt;?php include_partial('product/form_fieldset', array('product' =&amp;gt; $product, 'form' =&amp;gt; $form, 'fields' =&amp;gt; $fields, 'fieldset' =&amp;gt; $fieldset)) ?&amp;gt;&lt;br /&gt;    &amp;lt;?php endforeach; ?&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;?php if ($form-&amp;gt;getEmbeddedForms()): ?&amp;gt;&lt;br /&gt;      &amp;lt;fieldset id="sf_fieldset_recommended_products"&amp;gt;&lt;br /&gt;      &amp;lt;h2&amp;gt;Recommended products&amp;lt;/h2&amp;gt;&lt;br /&gt;      &amp;lt;table&amp;gt;&lt;br /&gt;      &amp;lt;tr&amp;gt;&lt;br /&gt;        &amp;lt;th&amp;gt;#&amp;lt;/th&amp;gt;&lt;br /&gt;        &amp;lt;th&amp;gt;del&amp;lt;/th&amp;gt;&lt;br /&gt;        &amp;lt;th&amp;gt;product&amp;lt;/th&amp;gt;&lt;br /&gt;        &amp;lt;th&amp;gt;note&amp;lt;/th&amp;gt;&lt;br /&gt;        &amp;lt;th&amp;gt;pos&amp;lt;/th&amp;gt;&lt;br /&gt;      &amp;lt;/tr&amp;gt;&lt;br /&gt;      &amp;lt;?php foreach ($form-&amp;gt;getEmbeddedForms() as $index =&amp;gt; $embForm): ?&amp;gt;&lt;br /&gt;      &amp;lt;tr&amp;gt;&lt;br /&gt;        &amp;lt;?php echo $form[$index]['id']-&amp;gt;render() ?&amp;gt;&lt;br /&gt;        &amp;lt;?php echo $form[$index]['product_id']-&amp;gt;render() ?&amp;gt;&lt;br /&gt;        &amp;lt;td&amp;gt;&amp;lt;?php echo $form[$index]-&amp;gt;renderLabel() ?&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;td&amp;gt;&amp;lt;?php echo $form[$index]['del_me']-&amp;gt;renderError() ?&amp;gt;&amp;lt;?php echo $form[$index]['del_me']-&amp;gt;render() ?&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;td&amp;gt;&amp;lt;?php echo $form[$index]['recommend_product_id']-&amp;gt;renderError() ?&amp;gt;&amp;lt;?php echo $form[$index]['recommend_product_id']-&amp;gt;render() ?&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;td&amp;gt;&amp;lt;?php echo $form[$index]['note']-&amp;gt;renderError() ?&amp;gt;&amp;lt;?php echo $form[$index]['note']-&amp;gt;render() ?&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;td&amp;gt;&amp;lt;?php echo $form[$index]['pos']-&amp;gt;renderError() ?&amp;gt;&amp;lt;?php echo $form[$index]['pos']-&amp;gt;render() ?&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;      &amp;lt;/tr&amp;gt;&lt;br /&gt;      &amp;lt;?php endforeach; ?&amp;gt;&lt;br /&gt;      &amp;lt;/table&amp;gt;&lt;br /&gt;      &amp;lt;/fieldset&amp;gt;&lt;br /&gt;    &amp;lt;?php endif; ?&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;?php include_partial('product/form_actions', array('product' =&amp;gt; $product, 'form' =&amp;gt; $form, 'configuration' =&amp;gt; $configuration, 'helper' =&amp;gt; $helper)) ?&amp;gt;&lt;br /&gt;  &amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_ZX6AxddT59s/SdvbPAKEMhI/AAAAAAAAAEw/9zM4uCFDVAk/s1600-h/sf-tabular-forms-2.gif"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 142px;" src="http://2.bp.blogspot.com/_ZX6AxddT59s/SdvbPAKEMhI/AAAAAAAAAEw/9zM4uCFDVAk/s400/sf-tabular-forms-2.gif" alt="" id="BLOGGER_PHOTO_ID_5322088435455111698" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Подформа преобрела более приятный вид, остается разобраться с обновлением и удалением.&lt;br /&gt;Добавляем новый метод в /lib/forms/ProductForm.class.php&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  public function updateObjectEmbeddedForms($values, $forms = null)&lt;br /&gt;  {&lt;br /&gt;    if (is_null($forms))&lt;br /&gt;    {&lt;br /&gt;      $forms = $this-&gt;embeddedForms;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    foreach ($forms as $name =&gt; $form)&lt;br /&gt;    {&lt;br /&gt;      if (!is_array($values[$name]))&lt;br /&gt;      {&lt;br /&gt;        continue;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      if ($form instanceof sfFormPropel)&lt;br /&gt;      {&lt;br /&gt;        if (isSet($values[$name]['del_me'])){&lt;br /&gt;          if ($values[$name]['del_me'] == 1)&lt;br /&gt;          {&lt;br /&gt;            $form-&gt;getObject()-&gt;delete();&lt;br /&gt;            unset($this-&gt;embeddedForms[$name]);&lt;br /&gt;            continue;&lt;br /&gt;          }&lt;br /&gt;        } else {&lt;br /&gt;          if (strstr($name, 'new-'))&lt;br /&gt;          {&lt;br /&gt;            //именно тут мы сами выступаем в роли валидатора, и если одно из обязательных полей пустое,&lt;br /&gt;            //мы игнорируем новую запись&lt;br /&gt;            $rProduct = $values[$name]['recommend_product_id'];&lt;br /&gt;            $rPos = $values[$name]['pos'];&lt;br /&gt;            if ( empty($rProduct) OR empty($rPos))&lt;br /&gt;            {&lt;br /&gt;              unset($this-&gt;embeddedForms[$name]);&lt;br /&gt;              continue;&lt;br /&gt;            }&lt;br /&gt;          }&lt;br /&gt;        }//if !isset del me&lt;br /&gt;        $form-&gt;updateObject($values[$name]);&lt;br /&gt;      }&lt;br /&gt;      else&lt;br /&gt;      {&lt;br /&gt;        $this-&gt;updateObjectEmbeddedForms($values[$name], $form-&gt;getEmbeddedForms());&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    //die();&lt;br /&gt;  }//updateObjectEmbeddedForms&lt;br /&gt;  &lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-120520384967509521?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/RouHJlmITeQ/symfony-12-tabular-subforms.html</link><author>noreply@blogger.com (Vit228)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_ZX6AxddT59s/SdvUskpjS6I/AAAAAAAAAEo/ewcoN1fWD8E/s72-c/sf-tabular-forms-1.gif" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://vit228.blogspot.com/2009/04/symfony-12-tabular-subforms.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-8320529904170414032</guid><pubDate>Thu, 25 Dec 2008 10:17:00 +0000</pubDate><atom:updated>2008-12-25T13:18:43.937+03:00</atom:updated><title>Символ 2009 года - в подарок!</title><description>&lt;span style="font-weight: bold;"&gt;&lt;span style="font-size:100%;"&gt;С Новым годом и Рождеством, дорогие друзья!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;Желаю всем психического здоровья!&lt;br /&gt;В качестве объекта для успокоения нервов и предпраздничного мидитирования предлагаю &lt;a href="http://www.netservice.ru/symbol2009/"&gt;символ года в виде бумажной коровы (скачать)&lt;/a&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_VCeJgLPg9JA/SVNaYPdMomI/AAAAAAAAAGU/k3zFRwiBbIY/s1600-h/idea_big.jpg"&gt;&lt;img style="cursor: pointer; width: 320px; height: 249px;" src="http://2.bp.blogspot.com/_VCeJgLPg9JA/SVNaYPdMomI/AAAAAAAAAGU/k3zFRwiBbIY/s320/idea_big.jpg" alt="" id="BLOGGER_PHOTO_ID_5283666160348078690" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;Энжой! :)&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-8320529904170414032?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/OU4FFCojVh8/2009.html</link><author>noreply@blogger.com (NetMozg Sr)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_VCeJgLPg9JA/SVNaYPdMomI/AAAAAAAAAGU/k3zFRwiBbIY/s72-c/idea_big.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://vit228.blogspot.com/2008/12/2009.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-2383880064496697182</guid><pubDate>Fri, 14 Nov 2008 17:20:00 +0000</pubDate><atom:updated>2008-11-18T00:03:04.198+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">admin</category><category domain="http://www.blogger.com/atom/ns#">symfony1.2</category><category domain="http://www.blogger.com/atom/ns#">generator</category><title>Symfony 1.2: file upload in admin</title><description>Это черновик&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;/backend/modules/author/lib/form/myAuthorForm.class.php&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/**&lt;br /&gt; * Author form.&lt;br /&gt; *&lt;br /&gt; * @package    any&lt;br /&gt; * @subpackage form&lt;br /&gt; * @author     Your name here&lt;br /&gt; * @version    SVN: $Id: sfPropelFormTemplate.php 10377 2008-07-21 07:10:32Z dwhittle $&lt;br /&gt; */&lt;br /&gt;class myAuthorForm extends BaseAuthorForm&lt;br /&gt;{&lt;br /&gt;  public function configure()&lt;br /&gt;  {&lt;br /&gt;    $this-&gt;setWidget('description', new myWidgetFormRichTextarea(array('editor'=&gt;'fck')));&lt;br /&gt;    $values = $this-&gt;getValues();&lt;br /&gt;    $this-&gt;setWidget('pic', new myWidgetFormInputFileEditable(&lt;br /&gt;   array(&lt;br /&gt;        'is_image'      =&gt; true,&lt;br /&gt;        'delete_label'  =&gt; 'удалить'&lt;br /&gt;   )));&lt;br /&gt;    //$this-&gt;setWidget('pic', new sfWidgetFormInputFile());&lt;br /&gt;    $this-&gt;setWidget('avatar', new sfWidgetFormInputFile());&lt;br /&gt;    /* VALIDATORS */&lt;br /&gt;    $this-&gt;setValidators(array(&lt;br /&gt;      'f_name'      =&gt; new sfValidatorString(&lt;br /&gt;          array(),&lt;br /&gt;          array('required' =&gt; 'Обязательное поле')&lt;br /&gt;      ),&lt;br /&gt;      'l_name'      =&gt; new sfValidatorString(&lt;br /&gt;          array(),&lt;br /&gt;          array('required' =&gt; 'Обязательное поле')&lt;br /&gt;      ),&lt;br /&gt;      'email'            =&gt; new sfValidatorEmail(&lt;br /&gt;          $options = array(), &lt;br /&gt;          $messages = array(&lt;br /&gt;            'invalid' =&gt; 'Введите правильный Email',&lt;br /&gt;            'required' =&gt; false)&lt;br /&gt;      ),&lt;br /&gt;      'pic'          =&gt; new sfValidatorFile(array(&lt;br /&gt;            'required' =&gt; false,&lt;br /&gt;            'max_size' =&gt; '102400', // bytes (1MB)&lt;br /&gt;            'mime_types' =&gt; array('image/png', 'image/jpeg',) &lt;br /&gt;       )),&lt;br /&gt;    ));&lt;br /&gt;    &lt;br /&gt;    //$this-&gt;widgetSchema-&gt;setNameFormat('%s');&lt;br /&gt;&lt;br /&gt;    $this-&gt;validatorSchema-&gt;setOption('allow_extra_fields', true);&lt;br /&gt;    $this-&gt;validatorSchema-&gt;setOption('filter_extra_fields', false);&lt;br /&gt;  }//configure&lt;br /&gt;&lt;br /&gt; public function updateObject($values = null)&lt;br /&gt;  {&lt;br /&gt;    $object = parent::updateObject();&lt;br /&gt;    $path = sfConfig::get('sf_root_dir').DIRECTORY_SEPARATOR.&lt;br /&gt;      sfConfig::get('sf_web_dir_name').DIRECTORY_SEPARATOR.sfConfig::get('sf_upload_dir');&lt;br /&gt;    $object-&gt;setPic(str_replace($path.'/', '', $object-&gt;getPic()));&lt;br /&gt;    return $object;&lt;br /&gt;  }&lt;br /&gt;  /* do save*/&lt;br /&gt;  protected function doSave($con = null){&lt;br /&gt;    $values = $this-&gt;getValues();&lt;br /&gt;    &lt;br /&gt;    $path = sfConfig::get('sf_root_dir').'/'.&lt;br /&gt;      sfConfig::get('sf_web_dir_name').'/'.sfConfig::get('sf_upload_dir');&lt;br /&gt;    &lt;br /&gt;    if (isset($values['pic_delete'])){&lt;br /&gt;      $currentFile = $path.'/'.$this-&gt;getObject()-&gt;getPic();&lt;br /&gt;      if (is_file($currentFile)){&lt;br /&gt;        unlink($currentFile);&lt;br /&gt;      }&lt;br /&gt;      $this-&gt;getObject()-&gt;setPic('');&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    $file = $values['pic'];&lt;br /&gt;&lt;br /&gt;    if(!empty($file)){&lt;br /&gt;      if (file_exists(sfConfig::get('sf_upload_dir').'/'.$this-&gt;getObject()-&gt;getPic())){&lt;br /&gt;        @unlink($this-&gt;getObject()-&gt;getPic());&lt;br /&gt;      }&lt;br /&gt;      $filename = sha1($file-&gt;getOriginalName()).$file-&gt;getExtension($file-&gt;getOriginalExtension());&lt;br /&gt;      $path = sfConfig::get('sf_root_dir').DIRECTORY_SEPARATOR.sfConfig::get('sf_web_dir_name').DIRECTORY_SEPARATOR.sfConfig::get('sf_upload_dir');&lt;br /&gt;      $file-&gt;save($path.'/'.$filename);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    return parent::doSave($con);&lt;br /&gt;  }&lt;br /&gt;}//class&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;/lib/myWidgetFormInputFileEditable.class.php&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/*&lt;br /&gt; * This file is part of the symfony package.&lt;br /&gt; * (c) Fabien Potencier &lt;fabien.potencier@symfony-project.com&gt;&lt;br /&gt; * &lt;br /&gt; * For the full copyright and license information, please view the LICENSE&lt;br /&gt; * file that was distributed with this source code.&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * sfWidgetFormInputFileEditable represents an upload HTML input tag with the possibility&lt;br /&gt; * to remove a previously uploaded file.&lt;br /&gt; *&lt;br /&gt; * @package    symfony&lt;br /&gt; * @subpackage widget&lt;br /&gt; * @author     Fabien Potencier &lt;fabien.potencier@symfony-project.com&gt;&lt;br /&gt; * @version    SVN: $Id: sfWidgetFormInputFileEditable.class.php 11544 2008-09-14 17:40:07Z fabien $&lt;br /&gt; */&lt;br /&gt;class myWidgetFormInputFileEditable extends sfWidgetFormInputFile&lt;br /&gt;{&lt;br /&gt;  /**&lt;br /&gt;   * Constructor.&lt;br /&gt;   *&lt;br /&gt;   * Available options:&lt;br /&gt;   *&lt;br /&gt;   *  * file_src:     The current image web source path (required)&lt;br /&gt;   *  * edit_mode:    A Boolean: true to enabled edit mode, false otherwise&lt;br /&gt;   *  * is_image:     Whether the file is a displayable image&lt;br /&gt;   *  * with_delete:  Whether to add a delete checkbox or not&lt;br /&gt;   *  * delete_label: The delete label used by the template&lt;br /&gt;   *  * template:     The HTML template to use to render this widget&lt;br /&gt;   *                  The available placeholders are:&lt;br /&gt;   *                    * input (the image upload widget)&lt;br /&gt;   *                    * delete (the delete checkbox)&lt;br /&gt;   *                    * delete_label (the delete label text)&lt;br /&gt;   *                    * file (the file tag)&lt;br /&gt;   *&lt;br /&gt;   * In edit mode, this widget renders an additional widget named after the&lt;br /&gt;   * file upload widget with a "_delete" suffix. So, when creating a form,&lt;br /&gt;   * don't forget to add a validator for this additional field.&lt;br /&gt;   *&lt;br /&gt;   * @param array $options     An array of options&lt;br /&gt;   * @param array $attributes  An array of default HTML attributes&lt;br /&gt;   *&lt;br /&gt;   * @see sfWidgetFormInputFile&lt;br /&gt;   */&lt;br /&gt;  protected function configure($options = array(), $attributes = array())&lt;br /&gt;  {&lt;br /&gt;    parent::configure($options, $attributes);&lt;br /&gt;&lt;br /&gt;    $this-&gt;setOption('type', 'file');&lt;br /&gt;    $this-&gt;setOption('needs_multipart', true);&lt;br /&gt;&lt;br /&gt;    //$this-&gt;addRequiredOption('file_src');&lt;br /&gt;    $this-&gt;addOption('file_src', '');&lt;br /&gt;    $this-&gt;addOption('is_image', false);&lt;br /&gt;    $this-&gt;addOption('edit_mode', true);&lt;br /&gt;    $this-&gt;addOption('with_delete', true);&lt;br /&gt;    $this-&gt;addOption('delete_label', 'remove the current file');&lt;br /&gt;    $this-&gt;addOption('template', '%file% %input% %delete% %delete_label%');&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;   * @param  string $name        The element name&lt;br /&gt;   * @param  string $value       The value displayed in this widget&lt;br /&gt;   * @param  array  $attributes  An array of HTML attributes to be merged with the default HTML attributes&lt;br /&gt;   * @param  array  $errors      An array of errors for the field&lt;br /&gt;   *&lt;br /&gt;   * @return string An HTML tag string&lt;br /&gt;   *&lt;br /&gt;   * @see sfWidgetForm&lt;br /&gt;   */&lt;br /&gt;  public function render($name, $value = null, $attributes = array(), $errors = array())&lt;br /&gt;  {&lt;br /&gt;&lt;br /&gt;    $input = parent::render($name, $value, $attributes, $errors);&lt;br /&gt;&lt;br /&gt;    if (!$this-&gt;getOption('edit_mode'))&lt;br /&gt;    {&lt;br /&gt;      return $input;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if ($this-&gt;getOption('with_delete')){&lt;br /&gt;      $deleteName = ']' == substr($name, -1) ? substr($name, 0, -1).'_delete]' : $name.'_delete';&lt;br /&gt;      $delete = $this-&gt;renderTag('input', array_merge(array('type' =&gt; 'checkbox', 'name' =&gt; $deleteName), $attributes));&lt;br /&gt;      $deleteLabel = $this-&gt;renderContentTag('span', $this-&gt;getOption('delete_label'), array_merge(array('for' =&gt; $this-&gt;generateId($deleteName))));&lt;br /&gt;    } else {&lt;br /&gt;      $delete = '';&lt;br /&gt;      $deleteLabel = '';&lt;br /&gt;    }&lt;br /&gt;    if ($value){&lt;br /&gt;      $picLink = " || &amp;lt;a class='thickbox' target='_blank' href='/uploads/".$value."'&amp;gt;show me&amp;lt;/a&amp;gt;";&lt;br /&gt;    } else {&lt;br /&gt;      $picLink = "";&lt;br /&gt;      $delete = '';&lt;br /&gt;      $deleteLabel = '';&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    return strtr($this-&gt;getOption('template'), array(&lt;br /&gt;      '%input%' =&gt; $input, &lt;br /&gt;      '%delete%' =&gt; $delete, &lt;br /&gt;      '%delete_label%' =&gt; $deleteLabel, &lt;br /&gt;      '%file%' =&gt; $this-&gt;getFileAsTag($attributes, $value))&lt;br /&gt;    ).$picLink;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  protected function getFileAsTag($attributes, $value=null)&lt;br /&gt;  {&lt;br /&gt;    if ($this-&gt;getOption('is_image'))&lt;br /&gt;    {&lt;br /&gt;      return false !== $value ? $this-&gt;renderTag('img', array_merge(array('src' =&gt; $value)), $attributes) : '';&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;      return $this-&gt;getOption('file_src');&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;/backend/config/view.yml&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;default:&lt;br /&gt;  http_metas:&lt;br /&gt;    content-type: text/html&lt;br /&gt;  metas:&lt;br /&gt;    title:        Admin&lt;br /&gt;  stylesheets:    [main, thickbox]&lt;br /&gt;  javascripts:    [jq/jquery.pack.js, jq/thickbox.pack.js]&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-2383880064496697182?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/5qNnEWq7L_M/symfony-12-file-upload-in-admin.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total><feedburner:origLink>http://vit228.blogspot.com/2008/11/symfony-12-file-upload-in-admin.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-6601267681530981968</guid><pubDate>Fri, 14 Nov 2008 17:01:00 +0000</pubDate><atom:updated>2008-11-14T20:20:04.248+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">symfony</category><category domain="http://www.blogger.com/atom/ns#">improvements</category><title>Symfony: sfGuard custom login form</title><description>Немного улучшим дизайн формы ввода логина.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_ZX6AxddT59s/SR2wArWVCYI/AAAAAAAAAEQ/oogY6vNgB0g/s1600-h/sf-login-form.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 318px; height: 205px;" src="http://3.bp.blogspot.com/_ZX6AxddT59s/SR2wArWVCYI/AAAAAAAAAEQ/oogY6vNgB0g/s400/sf-login-form.jpg" alt="" id="BLOGGER_PHOTO_ID_5268560664776214914" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;myGuard.css&lt;br /&gt;&lt;pre&gt;.error_list { color: #ff0000; }&lt;br /&gt;.errorField{&lt;br /&gt; background: #ffffcc; border: 2px solid red;&lt;br /&gt;}&lt;br /&gt;.okField{&lt;br /&gt; background: #ffffcc; border: 2px solid lightgreen;&lt;br /&gt;}&lt;br /&gt;.inputField{&lt;br /&gt; background: #ffffff;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;#loginForm {&lt;br /&gt; display: none;&lt;br /&gt; background: khaki; width: 280px;&lt;br /&gt; position: absolute;&lt;br /&gt; z-index: 9999; font-family: Tahoma; font-size: 12px;&lt;br /&gt; border: 0px solid red;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;#loginFormHeader {&lt;br /&gt; background: #cccc33; padding: 10px;&lt;br /&gt; border-bottom: 1px solid gray;&lt;br /&gt; font-weight: bold;&lt;br /&gt;}&lt;br /&gt;#loginFormBody {&lt;br /&gt; border-top: 1px solid #ececec;&lt;br /&gt; border-bottom: 1px solid gray;&lt;br /&gt; padding: 4px 0px 4px 0px;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;#loginFormPic {&lt;br /&gt; padding: 10px 0px 0px 10px;&lt;br /&gt; display: block;&lt;br /&gt; float: left;&lt;br /&gt;}&lt;br /&gt;#loginFormBody ul{&lt;br /&gt; float: left;&lt;br /&gt; display: block;&lt;br /&gt; border: 0px solid navy;&lt;br /&gt; padding: 4px; list-style: none;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;#loginFormBody ul li{&lt;br /&gt; border: 0px solid #f63;&lt;br /&gt; padding: 4px;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;#loginFormBody label&lt;br /&gt;{&lt;br /&gt; display: block;&lt;br /&gt; border: 0px solid green;&lt;br /&gt; padding: 0 1em 3px 0;&lt;br /&gt; float: left;&lt;br /&gt; text-align: left;&lt;br /&gt; width: 40px;&lt;br /&gt; color: black;&lt;br /&gt; font-weight: normal !important;&lt;br /&gt;}&lt;br /&gt;#loginFormFooter {&lt;br /&gt; padding: 10px;&lt;br /&gt; text-align: center;&lt;br /&gt; border-top: 1px solid #ececec;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;/backend/config/view.yml&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;signinSuccess:&lt;br /&gt;  javascripts:    [jq/jquery.pack.js, jq/jquery.dropshadow.js]&lt;br /&gt;  stylesheets:    [main, myGuard]&lt;br /&gt;  metas:&lt;br /&gt;    title:        login&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;/backend/modules/sfGuardAuth/signinSuccess.php&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;?php $errorFieldClass = "errorField" ?&amp;gt;&lt;br /&gt;&amp;lt;?php $defaultFieldClass = ($sf_request-&amp;gt;isMethod('post') ? "okField" : "inputField" )?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;form action="&amp;lt;?php echo url_for('@sf_guard_signin') ?&amp;gt;"&lt;br /&gt;  method="post"&amp;gt;&lt;br /&gt;&amp;lt;div id="loginForm"&amp;gt;&lt;br /&gt;  &amp;lt;div id="loginFormHeader"&amp;gt;Требуется авторизация&amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;div id="loginFormBody"&amp;gt;&lt;br /&gt;    &amp;lt;div id="loginFormPic"&amp;gt;&amp;lt;img src="/sf/sf_default/images/icons/lock48.png" /&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;    &amp;lt;ul&amp;gt;&lt;br /&gt;      &amp;lt;li&amp;gt;&amp;lt;label for="signin_username"&amp;gt;Логин:&amp;lt;/label&amp;gt;&lt;br /&gt;        &amp;lt;?php echo $form['username']-&amp;gt;render(&lt;br /&gt;            array(&lt;br /&gt;              'class' =&amp;gt; $form['username']-&amp;gt;hasError() ? $errorFieldClass : $defaultFieldClass))&lt;br /&gt;        ?&amp;gt;&lt;br /&gt;      &amp;lt;/li&amp;gt;&lt;br /&gt;      &amp;lt;li&amp;gt;&amp;lt;label for="signin_password"&amp;gt;Пароль:&amp;lt;/label&amp;gt;&lt;br /&gt;        &amp;lt;?php echo $form['password']-&amp;gt;render(&lt;br /&gt;            array(&lt;br /&gt;              'class' =&amp;gt; $form['password']-&amp;gt;hasError() ? $errorFieldClass : $defaultFieldClass))&lt;br /&gt;        ?&amp;gt;&lt;br /&gt;      &amp;lt;/li&amp;gt;&lt;br /&gt;      &amp;lt;li&amp;gt;&amp;lt;label for="signin_remember"&amp;gt;&amp;lt;/label&amp;gt;&lt;br /&gt;        &amp;lt;?php echo $form['remember']-&amp;gt;render() ?&amp;gt; Запомнить?&lt;br /&gt;      &amp;lt;/li&amp;gt;&lt;br /&gt;    &amp;lt;/ul&amp;gt;&lt;br /&gt;    &amp;lt;br clear="all" /&amp;gt;&lt;br /&gt;  &amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;div id="loginFormFooter"&amp;gt;&lt;br /&gt;    &amp;lt;input type="submit" value="войти" /&amp;gt;&lt;br /&gt;  &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;$(document).ready(function() {&lt;br /&gt;  $("#loginForm").hide();&lt;br /&gt;  var popupX = Math.round( ($(window).width() - $("#loginForm").width()) / 2) ;&lt;br /&gt;  var popupY = $(document).scrollTop() + Math.round($(window).height()/2) - Math.round($("#loginForm").height()/2);&lt;br /&gt;  $("#loginForm").css({top: popupY+"px", left: popupX+"px"});&lt;br /&gt;  $("#signin_username").focus();&lt;br /&gt;  $("#loginForm").show();&lt;br /&gt;  $("#loginForm").dropShadow();//{left: -2, top: -2, blur: 4, color: "#03f"}&lt;br /&gt;});&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-6601267681530981968?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/v8qRjnhykqw/symfony-sfguard-custom-login-form.html</link><author>noreply@blogger.com (Vit228)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_ZX6AxddT59s/SR2wArWVCYI/AAAAAAAAAEQ/oogY6vNgB0g/s72-c/sf-login-form.jpg" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://vit228.blogspot.com/2008/11/symfony-sfguard-custom-login-form.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-2453772146669359136</guid><pubDate>Tue, 11 Nov 2008 10:59:00 +0000</pubDate><atom:updated>2008-11-11T14:06:30.807+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">admin</category><category domain="http://www.blogger.com/atom/ns#">symfony1.2</category><category domain="http://www.blogger.com/atom/ns#">generator</category><title>Symfony 1.2: вышло обновление - beta2</title><description>Очень оперативно работают парни, 10 дней прошло после выхода beta1, и вот вам обновление.&lt;br /&gt;Список "фиксов" тут:&lt;br /&gt;http://trac.symfony-project.org/query?status=closed&amp;milestone=1.2.0+BETA2&lt;br /&gt;&lt;br /&gt;Теперь о неприятном ;)&lt;br /&gt;После обновления я сразу получил ошибку&lt;br /&gt;&lt;pre&gt;500 | Internal Server Error | sfConfigurationException&lt;br /&gt;The route "articles_collection" does not exist.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Видимо опять что то изменилось в системе роутинга, беглый просмотр офиц.сайта не дал ответа что далать, пришлось "методом научного тыка" сделать костыль.&lt;br /&gt;&lt;pre&gt;articles_collection:&lt;br /&gt;  url:   /article/:action/*&lt;br /&gt;&lt;br /&gt;articles:&lt;br /&gt;  class:   sfPropelRouteCollection&lt;br /&gt;  options:&lt;br /&gt;    model:       Article&lt;br /&gt;    module:      article&lt;br /&gt;    with_show:   false&lt;br /&gt;    collection_actions: { filter: post, batch: post }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Не знаю, прав ли я???&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-2453772146669359136?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/JcVl6wVxiXE/symfony-12-beta2.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>1</thr:total><feedburner:origLink>http://vit228.blogspot.com/2008/11/symfony-12-beta2.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-1048381963453118176</guid><pubDate>Wed, 05 Nov 2008 13:45:00 +0000</pubDate><atom:updated>2008-11-11T14:09:57.909+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">symfony</category><category domain="http://www.blogger.com/atom/ns#">generator</category><title>Symfony 1.2: подводные камни</title><description>1. В схеме нельзя давать имя модели Comment, это имя теперь зарезервировано Propel 1.3, используйте BlogComment  и т.п.&lt;br /&gt;&lt;br /&gt;2. Новый админ-генератор использует routing.yml, перед генерацией админки надо обязательно вписать в него блок такого типа:&lt;br /&gt;&lt;pre&gt;articles:&lt;br /&gt;class: sfPropelRouteCollection&lt;br /&gt;options:&lt;br /&gt;  model:              BlogArticle&lt;br /&gt;  module:             article&lt;br /&gt;  collection_actions: { filter: post, batch: post }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;Внимание!!!&lt;/span&gt;&lt;br /&gt;Блок вставлять в начало routing.yml иначе получите ошибку&lt;br /&gt;404 | Not Found | sfError404Exception&lt;br /&gt;Action "articles/index" does not exist.&lt;br /&gt;&lt;br /&gt;3. Помимо генерации модели и форм командами &lt;span style="font-weight: bold;"&gt;propel:generate-model&lt;/span&gt;, &lt;span style="font-weight: bold;"&gt;propel:generate-forms&lt;/span&gt;, теперь еще надо генерировать и фильтры(при первом взгляде те же формы) командой &lt;span style="font-weight: bold;"&gt;propel:generate-filters&lt;/span&gt;. Либо просто &lt;span style="font-weight: bold;"&gt;propel:generate-all&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;...to be continued...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-1048381963453118176?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/_LtCsepIxkM/symfony-12.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total><feedburner:origLink>http://vit228.blogspot.com/2008/11/symfony-12.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-6990656723396535734</guid><pubDate>Sat, 01 Nov 2008 21:01:00 +0000</pubDate><atom:updated>2008-11-02T00:03:08.559+03:00</atom:updated><title>Symfony 1.2 beta released!</title><description>Ура свершилось!&lt;br /&gt;Инструкции по инсталляции тут http://www.symfony-project.org/installation/1_2&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017927848434571082-6990656723396535734?l=vit228.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/noob_vs_symfony/~3/g8QroPANQCo/symfony-12-beta-released.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total><feedburner:origLink>http://vit228.blogspot.com/2008/11/symfony-12-beta-released.html</feedburner:origLink></item></channel></rss>

