<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-7017927848434571082</atom:id><lastBuildDate>Wed, 18 Feb 2026 21:59:15 +0000</lastBuildDate><category>symfony</category><category>admin</category><category>generator</category><category>improvements</category><category>propel</category><category>symfony1.2</category><category>feedback</category><category>forms</category><category>upload</category><category>utf-8</category><category>Doctrine</category><category>ajax</category><category>application</category><category>backend</category><category>css</category><category>date</category><category>embedded</category><category>file</category><category>filter</category><category>helper</category><category>htaccess</category><category>icons</category><category>instalation</category><category>jQuery</category><category>lamp</category><category>less</category><category>log</category><category>mysql</category><category>nodejs</category><category>php</category><category>query</category><category>settings</category><category>slug</category><category>subdomain</category><category>symfony2</category><category>ubuntu</category><category>unique</category><category>usefull</category><category>validator</category><category>widget</category><title>code talks</title><description>больше кода, меньше слов</description><link>http://vit228.blogspot.com/</link><managingEditor>noreply@blogger.com (Vit228)</managingEditor><generator>Blogger</generator><openSearch:totalResults>43</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-6787596048086707285</guid><pubDate>Fri, 02 Oct 2015 09:28:00 +0000</pubDate><atom:updated>2015-10-02T12:30:23.680+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">less</category><category domain="http://www.blogger.com/atom/ns#">nodejs</category><category domain="http://www.blogger.com/atom/ns#">symfony2</category><title>Symfony2: fix error on dumping assets with using less, in Ubuntu 14.04</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;pre&gt;If you got an error on dumping assets&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;$ php app/console assetic:dump &lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;[Assetic\Exception\FilterException]         
  An error occurred while running:            
  &#39;/usr/sbin/node&#39; &#39;/tmp/assetic_lessl9esGS&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;Check anf fix all paths for nodejs and less, or just try this configuration&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;assetic:
    debug:          &quot;%kernel.debug%&quot;
    use_controller: false
    bundles:        [ ]
    #java: /usr/bin/java
    filters:
        less:
            bin: /usr/local/bin/lessc
            node: /usr/bin/nodejs
            node_paths: [&quot;/usr/local/lib/node_modules&quot;]
            apply_to: &quot;\.less$&quot;&lt;/pre&gt;
&lt;/div&gt;
</description><link>http://vit228.blogspot.com/2015/10/symfony2-fix-error-on-dumping-assets.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-4526930188052855917</guid><pubDate>Tue, 15 Jan 2013 14:46:00 +0000</pubDate><atom:updated>2013-01-15T18:48:39.085+04:00</atom:updated><title>Phalcon: Set output format for Phalcon-based RESTful API</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
1. edit .htaccess

&lt;br /&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;pre&gt;AddDefaultCharset UTF-8

&amp;lt;ifmodule mod_rewrite.c=&quot;mod_rewrite.c&quot;&amp;gt;
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^([^.]+)$ index.php?_url=/$1&amp;amp;format=json [QSA,L]
    RewriteRule ^([^.]+)\.(\w+)$ index.php?_url=/$1&amp;amp;format=$2 [QSA,L]
&amp;lt;/ifmodule&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h4 style=&quot;font-size: 14px; line-height: 18px; margin: 0pt 0pt 5px; padding: 0pt;&quot;&gt;
&lt;/h4&gt;
2. edit index.php&lt;br /&gt;
&lt;pre&gt;  ...&lt;/pre&gt;
&lt;pre&gt;  $app = new \Phalcon\Mvc\Micro();
&lt;/pre&gt;
&lt;pre&gt;  ...&lt;/pre&gt;
&lt;pre&gt;  $app-&amp;gt;finish(function () use ($app) {
    // check format
    $format = $app-&amp;gt;request-&amp;gt;getQuery(&#39;format&#39;, &#39;string&#39;, &#39;json&#39;);
    switch ($format) {
      case &#39;json&#39;: 
        print(json_encode($app-&amp;gt;result-&amp;gt;data));
        break;
      case &#39;xml&#39;:
        $xml = new SimpleXMLElement(&#39;&lt;root&gt;&#39;);
        array_walk_recursive($app-&amp;gt;result-&amp;gt;data, array ($xml, &#39;addChild&#39;));
        print $xml-&amp;gt;asXML();
        break;
    }
  });&lt;/root&gt;&lt;/pre&gt;
&lt;div&gt;
&amp;nbsp;&amp;nbsp;&lt;/div&gt;
3. use api with .json | .xml&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;$ curl http://site/api/user/1&lt;/pre&gt;
&lt;pre&gt;$ {json: data}&lt;/pre&gt;
&lt;pre&gt;$ curl http://site/api/user/1.json&lt;/pre&gt;
&lt;pre&gt;$ {json: data}&lt;/pre&gt;
&lt;pre&gt;$ curl http://site/api/user/1.xml&lt;/pre&gt;
&lt;pre&gt;$ &amp;lt;xml&amp;gt;data&amp;lt;/xml&amp;gt;&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;</description><link>http://vit228.blogspot.com/2013/01/phalcon-set-output-format-for-phalcon.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-1566052744466789074</guid><pubDate>Thu, 22 Nov 2012 14:34:00 +0000</pubDate><atom:updated>2012-11-22T18:34:39.658+04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">mysql</category><category domain="http://www.blogger.com/atom/ns#">settings</category><category domain="http://www.blogger.com/atom/ns#">utf-8</category><title>mysql: set utf-8 by default</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;pre&gt;$ cd /etc/mysql
$ sudo nano my.cnf
&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;pre&gt;[client]
default-character-set   = utf8

[mysqld]
init_connect=&#39;SET collation_connection = utf8_general_ci&#39;
init_connect=&#39;SET NAMES utf8&#39;
character-set-server=utf8
collation-server=utf8_general_ci
skip-character-set-client-handshake

[mysql]
default-character-set   = utf8
&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;pre&gt;$ sudo service mysql restart
&lt;/pre&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</description><link>http://vit228.blogspot.com/2012/11/mysql-set-utf-8-by-default.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7017927848434571082.post-2012105605900410682</guid><pubDate>Mon, 17 Sep 2012 11:41:00 +0000</pubDate><atom:updated>2012-09-17T15:41:29.039+04:00</atom:updated><title>mysql: Cannot delete or update a parent row: a foreign key constraint fails</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;
Если при удалении пустой таблицы, не содержащей никаких связей и индексов из БД все же возникает ошибка&lt;br /&gt;
&lt;span style=&quot;color: red; font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;MySQL said: Documentation #1217 - Cannot delete or update a parent row: a foreign key constraint fails&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Выполняем следующий запрос:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: blue; font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;SET FOREIGN_KEY_CHECKS =0;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: blue; font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;DROP TABLE IF EXISTS table_name;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: blue; font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;SET FOREIGN_KEY_CHECKS =1;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;
</description><link>http://vit228.blogspot.com/2012/09/mysql-cannot-delete-or-update-parent.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total></item><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=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&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 &quot;$1&quot; ]; then
    echo &quot;Missing parameters.&quot;
    echo &quot;Usage: $0 --midiff, --mi or --buall&quot;
    exit 0
fi

case &quot;$1&quot; in
    &quot;--cc&quot; )
    php symfony cc
    ;;

    &quot;--midiff&quot; )
    php symfony doctrine:generate-migrations-diff
    ;;

    &quot;--mi&quot; )
    php symfony doctrine:migrate
    ;;

    &quot;--buall&quot; )
    php symfony doctrine:build --all-classes
    ;;

    &quot;--busql&quot; )
    php symfony doctrine:build-sql
    ;;

    &quot;--inssql&quot; )
    php symfony doctrine:insert-sql
    ;;

    &quot;--puass&quot; )
    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;</description><link>http://vit228.blogspot.com/2012/01/symfony-short-commands-in-terminal.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>1</thr:total></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(&#39;Category c&#39;)&lt;br /&gt;            -&gt;innerJoin(&#39;c.Product p&#39;)&lt;br /&gt;            -&gt;whereIn(&#39;c.slug&#39;, array(&#39;cpu&#39;, &#39;mainboards&#39;, &#39;ram&#39;, &#39;hdd&#39;, &#39;videocards&#39;, &#39;cases&#39;))&lt;br /&gt;            -&gt;addWhere(&#39;p.is_published = ?&#39;, true)&lt;br /&gt;            -&gt;addOrderBy(&#39;FIELD(c.slug, &quot;cpu&quot;, &quot;mainboards&quot;, &quot;ram&quot;, &quot;hdd&quot;, &quot;videocards&quot;, &quot;cases&quot;)&#39;)&lt;br /&gt;            -&gt;execute()&lt;br /&gt;    ;&lt;br /&gt;&lt;/pre&gt;</description><link>http://vit228.blogspot.com/2011/02/symfony-doctrine-custom-sql-order.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total></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;</description><link>http://vit228.blogspot.com/2011/02/symfony-upload-file-save-original-name.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total></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(&#39;Post p INDEXBY id&#39;)&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 за наводку</description><link>http://vit228.blogspot.com/2011/02/symfony-doctrine-indexby-field.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total></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=&quot;font-weight:bold;&quot;&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(&#39;lang&#39;, &#39;ru&#39;);&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;    $query = &quot;&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` = &#39;&quot;.$lang.&quot;&#39; AND&lt;/div&gt;&lt;div&gt;        substring(`name`,1,1) &lt;&gt; &#39;&#39;&lt;/div&gt;&lt;div&gt;      GROUP BY substring(`name`,1,1)&lt;/div&gt;&lt;div&gt;    &quot;;&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=&quot;font-weight:bold;&quot;&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=&quot;abcList&quot;&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, &#39;@user_list?search=&#39;.$letter.&#39;&amp;amp;pos=start&#39;)?&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=&quot;all&quot; /&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=&quot;font-weight:bold;&quot;&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;</description><link>http://vit228.blogspot.com/2011/01/symfony-doctrine-raw-sql-get-alphabet.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total></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;</description><link>http://vit228.blogspot.com/2010/09/ubuntu-install-lamp-apc-phpmyadmin.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>4</thr:total></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#">admin</category><category domain="http://www.blogger.com/atom/ns#">improvements</category><title>Symfony: backend pager</title><description>&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguu5bvnC3DGkr6Di_OOyL6C23BuhVMMJ5_sTc7bY6zlI6RuR9DCfgcMMYtYDVs8g-xXi5ovruGQQxSg6k1emIBZVgwBlgyb4zgWiN7HhyphenhyphenSacrZTBXKDJRFp_aef4C-9cfn616E7wpKx14/s1600/backend-pager.png&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 264px; height: 154px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguu5bvnC3DGkr6Di_OOyL6C23BuhVMMJ5_sTc7bY6zlI6RuR9DCfgcMMYtYDVs8g-xXi5ovruGQQxSg6k1emIBZVgwBlgyb4zgWiN7HhyphenhyphenSacrZTBXKDJRFp_aef4C-9cfn616E7wpKx14/s400/backend-pager.png&quot; border=&quot;0&quot; alt=&quot;&quot;id=&quot;BLOGGER_PHOTO_ID_5519399502741111650&quot; /&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 = $(&#39;.sf_admin_pagination&#39;).html();&lt;br /&gt;  if (pager) {&lt;br /&gt;    var re = /(\s+)(\d+)(\s)+/;&lt;br /&gt;    var newstr = pager.replace(re, &quot;&lt;span class=\&quot;currentPage\&quot;&gt;$2&lt;/span&gt;&quot;);&lt;br /&gt;    $(&#39;.sf_admin_pagination&#39;).html(newstr);&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;</description><link>http://vit228.blogspot.com/2010/09/symfony-backend-pager.html</link><author>noreply@blogger.com (Vit228)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguu5bvnC3DGkr6Di_OOyL6C23BuhVMMJ5_sTc7bY6zlI6RuR9DCfgcMMYtYDVs8g-xXi5ovruGQQxSg6k1emIBZVgwBlgyb4zgWiN7HhyphenhyphenSacrZTBXKDJRFp_aef4C-9cfn616E7wpKx14/s72-c/backend-pager.png" height="72" width="72"/><thr:total>1</thr:total></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=&quot;font-weight:bold;&quot;&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(&#39;Config&#39;)-&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=&quot;font-weight:bold;&quot;&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(&#39;Config&#39;)-&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=&quot;font-weight:bold;&quot;&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(&#39;sf_upload_dir&#39;).&#39;/&#39;.myConfig::get(&#39;posts_dir&#39;, &#39;posts&#39;);&lt;br /&gt;&#39;max_size&#39; =&gt; myConfig::get(&#39;post_max_icon_size&#39;, &#39;10&#39;, &#39;size in KBytes&#39;)*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=&quot;font-weight:bold;&quot;&gt;backend_dev.php/config&lt;/span&gt;</description><link>http://vit228.blogspot.com/2009/12/symfony-settings.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total></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>2013-10-09T11:53:38.407+04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">slug</category><category domain="http://www.blogger.com/atom/ns#">symfony</category><title>Symfony: Doctrine slugify кириллица</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;span style=&quot;font-weight: bold;&quot;&gt;/lib/Slugify.class.php&lt;/span&gt;&lt;br /&gt;
&lt;pre&gt;
&lt;/pre&gt;
&lt;pre&gt;class SlugifyClass {
  static function Slugify($title) {
    $gost = array(
     &quot;Є&quot;=&amp;gt;&quot;EH&quot;,&quot;І&quot;=&amp;gt;&quot;I&quot;,&quot;і&quot;=&amp;gt;&quot;i&quot;,&quot;№&quot;=&amp;gt;&quot;#&quot;,&quot;є&quot;=&amp;gt;&quot;eh&quot;,
     &quot;А&quot;=&amp;gt;&quot;A&quot;,&quot;Б&quot;=&amp;gt;&quot;B&quot;,&quot;В&quot;=&amp;gt;&quot;V&quot;,&quot;Г&quot;=&amp;gt;&quot;G&quot;,&quot;Д&quot;=&amp;gt;&quot;D&quot;,
     &quot;Е&quot;=&amp;gt;&quot;E&quot;,&quot;Ё&quot;=&amp;gt;&quot;JO&quot;,&quot;Ж&quot;=&amp;gt;&quot;ZH&quot;,
     &quot;З&quot;=&amp;gt;&quot;Z&quot;,&quot;И&quot;=&amp;gt;&quot;I&quot;,&quot;Й&quot;=&amp;gt;&quot;JJ&quot;,&quot;К&quot;=&amp;gt;&quot;K&quot;,&quot;Л&quot;=&amp;gt;&quot;L&quot;,
     &quot;М&quot;=&amp;gt;&quot;M&quot;,&quot;Н&quot;=&amp;gt;&quot;N&quot;,&quot;О&quot;=&amp;gt;&quot;O&quot;,&quot;П&quot;=&amp;gt;&quot;P&quot;,&quot;Р&quot;=&amp;gt;&quot;R&quot;,
     &quot;С&quot;=&amp;gt;&quot;S&quot;,&quot;Т&quot;=&amp;gt;&quot;T&quot;,&quot;У&quot;=&amp;gt;&quot;U&quot;,&quot;Ф&quot;=&amp;gt;&quot;F&quot;,&quot;Х&quot;=&amp;gt;&quot;KH&quot;,
     &quot;Ц&quot;=&amp;gt;&quot;C&quot;,&quot;Ч&quot;=&amp;gt;&quot;CH&quot;,&quot;Ш&quot;=&amp;gt;&quot;SH&quot;,&quot;Щ&quot;=&amp;gt;&quot;SHH&quot;,&quot;Ъ&quot;=&amp;gt;&quot;&#39;&quot;,
     &quot;Ы&quot;=&amp;gt;&quot;Y&quot;,&quot;Ь&quot;=&amp;gt;&quot;&quot;,&quot;Э&quot;=&amp;gt;&quot;EH&quot;,&quot;Ю&quot;=&amp;gt;&quot;YU&quot;,&quot;Я&quot;=&amp;gt;&quot;YA&quot;,
     &quot;а&quot;=&amp;gt;&quot;a&quot;,&quot;б&quot;=&amp;gt;&quot;b&quot;,&quot;в&quot;=&amp;gt;&quot;v&quot;,&quot;г&quot;=&amp;gt;&quot;g&quot;,&quot;д&quot;=&amp;gt;&quot;d&quot;,
     &quot;е&quot;=&amp;gt;&quot;e&quot;,&quot;ё&quot;=&amp;gt;&quot;jo&quot;,&quot;ж&quot;=&amp;gt;&quot;zh&quot;,
     &quot;з&quot;=&amp;gt;&quot;z&quot;,&quot;и&quot;=&amp;gt;&quot;i&quot;,&quot;й&quot;=&amp;gt;&quot;jj&quot;,&quot;к&quot;=&amp;gt;&quot;k&quot;,&quot;л&quot;=&amp;gt;&quot;l&quot;,
     &quot;м&quot;=&amp;gt;&quot;m&quot;,&quot;н&quot;=&amp;gt;&quot;n&quot;,&quot;о&quot;=&amp;gt;&quot;o&quot;,&quot;п&quot;=&amp;gt;&quot;p&quot;,&quot;р&quot;=&amp;gt;&quot;r&quot;,
     &quot;с&quot;=&amp;gt;&quot;s&quot;,&quot;т&quot;=&amp;gt;&quot;t&quot;,&quot;у&quot;=&amp;gt;&quot;u&quot;,&quot;ф&quot;=&amp;gt;&quot;f&quot;,&quot;х&quot;=&amp;gt;&quot;kh&quot;,
     &quot;ц&quot;=&amp;gt;&quot;c&quot;,&quot;ч&quot;=&amp;gt;&quot;ch&quot;,&quot;ш&quot;=&amp;gt;&quot;sh&quot;,&quot;щ&quot;=&amp;gt;&quot;shh&quot;,&quot;ъ&quot;=&amp;gt;&quot;&quot;,
     &quot;ы&quot;=&amp;gt;&quot;y&quot;,&quot;ь&quot;=&amp;gt;&quot;&quot;,&quot;э&quot;=&amp;gt;&quot;eh&quot;,&quot;ю&quot;=&amp;gt;&quot;yu&quot;,&quot;я&quot;=&amp;gt;&quot;ya&quot;,&quot;«&quot;=&amp;gt;&quot;&quot;,&quot;»&quot;=&amp;gt;&quot;&quot;,&quot;—&quot;=&amp;gt;&quot;-&quot;,&quot; &quot;=&amp;gt;&quot;-&quot;
    );

    $iso = array(
     &quot;Є&quot;=&amp;gt;&quot;YE&quot;,&quot;І&quot;=&amp;gt;&quot;I&quot;,&quot;Ѓ&quot;=&amp;gt;&quot;G&quot;,&quot;і&quot;=&amp;gt;&quot;i&quot;,&quot;№&quot;=&amp;gt;&quot;#&quot;,&quot;є&quot;=&amp;gt;&quot;ye&quot;,&quot;ѓ&quot;=&amp;gt;&quot;g&quot;,
     &quot;А&quot;=&amp;gt;&quot;A&quot;,&quot;Б&quot;=&amp;gt;&quot;B&quot;,&quot;В&quot;=&amp;gt;&quot;V&quot;,&quot;Г&quot;=&amp;gt;&quot;G&quot;,&quot;Д&quot;=&amp;gt;&quot;D&quot;,
     &quot;Е&quot;=&amp;gt;&quot;E&quot;,&quot;Ё&quot;=&amp;gt;&quot;YO&quot;,&quot;Ж&quot;=&amp;gt;&quot;ZH&quot;,
     &quot;З&quot;=&amp;gt;&quot;Z&quot;,&quot;И&quot;=&amp;gt;&quot;I&quot;,&quot;Й&quot;=&amp;gt;&quot;J&quot;,&quot;К&quot;=&amp;gt;&quot;K&quot;,&quot;Л&quot;=&amp;gt;&quot;L&quot;,
     &quot;М&quot;=&amp;gt;&quot;M&quot;,&quot;Н&quot;=&amp;gt;&quot;N&quot;,&quot;О&quot;=&amp;gt;&quot;O&quot;,&quot;П&quot;=&amp;gt;&quot;P&quot;,&quot;Р&quot;=&amp;gt;&quot;R&quot;,
     &quot;С&quot;=&amp;gt;&quot;S&quot;,&quot;Т&quot;=&amp;gt;&quot;T&quot;,&quot;У&quot;=&amp;gt;&quot;U&quot;,&quot;Ф&quot;=&amp;gt;&quot;F&quot;,&quot;Х&quot;=&amp;gt;&quot;X&quot;,
     &quot;Ц&quot;=&amp;gt;&quot;C&quot;,&quot;Ч&quot;=&amp;gt;&quot;CH&quot;,&quot;Ш&quot;=&amp;gt;&quot;SH&quot;,&quot;Щ&quot;=&amp;gt;&quot;SHH&quot;,&quot;Ъ&quot;=&amp;gt;&quot;&#39;&quot;,
     &quot;Ы&quot;=&amp;gt;&quot;Y&quot;,&quot;Ь&quot;=&amp;gt;&quot;&quot;,&quot;Э&quot;=&amp;gt;&quot;E&quot;,&quot;Ю&quot;=&amp;gt;&quot;YU&quot;,&quot;Я&quot;=&amp;gt;&quot;YA&quot;,
     &quot;а&quot;=&amp;gt;&quot;a&quot;,&quot;б&quot;=&amp;gt;&quot;b&quot;,&quot;в&quot;=&amp;gt;&quot;v&quot;,&quot;г&quot;=&amp;gt;&quot;g&quot;,&quot;д&quot;=&amp;gt;&quot;d&quot;,
     &quot;е&quot;=&amp;gt;&quot;e&quot;,&quot;ё&quot;=&amp;gt;&quot;yo&quot;,&quot;ж&quot;=&amp;gt;&quot;zh&quot;,
     &quot;з&quot;=&amp;gt;&quot;z&quot;,&quot;и&quot;=&amp;gt;&quot;i&quot;,&quot;й&quot;=&amp;gt;&quot;j&quot;,&quot;к&quot;=&amp;gt;&quot;k&quot;,&quot;л&quot;=&amp;gt;&quot;l&quot;,
     &quot;м&quot;=&amp;gt;&quot;m&quot;,&quot;н&quot;=&amp;gt;&quot;n&quot;,&quot;о&quot;=&amp;gt;&quot;o&quot;,&quot;п&quot;=&amp;gt;&quot;p&quot;,&quot;р&quot;=&amp;gt;&quot;r&quot;,
     &quot;с&quot;=&amp;gt;&quot;s&quot;,&quot;т&quot;=&amp;gt;&quot;t&quot;,&quot;у&quot;=&amp;gt;&quot;u&quot;,&quot;ф&quot;=&amp;gt;&quot;f&quot;,&quot;х&quot;=&amp;gt;&quot;x&quot;,
     &quot;ц&quot;=&amp;gt;&quot;c&quot;,&quot;ч&quot;=&amp;gt;&quot;ch&quot;,&quot;ш&quot;=&amp;gt;&quot;sh&quot;,&quot;щ&quot;=&amp;gt;&quot;shh&quot;,&quot;ъ&quot;=&amp;gt;&quot;&quot;,
     &quot;ы&quot;=&amp;gt;&quot;y&quot;,&quot;ь&quot;=&amp;gt;&quot;&quot;,&quot;э&quot;=&amp;gt;&quot;e&quot;,&quot;ю&quot;=&amp;gt;&quot;yu&quot;,&quot;я&quot;=&amp;gt;&quot;ya&quot;,&quot;«&quot;=&amp;gt;&quot;&quot;,&quot;»&quot;=&amp;gt;&quot;&quot;,&quot;—&quot;=&amp;gt;&quot;-&quot;,&quot; &quot;=&amp;gt;&quot;-&quot;
    );

    $rtl_standard = sfConfig::get(&#39;rtl_standard&#39;, &#39;gost&#39;) ;

    //to lower case

    $title = mb_strtolower($title, &#39;UTF-8&#39;);
    
    switch ($rtl_standard) {
      case &#39;off&#39;:
          return $title;
      case &#39;gost&#39;:
          $out = trim(strtr($title, $gost), &#39;-&#39;);
      default:
          $out = trim(strtr($title, $iso), &#39;-&#39;);
    }
    
    // clean slug
    $out = preg_replace(&#39;/[^a-z0-9\-]+/i&#39;, &#39;&#39;, $out);
    return $out;
  }
}
&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Использование&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;Post:
  actAs:
    Timestampable: ~
    Taggable: ~
    Sluggable:
      unique: true
      fields: [title]
      canUpdate: true
      builder: [SlugifyClass, Slugify]&lt;/pre&gt;
&lt;/div&gt;
</description><link>http://vit228.blogspot.com/2009/10/symfony-doctrine-slugify.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>5</thr:total></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#">Doctrine</category><category domain="http://www.blogger.com/atom/ns#">symfony</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(&#39;p.*&#39;)&lt;br /&gt;      -&gt;addSelect(&#39;(SELECT count(*) FROM PostComments pc WHERE pc.post_id = p.id) as comments_count&#39;)&lt;br /&gt;      -&gt;from(&#39;Post p&#39;)&lt;br /&gt;      -&gt;where(&#39;p.is_published&#39;, true)&lt;br /&gt;      -&gt;orderBy(&#39;comments_count DESC&#39;)&lt;br /&gt;      -&gt;addOrderBy(&#39;d.created_at DESC&#39;)&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;</description><link>http://vit228.blogspot.com/2009/09/symfony-doctrine-order-by-calculated.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>2</thr:total></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#">htaccess</category><category domain="http://www.blogger.com/atom/ns#">symfony</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;</description><link>http://vit228.blogspot.com/2009/08/symfony-avoid-trailing-slash-problem.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>1</thr:total></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#">date</category><category domain="http://www.blogger.com/atom/ns#">symfony</category><title>Symfony: date selector (выбор даты рождения)</title><description>Нас не устраивает стандартный выбор даты в виде 3х листбоксов в формате месяц/день/год, да еще и месяцы указаны цифрами, что вызывает массу затруднений.&lt;br /&gt;Мы хотим такой вид:&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKvxWmPcfKv3X-ZPLPqzLjXIIRMRV3ReZHGJ8Aa-hGKpcZYucaWRuGqrHxLYnb6FjByO1g8LKOzyNFDlXkcyvv-5ND-OWUPO70sfszs5ujjfrLU1jYeRugZDZCL4p2yI1-606nDqbV8Go/s1600-h/birth-date.gif&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 333px; height: 118px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKvxWmPcfKv3X-ZPLPqzLjXIIRMRV3ReZHGJ8Aa-hGKpcZYucaWRuGqrHxLYnb6FjByO1g8LKOzyNFDlXkcyvv-5ND-OWUPO70sfszs5ujjfrLU1jYeRugZDZCL4p2yI1-606nDqbV8Go/s400/birth-date.gif&quot; border=&quot;0&quot; alt=&quot;&quot;id=&quot;BLOGGER_PHOTO_ID_5373271006971532770&quot; /&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;      &#39;id&#39;           =&gt; new sfWidgetFormInputHidden(),&lt;br /&gt;      &#39;city&#39;         =&gt; new sfWidgetFormInput(),&lt;br /&gt;      &#39;birthday&#39;     =&gt; new sfWidgetFormI18nDate(&lt;br /&gt;        array(&lt;br /&gt;          &#39;culture&#39; =&gt; &#39;ru&#39;,&lt;br /&gt;          &#39;format&#39;  =&gt; &#39;%day%.%month%.%year%&#39;,&lt;br /&gt;          &#39;years&#39;   =&gt; $years_list,&lt;br /&gt;        ),&lt;br /&gt;        array()&lt;br /&gt;      ),&lt;br /&gt;&lt;/pre&gt;</description><link>http://vit228.blogspot.com/2009/08/symfony.html</link><author>noreply@blogger.com (Vit228)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKvxWmPcfKv3X-ZPLPqzLjXIIRMRV3ReZHGJ8Aa-hGKpcZYucaWRuGqrHxLYnb6FjByO1g8LKOzyNFDlXkcyvv-5ND-OWUPO70sfszs5ujjfrLU1jYeRugZDZCL4p2yI1-606nDqbV8Go/s72-c/birth-date.gif" height="72" width="72"/><thr:total>0</thr:total></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#">upload</category><category domain="http://www.blogger.com/atom/ns#">widget</category><title>Symfony: sfWidgetFormInputFileEditable IE broken image</title><description>Положим, что мы хотим позволить пользователю прикреплять картинку к своему профилю.&lt;br /&gt;Обратившись к JOBEET находим решение - виджет &lt;span style=&quot;font-weight: bold;&quot;&gt;sfWidgetFormInputFileEditable&lt;span style=&quot;font-style: italic;&quot;&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;  &#39;id&#39;           =&gt; new sfWidgetFormInputHidden(),&lt;br /&gt;  ...&lt;br /&gt;  &#39;avatar&#39;       =&gt; new sfWidgetFormInputFileEditable(array(&lt;br /&gt;    &#39;label&#39;     =&gt; &#39;Ваш аватар&#39;,&lt;br /&gt;    &#39;file_src&#39;  =&gt; &#39;/uploads/avatars/&#39;.$this-&gt;getObject()-&gt;getAvatar(),&lt;br /&gt;    &#39;is_image&#39;  =&gt; true,&lt;br /&gt;    &#39;edit_mode&#39; =&gt; !$this-&gt;isNew(),&lt;br /&gt;  )),&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Однако вскоре мы обнаруживаем, что когда пользователь не создает. а редактирует свой профиль, и при этом аватар у него не загружен, в форме появляется битый рисунок и предложение удалить несуществующую картинку:&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1xl6VXp4vuPNq-24nQX9ujOx8CkmCcZwWInhTR4nkU-mRjSwvXDA2OzrBEhUPO9z1N8qHnqtdxKt3ysH3DjHQSEpGOwQEjEgF6-2no7mkqEXCdYwgvbtt3VTeLxPmuuGDil77w_WTT34/s1600-h/brocken-image.gif&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 333px; height: 118px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1xl6VXp4vuPNq-24nQX9ujOx8CkmCcZwWInhTR4nkU-mRjSwvXDA2OzrBEhUPO9z1N8qHnqtdxKt3ysH3DjHQSEpGOwQEjEgF6-2no7mkqEXCdYwgvbtt3VTeLxPmuuGDil77w_WTT34/s400/brocken-image.gif&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5373266726140922898&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Решение проблемы:&lt;br /&gt;&lt;pre&gt;   &#39;avatar&#39;       =&gt; new sfWidgetFormInputFileEditable(array(&lt;br /&gt;     &#39;label&#39;     =&gt; &#39;Avatar for forum, blog, comments, etc...&#39;,&lt;br /&gt;     &#39;file_src&#39;  =&gt; &#39;/uploads/avatars/&#39;.$this-&gt;getObject()-&gt;getAvatar(),&lt;br /&gt;     &#39;is_image&#39;  =&gt; true,&lt;br /&gt;     &lt;span style=&quot;font-weight: bold;&quot;&gt;&#39;edit_mode&#39; =&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[&#39;avatar&#39;] = new sfValidatorFile(array(&lt;br /&gt;      &#39;required&#39;   =&gt; false,&lt;br /&gt;      &#39;path&#39;       =&gt; sfConfig::get(&#39;sf_upload_dir&#39;).&#39;/avatars&#39;,&lt;br /&gt;      &#39;mime_types&#39; =&gt; &#39;web_images&#39;,&lt;br /&gt;      &#39;max_size&#39; =&gt; &#39;40960&#39;, //(40KB in bytes)&lt;br /&gt;    ));&lt;/pre&gt;</description><link>http://vit228.blogspot.com/2009/08/symfony-sfwidgetforminputfileeditable.html</link><author>noreply@blogger.com (Vit228)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1xl6VXp4vuPNq-24nQX9ujOx8CkmCcZwWInhTR4nkU-mRjSwvXDA2OzrBEhUPO9z1N8qHnqtdxKt3ysH3DjHQSEpGOwQEjEgF6-2no7mkqEXCdYwgvbtt3VTeLxPmuuGDil77w_WTT34/s72-c/brocken-image.gif" height="72" width="72"/><thr:total>3</thr:total></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#">application</category><category domain="http://www.blogger.com/atom/ns#">subdomain</category><category domain="http://www.blogger.com/atom/ns#">symfony</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__).&#39;/../config/ProjectConfiguration.class.php&#39;);&lt;br /&gt;&lt;br /&gt;// get the domain parts as an array&lt;br /&gt;@list($tld, $domain, $subdomain, $subdomain2) = array_reverse(explode(&#39;.&#39;, $_SERVER[&#39;HTTP_HOST&#39;]));&lt;br /&gt;&lt;br /&gt;// determine which subdomain we&#39;re looking at&lt;br /&gt;$app = ($subdomain == &#39;webadmin&#39;) ? &#39;backend&#39; : $subdomain;&lt;br /&gt;$app = (empty($app) || $app == &#39;www&#39; ) ? &#39;frontend&#39; : $app;&lt;br /&gt;$env = (empty($subdomain2) || $subdomain2 == &#39;www&#39;) ? &#39;prod&#39; : $subdomain2;&lt;br /&gt;&lt;br /&gt;// determine which app to load based on subdomain&lt;br /&gt;if (!is_dir(realpath(dirname(__FILE__).&#39;/..&#39;).&#39;/apps/&#39;.$app))&lt;br /&gt;{&lt;br /&gt; $configuration = ProjectConfiguration::getApplicationConfiguration(&#39;frontend&#39;, &#39;prod&#39;, 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=&quot;http://blog.mirthlab.com/2008/03/04/dynamically-loading-symfony-applications-via-subdomains/&quot;&gt;Dynamically Loading Symfony Applications Via Subdomains&lt;/a&gt;</description><link>http://vit228.blogspot.com/2009/05/symfony-applications-as-subdomains.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total></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#">propel</category><category domain="http://www.blogger.com/atom/ns#">query</category><category domain="http://www.blogger.com/atom/ns#">symfony</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 = &#39;&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;   &#39;;&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...)</description><link>http://vit228.blogspot.com/2009/04/symfony-raw-query-get-years-list-for.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>2</thr:total></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#">backend</category><category domain="http://www.blogger.com/atom/ns#">filter</category><category domain="http://www.blogger.com/atom/ns#">symfony</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, &#39;admin.build_criteria&#39;), $criteria);&lt;br /&gt;   $criteria = $event-&gt;getReturnValue();&lt;br /&gt;&lt;br /&gt;   if (!empty($filters[&#39;title&#39;][&#39;text&#39;]))&lt;br /&gt;   {&lt;br /&gt;     //добавим так же фильтр по полю CONTENT&lt;br /&gt;     $c1 = $criteria-&gt;getNewCriterion(PostPeer::TITLE, &#39;%&#39;.$filters[&#39;title&#39;][&#39;text&#39;].&#39;%&#39;, Criteria::LIKE);&lt;br /&gt;     $c2 = $criteria-&gt;getNewCriterion(PostPeer::CONTENT, &#39;%&#39;.$filters[&#39;title&#39;][&#39;text&#39;].&#39;%&#39;, 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;</description><link>http://vit228.blogspot.com/2009/04/symfony-filter-by-2-fields-in-backend.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>1</thr:total></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#">jQuery</category><category domain="http://www.blogger.com/atom/ns#">symfony1.2</category><title>Symfony: add jQuery to helper</title><description>Положим что наш самодельный helper должен использовать jQuery, загружен jQuery или нет, мы не знаем, поэтому самое простое в начале скрипта сделать&lt;br /&gt;&lt;pre&gt;sfContext::getInstance()-&gt;getResponse()-&gt;addJavascript(&#39;jq/jquery-1.3.2.min.js&#39;);&lt;/pre&gt;&lt;br /&gt;Но это может привести к многократной загрузке ядра jQuery браузером пользователя.&lt;br /&gt;Что бы избежать этого используем простую проверку.&lt;br /&gt;&lt;pre&gt;  $jQueryPath = &#39;jq/jquery-1.3.2.min.js&#39;;&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;</description><link>http://vit228.blogspot.com/2009/04/symfony-add-jquery-to-helper.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total></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#">php</category><category domain="http://www.blogger.com/atom/ns#">usefull</category><category domain="http://www.blogger.com/atom/ns#">utf-8</category><title>PHP substr + utf-8</title><description>Положим нам надо в списке показывать кусок сообщения длиной не более 100символов, если сообщение больше 100символов, в конце добавить троеточие.&lt;br /&gt;В кодировке UTF простое обрезание строки &lt;span style=&quot;font-weight: bold;&quot;&gt;substr($str, 0, 100)&lt;/span&gt;, приводит к появлению нераспознанных символов. Нам помогут функции &lt;span style=&quot;font-weight: bold;&quot;&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, &#39;utf-8&#39;).&lt;br /&gt;    (mb_strlen($str, &#39;utf-8&#39;) &gt; 100 ? &#39;...&#39; : &#39;&#39;);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;</description><link>http://vit228.blogspot.com/2009/04/php-substr-utf-8.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>5</thr:total></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#">admin</category><category domain="http://www.blogger.com/atom/ns#">embedded</category><category domain="http://www.blogger.com/atom/ns#">forms</category><category domain="http://www.blogger.com/atom/ns#">symfony</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: &#39;true&#39;}&lt;br /&gt;    rgt:          { type: integer, required: false, default: 0, nestedSetRightKey: &#39;true&#39;}&lt;br /&gt;    scope:        { type: integer, required: false, default: 0, treeScopeKey: &#39;true&#39;}&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;      &#39;category_id&#39;  =&gt; new sfWidgetFormPropelChoice(array(&#39;model&#39; =&gt; &#39;Category&#39;, &#39;add_empty&#39; =&gt; false)),&lt;br /&gt;      &#39;id&#39;           =&gt; new sfWidgetFormInputHidden(),&lt;br /&gt;      &#39;name&#39;         =&gt; new sfWidgetFormInput(),&lt;br /&gt;      &#39;price1&#39;       =&gt; new sfWidgetFormInput(),&lt;br /&gt;      &#39;price2&#39;       =&gt; new sfWidgetFormInput(),&lt;br /&gt;      &#39;pic&#39;          =&gt; new myWidgetFormInputFileEditable(),&lt;br /&gt;      &#39;is_published&#39; =&gt; new sfWidgetFormInputCheckbox(),&lt;br /&gt;    ));&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    $this-&gt;setValidators(array(&lt;br /&gt;      &#39;id&#39;           =&gt; new sfValidatorPropelChoice(array(&#39;model&#39; =&gt; &#39;Product&#39;, &#39;column&#39; =&gt; &#39;id&#39;, &#39;required&#39; =&gt; false)),&lt;br /&gt;      &#39;name&#39;         =&gt; new sfValidatorString(array(&#39;max_length&#39; =&gt; 255, &#39;required&#39; =&gt; false)),&lt;br /&gt;      &#39;price1&#39;       =&gt; new sfValidatorNumber(array(&#39;required&#39; =&gt; false)),&lt;br /&gt;      &#39;price2&#39;       =&gt; new sfValidatorNumber(array(&#39;required&#39; =&gt; false)),&lt;br /&gt;      &#39;is_published&#39; =&gt; new sfValidatorBoolean(array(&#39;required&#39; =&gt; false)),&lt;br /&gt;      &#39;category_id&#39;  =&gt; new sfValidatorPropelChoice(array(&#39;model&#39; =&gt; &#39;Category&#39;, &#39;column&#39; =&gt; &#39;id&#39;)),&lt;br /&gt;      &#39;pic&#39;          =&gt; new sfValidatorFile(array(&lt;br /&gt;            &#39;required&#39; =&gt; false,&lt;br /&gt;            &#39;max_size&#39; =&gt; &#39;102400&#39;, // bytes (1MB)&lt;br /&gt;            &#39;mime_types&#39; =&gt; array(&#39;image/png&#39;, &#39;image/jpeg&#39;, &#39;image/gif&#39;,)&lt;br /&gt;       )),&lt;br /&gt;    ));&lt;br /&gt;  &lt;br /&gt;    $this-&gt;widgetSchema-&gt;setNameFormat(&#39;product[%s]&#39;);&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(&#39;allow_extra_fields&#39;, true);&lt;br /&gt;    $this-&gt;validatorSchema-&gt;setOption(&#39;filter_extra_fields&#39;, 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(&#39;product_id&#39;, new sfWidgetFormInputHidden());&lt;br /&gt;      $rProductForm-&gt;setWidget(&#39;del_me&#39;, new sfWidgetFormInputCheckbox());&lt;br /&gt;      $rProductForm-&gt;setValidator(&#39;del_me&#39;, new sfValidatorBoolean(array(&#39;required&#39; =&gt; false)));&lt;br /&gt;      $rProductForm-&gt;widgetSchema-&gt;moveField(&#39;del_me&#39;, sfWidgetFormSchema::FIRST);&lt;br /&gt;&lt;br /&gt;      $this-&gt;embedForm(&#39;rProduct-&#39;.$index, $rProductForm);&lt;br /&gt;      $this-&gt;widgetSchema-&gt;setLabel(&#39;rProduct-&#39;.$index, $index+1);&lt;br /&gt;    }&lt;br /&gt;    $rProductForm = new ProductRecommendedForm();&lt;br /&gt;&lt;br /&gt;    $rProductForm-&gt;setWidget(&#39;product_id&#39;, new sfWidgetFormInputHidden());&lt;br /&gt;    //добавляем дополнительный чекбокс, для удаления записи&lt;br /&gt;    $rProductForm-&gt;setWidget(&#39;del_me&#39;, new sfWidgetFormInputCheckbox(&lt;br /&gt;        array(),&lt;br /&gt;        array(&#39;disabled&#39; =&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(&#39;recommend_product_id&#39;, new sfWidgetFormPropelChoice(&lt;br /&gt;          array(&#39;model&#39; =&gt; &#39;Product&#39;, &#39;add_empty&#39; =&gt; true)));&lt;br /&gt;&lt;br /&gt;      $rProductForm-&gt;setDefaults(array(&#39;product_id&#39; =&gt; $this-&gt;getObject()-&gt;getId()));&lt;br /&gt;      //отключим обязательный выбор значения листбокса&lt;br /&gt;      $rProductForm-&gt;setValidator(&#39;recommend_product_id&#39;, new sfValidatorInteger(array(&#39;required&#39; =&gt; false)));&lt;br /&gt;      //переносим чекбокс для удаления записи наверх&lt;br /&gt;      $rProductForm-&gt;widgetSchema-&gt;moveField(&#39;del_me&#39;, sfWidgetFormSchema::FIRST);&lt;br /&gt;&lt;br /&gt;      $this-&gt;embedForm(&#39;new-rec&#39;, $rProductForm);&lt;br /&gt;      $this-&gt;widgetSchema-&gt;setLabel(&#39;new-rec&#39;, &#39;new record&#39;);&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(&#39;sf_root_dir&#39;).DIRECTORY_SEPARATOR.&lt;br /&gt;      sfConfig::get(&#39;sf_web_dir_name&#39;).DIRECTORY_SEPARATOR.sfConfig::get(&#39;sf_upload_dir&#39;);&lt;br /&gt;    $object-&gt;setPic(str_replace($path.&#39;/&#39;, &#39;&#39;, $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(&#39;sf_root_dir&#39;).&#39;/&#39;.&lt;br /&gt;      sfConfig::get(&#39;sf_web_dir_name&#39;).&#39;/&#39;.sfConfig::get(&#39;sf_upload_dir&#39;);&lt;br /&gt;&lt;br /&gt;    if (isset($values[&#39;pic_delete&#39;])){&lt;br /&gt;      $currentFile = $path.&#39;/&#39;.$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(&#39;&#39;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    $file = $values[&#39;pic&#39;];&lt;br /&gt;&lt;br /&gt;    if(!empty($file)){&lt;br /&gt;      if (file_exists(sfConfig::get(&#39;sf_upload_dir&#39;).&#39;/&#39;.$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(&#39;sf_root_dir&#39;).DIRECTORY_SEPARATOR.sfConfig::get(&#39;sf_web_dir_name&#39;).DIRECTORY_SEPARATOR.sfConfig::get(&#39;sf_upload_dir&#39;);&lt;br /&gt;      $file-&gt;save($path.&#39;/&#39;.$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=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtaXybRwnD46NB18f1R9cEMF1JWGZAzO9hnGVt_EiP79ISS4yUoVqbkxQmfDwaYRsUhPwYi1JwcRgep7RWkyDCdwIWOe5h4TfeKGD5ym2tp5GDmtG_Pm8TG0pLrU3rslgrYqy5J31lrVM/s1600-h/sf-tabular-forms-1.gif&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 190px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtaXybRwnD46NB18f1R9cEMF1JWGZAzO9hnGVt_EiP79ISS4yUoVqbkxQmfDwaYRsUhPwYi1JwcRgep7RWkyDCdwIWOe5h4TfeKGD5ym2tp5GDmtG_Pm8TG0pLrU3rslgrYqy5J31lrVM/s400/sf-tabular-forms-1.gif&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5322081246885661602&quot; border=&quot;0&quot; /&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=&quot;sf_admin_form&quot;&amp;gt;&lt;br /&gt;  &amp;lt;?php echo form_tag_for($form, &#39;@product&#39;) ?&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() ? &#39;new&#39; : &#39;edit&#39;) as $fieldset =&amp;gt; $fields): ?&amp;gt;&lt;br /&gt;      &amp;lt;?php include_partial(&#39;product/form_fieldset&#39;, array(&#39;product&#39; =&amp;gt; $product, &#39;form&#39; =&amp;gt; $form, &#39;fields&#39; =&amp;gt; $fields, &#39;fieldset&#39; =&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=&quot;sf_fieldset_recommended_products&quot;&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][&#39;id&#39;]-&amp;gt;render() ?&amp;gt;&lt;br /&gt;        &amp;lt;?php echo $form[$index][&#39;product_id&#39;]-&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][&#39;del_me&#39;]-&amp;gt;renderError() ?&amp;gt;&amp;lt;?php echo $form[$index][&#39;del_me&#39;]-&amp;gt;render() ?&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;td&amp;gt;&amp;lt;?php echo $form[$index][&#39;recommend_product_id&#39;]-&amp;gt;renderError() ?&amp;gt;&amp;lt;?php echo $form[$index][&#39;recommend_product_id&#39;]-&amp;gt;render() ?&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;td&amp;gt;&amp;lt;?php echo $form[$index][&#39;note&#39;]-&amp;gt;renderError() ?&amp;gt;&amp;lt;?php echo $form[$index][&#39;note&#39;]-&amp;gt;render() ?&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;td&amp;gt;&amp;lt;?php echo $form[$index][&#39;pos&#39;]-&amp;gt;renderError() ?&amp;gt;&amp;lt;?php echo $form[$index][&#39;pos&#39;]-&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(&#39;product/form_actions&#39;, array(&#39;product&#39; =&amp;gt; $product, &#39;form&#39; =&amp;gt; $form, &#39;configuration&#39; =&amp;gt; $configuration, &#39;helper&#39; =&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=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi43hvIb31E_tazoG278COgl9mM1wp1YlIHyW0Dtj8PhnOhyphenhyphenYDzEwt0bvD0J3ECNXu9bnsjSkTg6UlyH8feAVeGq4_cskRuHNZ5aNlZNznAtLdaonXnsSryWZqPvfmvU6URw4MsFyrCfEE/s1600-h/sf-tabular-forms-2.gif&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 142px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi43hvIb31E_tazoG278COgl9mM1wp1YlIHyW0Dtj8PhnOhyphenhyphenYDzEwt0bvD0J3ECNXu9bnsjSkTg6UlyH8feAVeGq4_cskRuHNZ5aNlZNznAtLdaonXnsSryWZqPvfmvU6URw4MsFyrCfEE/s400/sf-tabular-forms-2.gif&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5322088435455111698&quot; border=&quot;0&quot; /&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][&#39;del_me&#39;])){&lt;br /&gt;          if ($values[$name][&#39;del_me&#39;] == 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, &#39;new-&#39;))&lt;br /&gt;          {&lt;br /&gt;            //именно тут мы сами выступаем в роли валидатора, и если одно из обязательных полей пустое,&lt;br /&gt;            //мы игнорируем новую запись&lt;br /&gt;            $rProduct = $values[$name][&#39;recommend_product_id&#39;];&lt;br /&gt;            $rPos = $values[$name][&#39;pos&#39;];&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;</description><link>http://vit228.blogspot.com/2009/04/symfony-12-tabular-subforms.html</link><author>noreply@blogger.com (Vit228)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtaXybRwnD46NB18f1R9cEMF1JWGZAzO9hnGVt_EiP79ISS4yUoVqbkxQmfDwaYRsUhPwYi1JwcRgep7RWkyDCdwIWOe5h4TfeKGD5ym2tp5GDmtG_Pm8TG0pLrU3rslgrYqy5J31lrVM/s72-c/sf-tabular-forms-1.gif" height="72" width="72"/><thr:total>3</thr:total></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=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&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=&quot;http://www.netservice.ru/symbol2009/&quot;&gt;символ года в виде бумажной коровы (скачать)&lt;/a&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf0c8zmuxwQzoluZeBIl3pLzi6RPpbRPRudqRtna5uamNhRRpsPlxLG73nnEj3wTkq0ieOfs86v56Cv993b-ReVIAJ89ChtaWhIztxZFT-ru_0r_jVqgfG32jb1Nt4uyNGy1ILqpsxyEs/s1600-h/idea_big.jpg&quot;&gt;&lt;img style=&quot;cursor: pointer; width: 320px; height: 249px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf0c8zmuxwQzoluZeBIl3pLzi6RPpbRPRudqRtna5uamNhRRpsPlxLG73nnEj3wTkq0ieOfs86v56Cv993b-ReVIAJ89ChtaWhIztxZFT-ru_0r_jVqgfG32jb1Nt4uyNGy1ILqpsxyEs/s320/idea_big.jpg&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5283666160348078690&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Энжой! :)&lt;/span&gt;</description><link>http://vit228.blogspot.com/2008/12/2009.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf0c8zmuxwQzoluZeBIl3pLzi6RPpbRPRudqRtna5uamNhRRpsPlxLG73nnEj3wTkq0ieOfs86v56Cv993b-ReVIAJ89ChtaWhIztxZFT-ru_0r_jVqgfG32jb1Nt4uyNGy1ILqpsxyEs/s72-c/idea_big.jpg" height="72" width="72"/><thr:total>0</thr:total></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#">generator</category><category domain="http://www.blogger.com/atom/ns#">symfony1.2</category><title>Symfony 1.2: file upload in admin</title><description>Это черновик&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&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(&#39;description&#39;, new myWidgetFormRichTextarea(array(&#39;editor&#39;=&gt;&#39;fck&#39;)));&lt;br /&gt;    $values = $this-&gt;getValues();&lt;br /&gt;    $this-&gt;setWidget(&#39;pic&#39;, new myWidgetFormInputFileEditable(&lt;br /&gt;   array(&lt;br /&gt;        &#39;is_image&#39;      =&gt; true,&lt;br /&gt;        &#39;delete_label&#39;  =&gt; &#39;удалить&#39;&lt;br /&gt;   )));&lt;br /&gt;    //$this-&gt;setWidget(&#39;pic&#39;, new sfWidgetFormInputFile());&lt;br /&gt;    $this-&gt;setWidget(&#39;avatar&#39;, new sfWidgetFormInputFile());&lt;br /&gt;    /* VALIDATORS */&lt;br /&gt;    $this-&gt;setValidators(array(&lt;br /&gt;      &#39;f_name&#39;      =&gt; new sfValidatorString(&lt;br /&gt;          array(),&lt;br /&gt;          array(&#39;required&#39; =&gt; &#39;Обязательное поле&#39;)&lt;br /&gt;      ),&lt;br /&gt;      &#39;l_name&#39;      =&gt; new sfValidatorString(&lt;br /&gt;          array(),&lt;br /&gt;          array(&#39;required&#39; =&gt; &#39;Обязательное поле&#39;)&lt;br /&gt;      ),&lt;br /&gt;      &#39;email&#39;            =&gt; new sfValidatorEmail(&lt;br /&gt;          $options = array(), &lt;br /&gt;          $messages = array(&lt;br /&gt;            &#39;invalid&#39; =&gt; &#39;Введите правильный Email&#39;,&lt;br /&gt;            &#39;required&#39; =&gt; false)&lt;br /&gt;      ),&lt;br /&gt;      &#39;pic&#39;          =&gt; new sfValidatorFile(array(&lt;br /&gt;            &#39;required&#39; =&gt; false,&lt;br /&gt;            &#39;max_size&#39; =&gt; &#39;102400&#39;, // bytes (1MB)&lt;br /&gt;            &#39;mime_types&#39; =&gt; array(&#39;image/png&#39;, &#39;image/jpeg&#39;,) &lt;br /&gt;       )),&lt;br /&gt;    ));&lt;br /&gt;    &lt;br /&gt;    //$this-&gt;widgetSchema-&gt;setNameFormat(&#39;%s&#39;);&lt;br /&gt;&lt;br /&gt;    $this-&gt;validatorSchema-&gt;setOption(&#39;allow_extra_fields&#39;, true);&lt;br /&gt;    $this-&gt;validatorSchema-&gt;setOption(&#39;filter_extra_fields&#39;, 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(&#39;sf_root_dir&#39;).DIRECTORY_SEPARATOR.&lt;br /&gt;      sfConfig::get(&#39;sf_web_dir_name&#39;).DIRECTORY_SEPARATOR.sfConfig::get(&#39;sf_upload_dir&#39;);&lt;br /&gt;    $object-&gt;setPic(str_replace($path.&#39;/&#39;, &#39;&#39;, $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(&#39;sf_root_dir&#39;).&#39;/&#39;.&lt;br /&gt;      sfConfig::get(&#39;sf_web_dir_name&#39;).&#39;/&#39;.sfConfig::get(&#39;sf_upload_dir&#39;);&lt;br /&gt;    &lt;br /&gt;    if (isset($values[&#39;pic_delete&#39;])){&lt;br /&gt;      $currentFile = $path.&#39;/&#39;.$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(&#39;&#39;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    $file = $values[&#39;pic&#39;];&lt;br /&gt;&lt;br /&gt;    if(!empty($file)){&lt;br /&gt;      if (file_exists(sfConfig::get(&#39;sf_upload_dir&#39;).&#39;/&#39;.$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(&#39;sf_root_dir&#39;).DIRECTORY_SEPARATOR.sfConfig::get(&#39;sf_web_dir_name&#39;).DIRECTORY_SEPARATOR.sfConfig::get(&#39;sf_upload_dir&#39;);&lt;br /&gt;      $file-&gt;save($path.&#39;/&#39;.$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=&quot;font-weight:bold;&quot;&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 &quot;_delete&quot; suffix. So, when creating a form,&lt;br /&gt;   * don&#39;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(&#39;type&#39;, &#39;file&#39;);&lt;br /&gt;    $this-&gt;setOption(&#39;needs_multipart&#39;, true);&lt;br /&gt;&lt;br /&gt;    //$this-&gt;addRequiredOption(&#39;file_src&#39;);&lt;br /&gt;    $this-&gt;addOption(&#39;file_src&#39;, &#39;&#39;);&lt;br /&gt;    $this-&gt;addOption(&#39;is_image&#39;, false);&lt;br /&gt;    $this-&gt;addOption(&#39;edit_mode&#39;, true);&lt;br /&gt;    $this-&gt;addOption(&#39;with_delete&#39;, true);&lt;br /&gt;    $this-&gt;addOption(&#39;delete_label&#39;, &#39;remove the current file&#39;);&lt;br /&gt;    $this-&gt;addOption(&#39;template&#39;, &#39;%file% %input% %delete% %delete_label%&#39;);&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(&#39;edit_mode&#39;))&lt;br /&gt;    {&lt;br /&gt;      return $input;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if ($this-&gt;getOption(&#39;with_delete&#39;)){&lt;br /&gt;      $deleteName = &#39;]&#39; == substr($name, -1) ? substr($name, 0, -1).&#39;_delete]&#39; : $name.&#39;_delete&#39;;&lt;br /&gt;      $delete = $this-&gt;renderTag(&#39;input&#39;, array_merge(array(&#39;type&#39; =&gt; &#39;checkbox&#39;, &#39;name&#39; =&gt; $deleteName), $attributes));&lt;br /&gt;      $deleteLabel = $this-&gt;renderContentTag(&#39;span&#39;, $this-&gt;getOption(&#39;delete_label&#39;), array_merge(array(&#39;for&#39; =&gt; $this-&gt;generateId($deleteName))));&lt;br /&gt;    } else {&lt;br /&gt;      $delete = &#39;&#39;;&lt;br /&gt;      $deleteLabel = &#39;&#39;;&lt;br /&gt;    }&lt;br /&gt;    if ($value){&lt;br /&gt;      $picLink = &quot; || &amp;lt;a class=&#39;thickbox&#39; target=&#39;_blank&#39; href=&#39;/uploads/&quot;.$value.&quot;&#39;&amp;gt;show me&amp;lt;/a&amp;gt;&quot;;&lt;br /&gt;    } else {&lt;br /&gt;      $picLink = &quot;&quot;;&lt;br /&gt;      $delete = &#39;&#39;;&lt;br /&gt;      $deleteLabel = &#39;&#39;;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    return strtr($this-&gt;getOption(&#39;template&#39;), array(&lt;br /&gt;      &#39;%input%&#39; =&gt; $input, &lt;br /&gt;      &#39;%delete%&#39; =&gt; $delete, &lt;br /&gt;      &#39;%delete_label%&#39; =&gt; $deleteLabel, &lt;br /&gt;      &#39;%file%&#39; =&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(&#39;is_image&#39;))&lt;br /&gt;    {&lt;br /&gt;      return false !== $value ? $this-&gt;renderTag(&#39;img&#39;, array_merge(array(&#39;src&#39; =&gt; $value)), $attributes) : &#39;&#39;;&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;      return $this-&gt;getOption(&#39;file_src&#39;);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&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;</description><link>http://vit228.blogspot.com/2008/11/symfony-12-file-upload-in-admin.html</link><author>noreply@blogger.com (Vit228)</author><thr:total>0</thr:total></item></channel></rss>