<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>nova blog &#187; Symfony</title>
	<atom:link href="http://blog.tlsys.hu/cimke/symfony/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.tlsys.hu</link>
	<description></description>
	<lastBuildDate>Mon, 17 Oct 2011 19:44:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Symfony IV. rész &#8211; egy form embedder plugin</title>
		<link>http://blog.tlsys.hu/symfony_form_embedder_plugin/</link>
		<comments>http://blog.tlsys.hu/symfony_form_embedder_plugin/#comments</comments>
		<pubDate>Sun, 20 Feb 2011 08:43:41 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Symfony]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.tlsys.hu/?p=483</guid>
		<description><![CDATA[
			
			
			
			
			
			
			Tweet
						
						
			Ebben a bejegyzésemben az előző bejegyzésemben bemutatott form beágyazási technika alapján készített plugint tenném közzé.

A plugin célja, hogy egyszerűsítsen a symfony beágyazási technikáján. Az egyszerűsítés viszont nem minden esetben jobb. Tehát ott érdemes használni, ahol nem visszük túlzásba a beágyazást.   Ha túlságosan egyedi formára kívánjuk hozni, akkor előfordulhat hogy rengeteg módosítás helyett, célszerűbb [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="border:1px solid #808080;background-color:#F0F4F9;">
			<div style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.tlsys.hu%2Fsymfony_form_embedder_plugin%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div>
			<div style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://blog.tlsys.hu/symfony_form_embedder_plugin/"></g:plusone>
			</div>
			<div style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://blog.tlsys.hu/symfony_form_embedder_plugin/"  data-text="Symfony IV. rész &#8211; egy form embedder plugin" data-count="horizontal">Tweet</a>
			</div><div style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://blog.tlsys.hu/symfony_form_embedder_plugin/" data-counter="right"></script></div>			
			<div style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://blog.tlsys.hu/symfony_form_embedder_plugin/"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>Ebben a bejegyzésemben az <a href="symfony_embedded_form/">előző bejegyzésemben</a> bemutatott form beágyazási technika alapján készített plugint tenném közzé.<br />
<span id="more-483"></span><br />
A plugin célja, hogy egyszerűsítsen a symfony beágyazási technikáján. Az egyszerűsítés viszont nem minden esetben jobb. Tehát ott érdemes használni, ahol nem visszük túlzásba a beágyazást. <img src='http://blog.tlsys.hu/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Ha túlságosan egyedi formára kívánjuk hozni, akkor előfordulhat hogy rengeteg módosítás helyett, célszerűbb teljesen tiszta lapról indulni. Akkor pedig az előző bejegyzésem nagyobb segítség, mint ez a plugin.<br />
<strong>A plugin használatának nagyon fontos feltétele, hogy a kapcsolt táblák 1:N kapcsolatban legyenek az adatbázis szerint is. Tehát a beágyazandó táblában legyen meg az idegen kulcs!</strong></p>
<p>Hozzávalók:<br />
<a href="http://blog.tlsys.hu/wp-content/uploads/2011/02/tlsysEmbedderHelperPlugin.tar.gz">A plugin itt található</a><br />
<a href="http://www.symfony-project.org/plugins/sfJqueryReloadedPlugin">sfJqueryReloadedPlugin</a><br />
<a href="http://book.cakephp.org/hu/view/3/A-Kézikönyv#!/hu/view/640/Set">CakePHP set osztálya</a>, <a href="http://blog.tlsys.hu/wp-content/uploads/2011/02/set.zip">a symfonysított verziót ide tettem fel</a>.</p>
<p>A plugin telepítése:</p>
<ol>
<li>
Miután létrehoztuk a projektünket, a plugin könyvtárba csomagoljuk ki plugint
</li>
<li>
Engedélyezzük a az apps/config/settings.yml fájlban:</p>
<pre class="brush: php; title: ; notranslate">
all:
  enabled_modules:        [default, tlsysEmbedderHelper, stb]
</pre>
<p>Erre azért van szükség, mert az ajaxos hívást kiszolgáló action a pluginba került. Így azt sem kell állandóan újra és újra megírni.
</li>
<li>
A lib/form/BaseFormPropel.class.php származtatása a pluginnban talalhato tlsysEmbedderFormból </p>
<pre class="brush: php; title: ; notranslate">
abstract class BaseFormPropel extends tlsysEmbedderForm
</pre>
</li>
<li>
A szükséges formokkban értéket kell adni a $tlsysEmbeddedForms protected változónak. Egy példa az előző bejegyzésemben található OsztalyFormra.</p>
<pre class="brush: php; title: ; notranslate">
class OsztalyForm extends BaseOsztalyForm
{
  # meg kell adni a beágyazni szándékozott osztály nevét, egyes és többesszámban
  # a többesszám az, ahogy a propel hivatkozik rá
  protected $tlsysEmbeddedForms = array(array('singular'=&gt;'Tanulo', 'plural'=&gt;'Tanulos'));
  public function configure()
  {
  }
}
</pre>
</li>
</ol>
<p>Ezzel a 4 lépéssel ugyanazt értük el, mint az előző bejegyzésemben található litániával.</p>
<p><a href="http://blog.tlsys.hu/wp-content/uploads/2011/02/sandbox-tlsysEmbedderHelperPlugin.tar.gz">A bemutató alkalmazás innen tölthető le</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tlsys.hu/symfony_form_embedder_plugin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony III. rész – beágyazott form</title>
		<link>http://blog.tlsys.hu/symfony_embedded_form/</link>
		<comments>http://blog.tlsys.hu/symfony_embedded_form/#comments</comments>
		<pubDate>Mon, 14 Feb 2011 18:52:25 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Symfony]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.tlsys.hu/?p=461</guid>
		<description><![CDATA[
			
			
			
			
			
			
			Tweet
						
						
			A symfony beágyazott (embedded) form megoldásáról szóló kis szösszenet kerül ide.
A segítségével két, master-detail kapcsolatban álló tábla egyidejű módosítását lehet megvalósítani.

Itt is az első leírásban létrehozott sandbox projektünket fogjuk átszerkeszteni.
Tehát állítsuk be a config könyvtárban lévő adatbázisokhoz tartozó fájlokat (propel.ini és databases.yml) az előzőleg létrehozott sandbox adatbázisra. Majd szerkesszük meg a config/schema.yml fájlt:

propel:
  _attributes:
 [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="border:1px solid #808080;background-color:#F0F4F9;">
			<div style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.tlsys.hu%2Fsymfony_embedded_form%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div>
			<div style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://blog.tlsys.hu/symfony_embedded_form/"></g:plusone>
			</div>
			<div style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://blog.tlsys.hu/symfony_embedded_form/"  data-text="Symfony III. rész – beágyazott form" data-count="horizontal">Tweet</a>
			</div><div style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://blog.tlsys.hu/symfony_embedded_form/" data-counter="right"></script></div>			
			<div style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://blog.tlsys.hu/symfony_embedded_form/"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>A symfony beágyazott (embedded) form megoldásáról szóló kis szösszenet kerül ide.<br />
A segítségével két, master-detail kapcsolatban álló tábla egyidejű módosítását lehet megvalósítani.<br />
<span id="more-461"></span></p>
<p>Itt is az <a href="http://blog.tlsys.hu/symfony-propel-ubuntu-telepit/">első leírásban</a> létrehozott sandbox projektünket fogjuk átszerkeszteni.</p>
<p>Tehát állítsuk be a config könyvtárban lévő adatbázisokhoz tartozó fájlokat (propel.ini és databases.yml) az előzőleg létrehozott sandbox adatbázisra. Majd szerkesszük meg a config/schema.yml fájlt:</p>
<pre class="brush: sql; title: ; notranslate">
propel:
  _attributes:
    package: lib.model
    defaultIdMethod: native
  osztaly:
    _attributes: { phpName: Osztaly }
    id: { phpName: Id, type: INTEGER, size: '11', primaryKey: true, autoIncrement: true, required: true }
    kod: { phpName: Kod, type: CHAR, size: '1', required: true }
    evfolyam: { phpName: Evfolyam, type: INTEGER, size: '11', required: true }
  tanulo:
    _attributes: { phpName: Tanulo }
    id: { phpName: Id, type: INTEGER, size: '11', primaryKey: true, autoIncrement: true, required: true }
    name: { phpName: Name, type: VARCHAR, size: '255', required: true }
    szuletes: { phpName: Szuletes, type: DATE, required: true }
    osztaly_id: { phpName: OsztalyId, type: INTEGER, size: '11', required: false, foreignTable: osztaly, foreignReference: id, onDelete: CASCADE, onUpdate: CASCADE }
    _indexes: { category_id: [osztaly_id] }
</pre>
<p>Majd futtassuk le az alábbi parancsokat is:</p>
<pre class="brush: bash; title: ; notranslate">
# hozzuk létre a formokat, filtereket, modeleket, és a táblákat is generáljuk le
# a kérdésre, miszerint kívánjuk-e hogy felülírja az adatbázisunkat válaszoljunk igennel (Y)
./symfony propel:build-all
# és a két táblánkhoz tartozó admin felületet készítsük el:
./symfony propel:generate-admin frontend osztaly
./symfony propel:generate-admin frontend tanulo
</pre>
<p>Szükségünk lesz egy pluginra, a <a href="http://www.symfony-project.org/plugins/sfJqueryReloadedPlugin">sfJqueryReloadedPlugin</a>ra. A telepítése nem túl bonyolult. Ha az összes plugint engedélyeztük (a config/ProjectConfiguration.class.php fájlban), akkor elég bemásolni a plugin könyvtárba. Mivel a letöltött tömörített fájlban mindenféle kódszámot ír a könyvtárnév végére, így a könnyebb elérhetőség miatt használjuk inkább a sfJqueryReloadedPlugin könyvtárnevet.</p>
<p>A lib/model/Osztaly.php fájlt pedig egészítsük ki az alábbi metódussal</p>
<pre class="brush: php; title: ; notranslate">
public function __toString()
{
  return $this-&gt;evfolyam.'/'.$this-&gt;kod;
}
</pre>
<p>Az apps/frontend/config/routing.yml fájlt is módosítsuk, hogy az osztályok listája jelenjen meg alapértelmezetten.</p>
<pre class="brush: php; title: ; notranslate">
homepage:
  url:   /
  param: { module: osztaly, action: index }
</pre>
<p>Ezzel az alap projektünk elkészült. Lehet listázni, új osztályt felvinni és módosítani. Azonban az osztályhoz még nem tudunk tanulót rögzíteni. Ehhez módosítsuk a lib/form/OsztalyForm.class.php fájlt.<br />
Ez egy hosszabb lélegzetvétel lesz, mert nem aprózom el <img src='http://blog.tlsys.hu/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<pre class="brush: php; title: ; notranslate">
class OsztalyForm extends BaseOsztalyForm
{
   /**
   * a form konfiguralasa
   * hozzaadjuk a tanulokat a formhoz
   * hozzadjuk a hozzaadas gombot (Uj) letrehozo widgetet is.
   */
   public function configure()
  {
    parent::setup();
    $context = sfContext::getInstance();
    $this-&gt;loadHelpers($context);

    $tanulok = $this-&gt;getObject()-&gt;getTanulos();

    //Egy ures formba eltaroljuk az embeddelt TanuloFormokat
    $this-&gt;embedForm('tanulos', new sfForm());
    $count = 0;
    foreach ($tanulok as $tanulo) {
      $this-&gt;addTanulo($count, $tanulo);
      $count ++;
    }

    // a hozzaadas gomb mint egy uj mezo kerul a formunkba
    $this-&gt;widgetSchema['addEmbedform'] = new embedderFormWidget(array(
        'url'=&gt;url_for('osztaly/getEmbedForm'),
        'html_element' =&gt; &quot;.sf_admin_form_field_tanulos table:first&quot;,
        ));
    $this-&gt;widgetSchema-&gt;setLabel('addEmbedform', false);
  }

  /**
   * kulonbozo helperek betoltese
   * Url helper az ajax hivashoz hasznalando helyes url megadasahoz
   * jQueryReloadedPlugin jQuery helpere
   * es a jQuery UI plugin javascript betoltese
   *
   * @param sfContext $context
   */
  public function loadHelpers($context)
  {
    $context-&gt;getConfiguration()-&gt;loadHelpers(array('jQuery','Tag','Url'));
    $context-&gt;getResponse()-&gt;addStyleSheet(sfConfig::get('sf_jquery_web_dir', '/sfJqueryReloadedPlugin') . &quot;/css/ui-lightness/jquery-ui-1.8.2.custom.css&quot;);
    jq_add_plugins_by_name(array('ui'));
  }

  /**
   * A torles link a Tanulo mellett
   *
   * @param string $index
   * @return string
   */
  public function getEmbedFormLabel($index)
  {
    return jq_link_to_function(
      '&lt;span class=&quot;ui-icon ui-icon-trash&quot;&gt;&lt;/span&gt;',
      &quot;jQuery(this).parents('tr:first').remove(); jQuery('#osztaly_tanulos_&quot;.$index.&quot;_id').remove();&quot;,
      array('confirm' =&gt; 'Sure???'));
  }

  /**
   * A Tanulo hozzaadasa az Osztalyhoz
   *
   * Erre akkor is szuksegunk lesz, amikor egy uj tanulot veszunk fel
   *
   * @param string $num
   * @param Tanulo $tanulo
   */
  public function addTanulo($num, $tanulo = null)
  {
    if (!$tanulo)
    {
      $tanulo = new Tanulo();
    }
    $tanulo-&gt;setOsztaly($this-&gt;getObject());
    $form = new TanuloForm($tanulo);
    $form-&gt;getWidgetSchema()-&gt;offsetUnset('osztaly_id');
    $this-&gt;embeddedForms['tanulos']-&gt;embedForm($num, $form);

    // torles link
    $label = $this-&gt;getEmbedFormLabel($num);
    $this-&gt;embeddedForms['tanulos']-&gt;widgetSchema-&gt;setLabel($num,$label);

    $this-&gt;embedForm('tanulos', $this-&gt;embeddedForms['tanulos']);
  }

  /**
   *
   * Ha rogziteskor uj tanulot vettunk fel, akkor adjuk hozza az osztalyhoz
   * Ha pedig toroltunk akkor tavolitsuk el a formbol
   */
  public function bind(array $taintedValues = null, array $taintedFiles = null)
  {
    if (isset($taintedValues['tanulos']))
    {
      foreach($taintedValues['tanulos'] as $key =&gt; $tanulo)
      {
        if (!isset($this['tanulos'][$key]))
        {
          $this-&gt;addTanulo($key);
        }
      }
    }

    foreach ($this-&gt;embeddedForms['tanulos'] as $key=&gt;$form)
    {
      if (!isset($taintedValues['tanulos'][$key]) &amp;&amp; $key&lt;&gt;'_csrf_token')
      {
        $this-&gt;getWidgetSchema()-&gt;offsetGet('tanulos')-&gt;offsetUnset($key);
        $this-&gt;getValidatorSchema()-&gt;offsetGet('tanulos')-&gt;offsetUnset($key);
        unset(
          $taintedValues['tanulos'][$key],
          $taintedFiles['tanulos'][$key]);
      }
    }

    parent::bind($taintedValues, $taintedFiles);
  }

  /**
   * Tanulonak beallitjuk az osztalyat
   *
   * Amikor egy uj osztallyal egyutt viszunk fel egy tanulot, akkor
   * meg kell adnunk a tanulonak is, hogy melyik osztalyba tartozik.
   * Raadasul eltavolitottuk a tanulo from osztaly_id mezojet, így minden
   * egyeb esetben is szukseg van erre.
   *
   */
  public function saveEmbeddedForms($con = null, $forms = null)
  {
    $oszaly = $this-&gt;getObject();
    if ($forms)
    {
      foreach ($forms as $form)
      {
        if ($form instanceof sfFormObject)
        {
          $form-&gt;getObject()-&gt;setOsztaly($oszaly);
        }
      }
    }   

    return parent::saveEmbeddedForms($con, $forms);
  }

  /**
   * Ezt az osztalyfuggvenyt bovitjuk. A kikeressuk a postolt adatokbol a  tanulok
   * azonositojat (id). Amelyik tanulo azonositoja nincs benne a kapott eredmenyben,
   * toroljuk az osztalybol.
   */
  public function updateObjectEmbeddedForms ($values, $forms = null)
  {
    // $values['tanulos'][][id] elemeket, ahol id&gt;0
    $ids = set::extract('/tanulos[id&gt;0]/id', $values);
    if (!$forms)
    {
      $c = new Criteria();
      $c-&gt;add(TanuloPeer::OSZTALY_ID, $this-&gt;getObject()-&gt;getId());
      $c-&gt;add(TanuloPeer::ID, $ids, Criteria::NOT_IN);
      TanuloPeer::doDelete($c);
    }
    return parent::updateObjectEmbeddedForms ($values, $forms);
  }
}
</pre>
<p>Három dolgot használtunk fel a formban, amit még el kell készítenünk. </p>
<p>Egy widget, ami létrehozza a tanuló hozzáadása linket. Ezt embedderFormWidget néven neveztem el és a lib/widget mappába tegyük. Ez a mappa még nem létezik, létre kell hozni. Ebbe hozuk létre a embedderFormWidget.class.php fájlt:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
/**
 * @author     nova
 * @version    1.0.0
 */
class embedderFormWidget extends sfWidgetForm
{
  /**
   * Configures the current widget.
   *
   * Available options:
   *
   * @param string html_element - az elem, amihez hozzafuzunk
   * @param string url - az ajay keres url-je
   *
   * @see sfWidgetForm
   */
  protected function configure($options = array(), $attributes = array())
  {
    $this-&gt;addOption('html_element');
    $this-&gt;addOption('url');
    parent::configure($options, $attributes);
  }

  /**
   * @param  string $name        The element name
   * @param  string $value       The date displayed in this widget
   * @param  array  $attributes  An array of HTML attributes to be merged with the default HTML attributes
   * @param  array  $errors      An array of errors for the field
   *
   * @return string An HTML tag string
   *
   * @see sfWidgetForm
   */
  public function render($name, $value = null, $attributes = array(), $errors = array())
  {
    $attributes = $this-&gt;getAttributes();
    $html =jq_link_to_function(
        '&lt;span class=&quot;ui-icon ui-icon-circle-plus fright&quot;&gt;&lt;/span&gt;&lt;span class=&quot;fright&quot;&gt;Új&lt;/span&gt;',
        &quot;jQuery.get('&quot;.$this-&gt;getOption('url').&quot;',function(data){
            jQuery('&quot;.$this-&gt;getOption('html_element').&quot;').append(data);
        });&quot;,
        $attributes);
    return $html;
  }
}
</pre>
<p>Aztán gondoskodnuk kell az ajax hívás válaszáról a szerver oldalon. Módosítsuk az apps/fronntedn/modules/osztaly/actions/actions.class.php fájlt az alábbi metódussal:</p>
<pre class="brush: php; title: ; notranslate">
  /**
   * Visszaad egy új sort (widgetet) a tanulo formhoz
   *
   * @param sfWebRequest $request
   */
  public function executeGetEmbedForm(sfWebRequest $request)
  {
    $form = $this-&gt;configuration-&gt;getForm();
    $num = 'tmp_'.time();
    $form-&gt;addTanulo($num);

    return $this-&gt;renderText($form-&gt;getWidget('tanulos')-&gt;getWidget($num)-&gt;render($num));
  }
</pre>
<p>Ezen kívül még felhasználtam egy konkurens MVC rendszerben található igencsak hasznos osztályt, a<br />
<a href="http://book.cakephp.org/hu/view/3/A-Kézikönyv#!/hu/view/640/Set">CakePHP set osztályát</a><br />
Ezt persze módosítanom kellett, hogy szeresse a Symfony is. <a href="http://blog.tlsys.hu/wp-content/uploads/2011/02/set.zip">Ide tettem fel</a>.</p>
<p>Letölthetővé tettem a teljes projektet is, <a href="http://blog.tlsys.hu/wp-content/uploads/2011/02/sandbox.tar.gz">innen</a>.</p>
<p>Sajnos annyi energiám nem volt hogy lépésről lépésre építsem fel a projektet, remélem így is hasznosnak találja, aki elolvassa. Nekem meg jó jegyzet <img src='http://blog.tlsys.hu/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tlsys.hu/symfony_embedded_form/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony II. rész – admin generator</title>
		<link>http://blog.tlsys.hu/symfony-2-admin-generator/</link>
		<comments>http://blog.tlsys.hu/symfony-2-admin-generator/#comments</comments>
		<pubDate>Sat, 05 Jun 2010 21:08:11 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://blog.tlsys.hu/?p=351</guid>
		<description><![CDATA[
			
			
			
			
			
			
			Tweet
						
						
			Tovább mennék az első rész folyamányaként. Admin generátorról lesz itt is szó, néhány általános probléma megoldását tenném közzé:

a listában szereplő mezők változtatása
kapcsolt táblák szerinti rendezés


Eljött az idő hogy egy pici, de konkrét adatbázist kreáljunk.
Futtasuk le akár a már telepített phpmyadminban

CREATE DATABASE sandbox;
USE sandbox;
CREATE TABLE `categories` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(255) [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="border:1px solid #808080;background-color:#F0F4F9;">
			<div style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.tlsys.hu%2Fsymfony-2-admin-generator%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div>
			<div style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://blog.tlsys.hu/symfony-2-admin-generator/"></g:plusone>
			</div>
			<div style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://blog.tlsys.hu/symfony-2-admin-generator/"  data-text="Symfony II. rész – admin generator" data-count="horizontal">Tweet</a>
			</div><div style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://blog.tlsys.hu/symfony-2-admin-generator/" data-counter="right"></script></div>			
			<div style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://blog.tlsys.hu/symfony-2-admin-generator/"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>Tovább mennék az <a href="http://blog.tlsys.hu/symfony-propel-ubuntu-telepit/">első rész</a> folyamányaként. Admin generátorról lesz itt is szó, néhány általános probléma megoldását tenném közzé:</p>
<ul>
<li>a listában szereplő mezők változtatása</li>
<li>kapcsolt táblák szerinti rendezés</li>
</ul>
<p><span id="more-351"></span><br />
Eljött az idő hogy egy pici, de konkrét adatbázist kreáljunk.<br />
Futtasuk le akár a már telepített phpmyadminban</p>
<pre class="brush: sql; title: ; notranslate">
CREATE DATABASE sandbox;
USE sandbox;
CREATE TABLE `categories` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(255) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `products` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(255) NOT NULL,
  `price` float(9,3) default '0.000',
  `category_id` int(11) default NULL,
  PRIMARY KEY  (`id`),
  KEY `category_id` (`category_id`),
  CONSTRAINT `products_fk` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
</pre>
<p>Az első leírásban létrehozott sandbox projectünket fogjuk átszerkeszteni.<br />
Tehát állítsuk be a config könyvtárban lévő adatbázisokhoz tartozó fájlokat (propel.ini és databases.yml) az előbb létrehozott sandbox adatbázisra.<br />
Majd futtassuk le az alábbi parancsokat is:</p>
<pre class="brush: bash; title: ; notranslate">
# generáljuk le a schema.yml fájlt
./symfony propel:build-schema
#hozzuk létre a formokat, filtereket, modeleket, -C direktiva kihagyja az sql-t (classes only)
./symfony propel:build-all -C
# és a két táblánkhoz tartozó admin felületet készítsük el:
./symfony propel:generate-admin --module=CategoriesAdmin frontend categories
# az apps/frontend/modules/CategoriesAdmin modulunkat
# és a route (apps/frontend/config/routing.yml) szabályt is létre fogja hozni
./symfony propel:generate-admin --module=ProductsAdmin frontend products
</pre>
<p>Máris érdemes létrehozni a PROJECT_DIR/apps/frontend/templates/layout.php fájlban a 2 menüpontunkat. Közvetlenül a body nyitótagja után tegyük be az alábbi sorokat.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;ul id=&quot;menu&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;&lt;?php echo url_for('@categories')?&gt;&quot;&gt;&lt;/a&gt;Kategóriák&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;&lt;?php echo url_for('@products')?&gt;&quot;&gt;Termékek&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</pre>
<p>A http://mydomain/sandbox/frontend_dev.php/CategoriesAdmin érjük el az alkalmazásunkat. Most próbáljuk meg feltölteni adatokkal. Először vigyünk fel kategóriákat. Majd próbáljunk meg, felvinni termékeket is. Elvileg el kell akadnunk amiatt, hogy a categories modelunknek még nincs __toString() metódusa. Ez egy PHP metódus, ami egy objektum kiíratására szolgál. Jelen esetünkben, mi, a name mezővel jelenítenénk meg a tábla egyes rekordjait. Így hát hozzuk létre ezt a metódust a PROJECT_DIR/lib/model/categories.php fájlban.</p>
<pre class="brush: php; title: ; notranslate">
class Categories extends BaseCategories {
  public function __toString()
  {
    return $this-&gt;getName();
  }
} // Categories
</pre>
<p>Ezután már sikeresen megjeleníthetjük a listát, és rögzíthetünk új rekordokat. De mint láthatjuk a termékek listában nem a kategóriák neve, hanem annak azonosítója (id) szerepel, ráadásul a felhasználóknak a termékek id-ja is megjelent. Sajnos a generátorunk nem tökéletes, így a létrehozott fájlokat jó pár helyen módosítanunk kell.<br />
Elsőként magát a PROJECT_DIR/apps/frontend/modules/ProductsAdmin/config/generator.yml fájlt módosítjuk. Figyelve a .yml fájlokra jellemző szabályokra (legfőképp, hogy behúzás nem tabulátor, hanem 2 üres hely) a listát tartalmazó sort egészítsük ki:</p>
<pre class="brush: plain; title: ; notranslate">
list:
  display: [categories, name, price ] # felsoroljuk a megjelenített mezőket, kapcsolt tábla esetén a classt
  peer_method: doSelectJoinAll # modelpeer osztályunk metódusa
</pre>
<p>Másodikként tekintsük meg a létrehozott PROJECT_DIR/apps/frontend/modules/ProductsAdmin/actions/action.class.php fájlt. Mint láthatjuk a ProductsAdminActions osztályunk az autoProductsAdminActions osztályból származik. Ez pedig a cache könyvtárban keresendő, a  PROJECT_DIR/cache/frontend/dev/modules/ProductsAdmin/actions/action.class.php fájlban. Ennek az osztálynak kell 2 függvényét felül definiálnuk:</p>
<pre class="brush: php; title: ; notranslate">
class ProductsAdminActions extends autoProductsAdminActions
{
  protected function addSortCriteria($criteria)
  {
    if (array(null, null) == ($sort = $this-&gt;getSort()))
    {
      return;
    }

    if ($sort[0] == 'categories.name')
    {
      $column = CategoriesPeer::NAME;
    }
    else
    {
      $column = ProductsPeer::translateFieldName($sort[0], BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_COLNAME);
    }

    if ('asc' == $sort[1])
    {
      $criteria-&gt;addAscendingOrderByColumn($column);
    }
    else
    {
      $criteria-&gt;addDescendingOrderByColumn($column);
    }
  }

  protected function isValidSortColumn($column)
  {
    if (in_array($column, array('categories.name')))
    {
      return true;
    }
    else
    {
      return parent::isValidSortColumn($column)
    }
  }
}
</pre>
<p>Majd hozzuk létre a PROJECT_DIR/apps/frontend/modules/ProductsAdmin/_list_th_tabular.php fájlt. Ezt is a cacheből másoltam ki és módosítottam.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php slot('sf_admin.current_header') ?&gt;
&lt;th class=&quot;sf_admin_text sf_admin_list_th_categories&quot;&gt;
  &lt;?php if ('categories.name' == $sort[0]): ?&gt;
    &lt;?php echo link_to(__('Categories', array(), 'messages'), '@products', array('query_string' =&gt; 'sort=categories.name&amp;sort_type='.($sort[1] == 'asc' ? 'desc' : 'asc'))) ?&gt;
    &lt;?php echo image_tag(sfConfig::get('sf_admin_module_web_dir').'/images/'.$sort[1].'.png', array('alt' =&gt; __($sort[1], array(), 'sf_admin'), 'title' =&gt; __($sort[1], array(), 'sf_admin'))) ?&gt;
  &lt;?php else: ?&gt;
    &lt;?php echo link_to(__('Categories', array(), 'messages'), '@products', array('query_string' =&gt; 'sort=categories.name&amp;sort_type=asc')) ?&gt;
  &lt;?php endif; ?&gt;
&lt;/th&gt;
&lt;?php end_slot(); ?&gt;
&lt;?php include_slot('sf_admin.current_header') ?&gt;

&lt;?php slot('sf_admin.current_header') ?&gt;
&lt;th class=&quot;sf_admin_text sf_admin_list_th_name&quot;&gt;
  &lt;?php if ('name' == $sort[0]): ?&gt;
    &lt;?php echo link_to(__('Name', array(), 'messages'), '@products', array('query_string' =&gt; 'sort=name&amp;sort_type='.($sort[1] == 'asc' ? 'desc' : 'asc'))) ?&gt;
    &lt;?php echo image_tag(sfConfig::get('sf_admin_module_web_dir').'/images/'.$sort[1].'.png', array('alt' =&gt; __($sort[1], array(), 'sf_admin'), 'title' =&gt; __($sort[1], array(), 'sf_admin'))) ?&gt;
  &lt;?php else: ?&gt;
    &lt;?php echo link_to(__('Name', array(), 'messages'), '@products', array('query_string' =&gt; 'sort=name&amp;sort_type=asc')) ?&gt;
  &lt;?php endif; ?&gt;
&lt;/th&gt;
&lt;?php end_slot(); ?&gt;
&lt;?php include_slot('sf_admin.current_header') ?&gt;&lt;?php slot('sf_admin.current_header') ?&gt;
&lt;th class=&quot;sf_admin_text sf_admin_list_th_price&quot;&gt;
  &lt;?php if ('price' == $sort[0]): ?&gt;
    &lt;?php echo link_to(__('Price', array(), 'messages'), '@products', array('query_string' =&gt; 'sort=price&amp;sort_type='.($sort[1] == 'asc' ? 'desc' : 'asc'))) ?&gt;
    &lt;?php echo image_tag(sfConfig::get('sf_admin_module_web_dir').'/images/'.$sort[1].'.png', array('alt' =&gt; __($sort[1], array(), 'sf_admin'), 'title' =&gt; __($sort[1], array(), 'sf_admin'))) ?&gt;
  &lt;?php else: ?&gt;
    &lt;?php echo link_to(__('Price', array(), 'messages'), '@products', array('query_string' =&gt; 'sort=price&amp;sort_type=asc')) ?&gt;
  &lt;?php endif; ?&gt;
&lt;/th&gt;
&lt;?php end_slot(); ?&gt;
&lt;?php include_slot('sf_admin.current_header') ?&gt;
</pre>
<p>Ezzel a fájllal azonban már sikerült teljesen elontanunk a generátort. Hiszen ha új mezőket teszünk be, vagy veszünk ki, akkor ezt a fájlt újra és újra szerkesztenünk kell. Ez ellen a legjobb módszer talán az lenne, ha írnánk egy saját generátor, ami figyelembe veszi ezt. Talán később még módosítom ezt a leírást ezen ötletemmel. </p>
<p>Léteznek már nagyobb tudású generátorok:<br />
<a href="http://www.symfony-project.org/plugins/ahAdminGeneratorThemesPlugin/1_0_0">ahAdminGeneratorThemesPlugin</a><br />
<a href="http://www.symfony-project.org/plugins/sfAdminThemejRollerPlugin">sfAdminThemejRollerPlugin</a><br />
Mindkettő Doctrinera alá készült el, de bizonyára nem túl nehéz átírni Propelesre. <img src='http://blog.tlsys.hu/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tlsys.hu/symfony-2-admin-generator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony I. rész &#8211; Symfony 1.3 + propel telepítése ubuntu környezetben</title>
		<link>http://blog.tlsys.hu/symfony-propel-ubuntu-telepit/</link>
		<comments>http://blog.tlsys.hu/symfony-propel-ubuntu-telepit/#comments</comments>
		<pubDate>Fri, 12 Feb 2010 19:23:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://blog.tlsys.hu/?p=181</guid>
		<description><![CDATA[
			
			
			
			
			
			
			Tweet
						
						
			Ide egy symfony 1.3 + Propel project elkészítését szánom. Ubuntu rendszeren dolgozom, azért mert egyszerűbb, mint Windowson. Ha Windowson próbálkoznék, akkor is valamilyen virtuális Linuxot (pl: virtualbox) telepítenék fejlesztői teszt környezetnek.
A symfony 1.3-ra pedig azért esett a választás, mert ez az utolsó verzió, ami kompatibilis az 1.0-val. Rengeteg 1.0-as plugin található, aminek nincs 1.2-1.3-1.4-es verziója. [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="border:1px solid #808080;background-color:#F0F4F9;">
			<div style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.tlsys.hu%2Fsymfony-propel-ubuntu-telepit%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div>
			<div style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://blog.tlsys.hu/symfony-propel-ubuntu-telepit/"></g:plusone>
			</div>
			<div style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://blog.tlsys.hu/symfony-propel-ubuntu-telepit/"  data-text="Symfony I. rész &#8211; Symfony 1.3 + propel telepítése ubuntu környezetben" data-count="horizontal">Tweet</a>
			</div><div style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://blog.tlsys.hu/symfony-propel-ubuntu-telepit/" data-counter="right"></script></div>			
			<div style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://blog.tlsys.hu/symfony-propel-ubuntu-telepit/"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>Ide egy symfony 1.3 + Propel project elkészítését szánom. Ubuntu rendszeren dolgozom, azért mert egyszerűbb, mint Windowson. Ha Windowson próbálkoznék, akkor is valamilyen virtuális Linuxot (pl: virtualbox) telepítenék fejlesztői teszt környezetnek.<br />
A symfony 1.3-ra pedig azért esett a választás, mert ez az utolsó verzió, ami kompatibilis az 1.0-val. Rengeteg 1.0-as plugin található, aminek nincs 1.2-1.3-1.4-es verziója. Ha esetleg gyorsan be kell üzemelnem valamelyiket, akkor 1.3 alatt talán könnyebb lesz. A propelt pedig azért választottam, mert a cég, ahol dolgozom ezt használja és ezért én sem használtam még doctrinet.<br />
A projektemnél az adatbázis már kész volt és használták is. Erre fogjuk ráhúzni a symfonyt admin felületét.<br />
<span id="more-181"></span>Telepítsük a hiányzó szoftvereket:<br />
Az alap rendszer az, hogy a LAMP (Linux-Apache-MySql-PHP) környezet már megvolt.<br />
Ha mégsem, akkor egy már telepített Ubuntu/Debian Linuxon, a <em>sudo apt-get install mysql-server phpmyadmin</em> paranccsal a legegyszerűbb telepíteni, egy mozdulattal mindent <img src='http://blog.tlsys.hu/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Utána jöhet a symfony:</p>
<pre class="brush: bash; title: ; notranslate">
sudo-s #rendszergazda módba váltunk
apt-get install php-pear
pear channel-discover pear.symfony-project.com
pear install symfony/symfony-1.3.5 #ha van újabb, akkor azt
apt-get install php5-xsl #xsl php kiterjesztés telepítése, a propelhez kell
a2enmod rewrite # mod rewrite
/etc/init.d/apache restart
exit #kilépünk a rendszergazda módból
mkdir sandbox #létrehozzuk a project könyvtárat
cd sandbox #belépünk a könyvtárba
symfony generate:project sandbox --orm=Propel #project készítése
symfony generate:app frontend #alkalmazás létrehozása
# hogy a majdani felület kapja meg az alap symfony designt
ln -s /usr/share/php/data/symfony/web/sf web/sf
</pre>
<p>Ezzel létre is hoztunk egy alkalmazást.<br />
Ami problémával szembesülhetünk hogy valamiért nem lehet újraindítani az apache szervert, mert a 80/443-as portok valamelyike már foglalt. Ez általában az /etc/apache/ports.conf fileban keletkezett duplikált bejegyzés miatt fordulhat elő. Töröljük az egyiket&#8230;</p>
<p>Most be kell állítanunk az adatbázist. Ez most több fájlt érint, hiszen alapból az 1.3 már doctrine modeleket használ, ha a projektet nem <em>&#8211;orm=Propel</em> direktívával hoztuk létre. Mi azzal tettük <img src='http://blog.tlsys.hu/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
De ha mégsem, akkor először is szükségünk lesz egy propel.ini fájlra a sandbox/config könyvtárunkban. A fájlt nekünk kell létrehozni az alábbi sorokkal. Értelemszerűen át kell szerkeszteni (host,dbname, password, user, output dir), akkor is ha nem mi hoztuk létre.</p>
<pre class="brush: plain; title: ; notranslate">
propel.targetPackage       = lib.model
propel.packageObjectModel  = true
propel.project             = sandbox
propel.database            = mysql
propel.database.driver     = mysql
propel.database.url        = mysql:host=localhost;dbname=teszt
propel.database.creole.url = ${propel.database.url}
propel.database.user       = felhsznalo
propel.database.password   = jelszo
propel.database.encoding   = utf8

; mysql options
propel.mysql.tableType     = InnoDB

propel.addVendorInfo       = true
propel.addGenericAccessors = true
propel.addGenericMutators  = true
propel.addTimeStamp        = true
propel.addValidators       = false

propel.useDateTimeClass       = true
propel.defaultTimeStampFormat = Y-m-d H:i:s
propel.defaultTimeFormat      = H:i:s
propel.defaultDateFormat      = Y-m-d

propel.schema.validate        = false
propel.samePhpName            = false
propel.disableIdentifierQuoting     = false
propel.emulateForeignKeyConstraints = true

; directories
propel.home                    = .
propel.output.dir              = /home/user/sandbox
propel.schema.dir              = ${propel.output.dir}/config
propel.conf.dir                = ${propel.output.dir}/config
propel.phpconf.dir             = ${propel.output.dir}/config
propel.sql.dir                 = ${propel.output.dir}/data/sql
propel.runtime.conf.file       = runtime-conf.xml
propel.php.dir                 = ${propel.output.dir}
propel.default.schema.basename = schema
propel.datadump.mapper.from    = *schema.xml
propel.datadump.mapper.to      = *data.xml

; builder settings
propel.builder.peer.class              = plugins.sfPropelPlugin.lib.builder.SfPeerBuilder
propel.builder.object.class            = plugins.sfPropelPlugin.lib.builder.SfObjectBuilder
propel.builder.objectstub.class        = plugins.sfPropelPlugin.lib.builder.SfExtensionObjectBuilder
propel.builder.peerstub.class          = plugins.sfPropelPlugin.lib.builder.SfExtensionPeerBuilder
propel.builder.objectmultiextend.class = plugins.sfPropelPlugin.lib.builder.SfMultiExtendObjectBuilder
propel.builder.mapbuilder.class        = plugins.sfPropelPlugin.lib.builder.SfMapBuilderBuilder

propel.builder.addIncludes  = false
propel.builder.addComments  = true
propel.builder.addBehaviors = true
</pre>
<p>a config/database.yml fájlt is átszerkesztjük:</p>
<pre class="brush: plain; title: ; notranslate">
dev:
  propel:
    param:
      classname:  DebugPDO
      debug:
        realmemoryusage: true
        details:
          time:       { enabled: true }
          slow:       { enabled: true, threshold: 0.1 }
          mem:        { enabled: true }
          mempeak:    { enabled: true }
          memdelta:   { enabled: true }

test:
  propel:
    param:
      classname:  DebugPDO

all:
  propel:
    class:        sfPropelDatabase
    param:
      classname:  PropelPDO
      dsn:        mysql:dbname=teszt;host=localhost
      username:   user
      password:  password
      encoding:   utf8
      persistent: true
      pooling:    true
</pre>
<p>Majd át kell szerkeszteni a config/ProjectConfiguration fájlt is. Engedélyezzük a pluginokat.</p>
<pre class="brush: php; title: ; notranslate">
  public function setup()
  {
     $this-&gt;enableAllPluginsExcept(array('sfDoctrinePlugin'));
     // vagy : $this-&gt;enablePlugins('sfPropelPlugin');
  }
</pre>
<p>Ezekután az adatbázisunkhoz legeneraálhatjuk a schema.yml fájlt. Majd abból a modelt, a formot és a filtereket. Majd végül az első modulunkat is (modelname a modelünk &#8211; táblánk &#8211; neve):</p>
<pre class="brush: bash; title: ; notranslate">
# az alábbi paranccsal tudjuk a web könyvtárunkba a szükséges symlinkeket
# létrehozni, amire szintén a design miatt lesz szükség
./symfony plugin:publish-assets
./symfony propel:build-schema #ezzel jön létre a config/schema.yml fájl a beállított adatbázis alapján
./symfony propel:build-model #modelek (táblák) legenerálása
./symfony propel:build-form #formok generálása
./symfony propel:build-filter #a táblázatokhoz tartozó filterek legenerálása
# vagy az előző 3 helyett csak egyszerűen
# ./symfony propel:build-all --classes-only
# most pedig következzen a tábláink admin felületének legenerálása:
./symfony propel:generate-admin frontend modelname #a modul is ezt a nevet kapja
# vagy ha más néven szeretnénk:
#./symfony propel:generate-admin --module=&quot;modelnameAdmin&quot; frontend modelname
</pre>
<p>Az utolsó parancsot érdemes az összes modulunkra (értsd: tábla) lefuttatni.<br />
Én két problémába ütköztem, ezen parncsok futtatásakor.</p>
<ul>
<li> A propel nem szereti a default értékként beállított CURRENT_TIMESTAMP-et, viszont a schema.yml-be beírja. Ezért át kellett szerkesztenem a generált fájlban: <em>defaultValue: &#8216;0000-00-00 00:00:00&#8242;</em>.<br />
Ráadásul a hibaüzenet is nagyon buta volt:<em>Szegmens hiba</em>. Na ebből találja ki az ember <img src='http://blog.tlsys.hu/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' /> </li>
<li> A másik probléma pedig az volt, hogy szerettem volna egyben lefuttatni a model, form, filter építő parancsokat, de elfogyott a memória. Nem tudom melyik memória volt kevés, mert a php.ini-ben a négyszeresére emeltem, de még mindig ugyanannyira kevés volt. De legalább a hibaüzenet és az utasítások érthetők voltak</li>
</ul>
<p>Zárjuk le egyszerűen a telepítésünket:<br />
Lehetne szenvedni az apache virtuális könyvtáraival, de az egy másik leírás lesz. <img src='http://blog.tlsys.hu/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
Most egy egyszerű Linux link is megteszi nekünk. Tehát létre kell hozni a /var/www könyvtárban egy linket a projectünknek. Ehhez el lehetne mélyednünk az ln parancs használatában, de én mindig a midnight commandert használtam ehhez. Ha nem lenne feltelepítve, akkor a <em>sudo apt-get install mc</em> paranccsal telepíthetjük. A két ablakos rendszerben a CTRL+X, majd utána S gomb lenyomásával hozhatunk létre linket. Hozzuk hát létre a /var/www könyvtárban egy linket sandbox néven, ami a sandbox/web könyvtárunkra mutat. És a máris elérhető a táblázatunk a http://mydomain/sandbox/index.php/modul url alatt. Ehhez lehet rendszergazdai módba kell váltanunk.<br />
<br />
Ha el akarjuk hagyni az <em>index.php</em> -t az URL-ből, akkor az /etc/apache/sites-available/default fájlt kell módosítani. A &#8220;Directory&#8221; szegmens alatt az <em>AllowOverride None</em> sort módosítani kell <em>AllowOverride  Al</em>l -ra. Ezzel engedélyezzük a <em>.htaccess</em> fájlok használatát. Így a <em>http://mydomain/sandbox/index.php/modul</em> helyett használhatjuk simán a <em>http://mydomain/sandbox/modul</em> URL-t is.<br />
<br />
Illetve ha valami hibába ütköznénk, akkor a fehér képernyő helyett a <em>http://mydomain/sandbox/frontend_dev.php/modul</em> alatt informálódhatunk a problémáról. Ha nem localhoston dolgozunk, akkor a frontend_dev.php fájl elején engedélyeznünk kell a saját IP címünket is.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tlsys.hu/symfony-propel-ubuntu-telepit/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Symfony parancsok</title>
		<link>http://blog.tlsys.hu/symfony-parancsok/</link>
		<comments>http://blog.tlsys.hu/symfony-parancsok/#comments</comments>
		<pubDate>Fri, 12 Feb 2010 10:20:45 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Symfony]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.tlsys.hu/?p=175</guid>
		<description><![CDATA[
			
			
			
			
			
			
			Tweet
						
						
			amiket sokat kerestem, hogy többet ne kelljen   

//sfGuardUser ID:
sfContext::getInstance()-&#62;getUser()-&#62;getGuardUser()-&#62;getId()

//Hogyan alakitsuk egy objetum name tulajdonságát id 'formátumura':
get_id_from_name($name)

// form formázása (&#60;p&#62; stílus):
// http://www.thatsquality.com/articles/7-days-of-symfony-1-1-forms-widgets-and-validators-day7
$formatter = $this-&#62;getWidgetSchema()-&#62;getFormFormatter();
$formatter-&#62;setErrorRowFormat('%errors%');
$formatter-&#62;setErrorListFormatInARow(&#34;%errors%\n&#34;);
$formatter-&#62;setErrorRowFormatInARow(&#34;&#60;p class='error-message'&#62;%error%&#60;/p&#62;&#34;);
$formatter-&#62;setRowFormat(&#34;%error%&#60;p&#62;%label%%field%%help%%hidden_fields%&#60;/p&#62;\n&#34;);
// ez alapból nem hívodik meg. De ha a formatter használja, pl: embeddformnál:
$formatter-&#62;setDecoratorFormat('&#60;table class=&#34;tgTextSlot&#34;&#62;%content%&#60;/table&#62;');

// hogyan adjunk egy form elemnek classt:
// formban :
$this-&#62;WidgetSchema['name']-&#62;setAttribute('class', 'classname');
// templateben 1:
echo $form-&#62;render(array('name' =&#62; array('class' =&#62; 'classname'), [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="border:1px solid #808080;background-color:#F0F4F9;">
			<div style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.tlsys.hu%2Fsymfony-parancsok%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div>
			<div style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://blog.tlsys.hu/symfony-parancsok/"></g:plusone>
			</div>
			<div style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://blog.tlsys.hu/symfony-parancsok/"  data-text="Symfony parancsok" data-count="horizontal">Tweet</a>
			</div><div style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://blog.tlsys.hu/symfony-parancsok/" data-counter="right"></script></div>			
			<div style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://blog.tlsys.hu/symfony-parancsok/"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>amiket sokat kerestem, hogy többet ne kelljen <img src='http://blog.tlsys.hu/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  <span id="more-175"></span></p>
<pre class="brush: php; title: ; notranslate">
//sfGuardUser ID:
sfContext::getInstance()-&gt;getUser()-&gt;getGuardUser()-&gt;getId()

//Hogyan alakitsuk egy objetum name tulajdonságát id 'formátumura':
get_id_from_name($name)

// form formázása (&lt;p&gt; stílus):
// http://www.thatsquality.com/articles/7-days-of-symfony-1-1-forms-widgets-and-validators-day7
$formatter = $this-&gt;getWidgetSchema()-&gt;getFormFormatter();
$formatter-&gt;setErrorRowFormat('%errors%');
$formatter-&gt;setErrorListFormatInARow(&quot;%errors%\n&quot;);
$formatter-&gt;setErrorRowFormatInARow(&quot;&lt;p class='error-message'&gt;%error%&lt;/p&gt;&quot;);
$formatter-&gt;setRowFormat(&quot;%error%&lt;p&gt;%label%%field%%help%%hidden_fields%&lt;/p&gt;\n&quot;);
// ez alapból nem hívodik meg. De ha a formatter használja, pl: embeddformnál:
$formatter-&gt;setDecoratorFormat('&lt;table class=&quot;tgTextSlot&quot;&gt;%content%&lt;/table&gt;');

// hogyan adjunk egy form elemnek classt:
// formban :
$this-&gt;WidgetSchema['name']-&gt;setAttribute('class', 'classname');
// templateben 1:
echo $form-&gt;render(array('name' =&gt; array('class' =&gt; 'classname'), 'name2' =&gt; array('class'=&gt;'classname'))) ;
// templateben 2:
echo $form['name']-&gt;renderRow(array('class' =&gt; 'classname'));

//formban widget mozgatása:
$this-&gt;getWidgetSchema()-&gt;moveField('widget_name', sfWidgetFormSchema::AFTER, 'last_name');

//$this változóinak lekérdezése
$this-&gt;getVarHolder()-&gt;getAll()

//SF_ENVIRONMENT 1.2 alatt:
sfConfig::get('sf_environment')

// összes request paraméter lekérése
$this-&gt;getRequest()-&gt;getParameterHolder()-&gt;getAll();
sfContext::getInstance()-&gt;getRequest()-&gt;getParameterHolder()-&gt;getAll()

// egy bizonyos request paraméter lekérése
$this-&gt;getRequestParameter('parameter', false);
sfContext::getInstance()-&gt;getRequest()-&gt;getParameter('parameter');

// controllerben helper használata
sfLoader::loadHelpers(array('Tag', 'Url'));
sfContext::getInstance()-&gt;getConfiguration()-&gt;loadHelpers(array('Tag', 'Url'));

//i18N akárhol:
sfContext::getInstance()-&gt;getI18N()-&gt;__('Nincs kiválasztva')

i18N formban:
$this-&gt;getWidgetSchema()-&gt;getFormFormatter()-&gt;translate('szoveg');

// Ez inkább propel. A model osztályból, annak sql neve:
constant(get_class($this-&gt;getPeer()).'::TABLE_NAME')

// ajax link
echo link_to_remote('postolunk', array(
'update'    =&gt; 'a div id-ja amibe a visszatérő adatokat kapjuk',
'url'       =&gt; 'az ajaxos url',
'method'    =&gt; 'post',
//ez meghívja a validate javascript függvényt:
'condition' =&gt; &quot;validate(Form.serialize('formId'))&quot;,
//és a legfontosabb, így lehet a form adatait is elküldeni:
'submit'    =&gt; &quot;formId&quot;
))

// A form mezői:
$this-&gt;getWidgetSchema()-&gt;getPositions()

// egy form hibát dob, de az épp rejtett, akkor irassuk ki.
$this-&gt;form-&gt;getErrorSchema()
foreach($this-&gt;form-&gt;getErrorSchema()-&gt;getErrors() as $key =&gt; $error)
{
  echo '&lt;p&gt;' . $key . ': ' . $error . '&lt;/p&gt;';
}

// absolute url:
link_to(__('szöveg', array(), 'messages'), '@url', array('absolute'=&gt;true))
</pre>
<p>Callback validator</p>
<pre class="brush: php; title: ; notranslate">
class aForm extends aBaseForm
{
  public function configure()
  {
    parent::configure() ; //esetleg ez nem fontos
    $this-&gt;validatorSchema-&gt;setPostValidator(new sfValidatorCallback(array('callback' =&gt; array($this, 'fuggvenyneve'))));
  }

  public function fuggvenyneve(sfValidatorBase $validator, array $values)
  {
    // $values tartalmazza az összes adatot, feldolgozod és a $hibavan-nak ennek függvényében értéket adsz:
    if ($hibavan)
    {
      throw new sfValidatorError($validator, 'hibaüzenet');
    }

    return $values;
  }
}
</pre>
<p>Propel</p>
<pre class="brush: php; title: ; notranslate">
$c = new Criteria();
$c-&gt;addJoin(
    array(ReaderFavoritePeer::BOOK_ID,ReaderFavoritePeer::READER_ID),
    array(BookOpinionPeer::BOOK_ID,BookOpinionPeer::READER_ID))

// és irassuk is ki a criteriát SQL-ben
echo $criteria-&gt;toString(); 

// szerezzük meg az ID-kat egy táblából.
$c = new Criteria();
$c-&gt;addSelectColumn(MyClassPeer::ID);
$res = BasePeer::doSelect($c);
$Ids = $res-&gt;fetchAll(PDO::FETCH_COLUMN,0);

// SELECT  FROM `tabla` WHERE (tabla.mezo1='string1' OR (tabla.mezo1='string2' AND tabla.mezo2='0'))
$c = new Criteria();
$cr1 = $c-&gt;getNewCriterion(TablePeer::MEZO1, 'string1');
$cr2 = $c-&gt;getNewCriterion(TablePeer::MEZO1, 'string2');
$cr3 = $c-&gt;getNewCriterion(TablePeer::MEZO2, '0');
$cr2-&gt;addAnd($cr3);
$cr1-&gt;addOr($cr2);
$c-&gt;add($cr1);
$c-&gt;toString();
</pre>
<p>Task</p>
<pre class="brush: php; title: ; notranslate">
./symfony i18n:extract frontend hu --auto-save
./symfony i18n:extract frontend hu --display-new
</pre>
<p>Internationalization</p>
<pre class="brush: php; title: ; notranslate">
      //http://www.php.net/manual/en/function.strftime.php
      fb(format_date(time(), 'f'),'f');
      fb(format_date(time(), 'G'),'G');
      fb(format_date(time(), 'y'),'y');
      fb(format_date(time(), 'M'),'M');
      fb(format_date(time(), 'd'),'d');
      fb(format_date(time(), 'h'),'h');
      fb(format_date(time(), 'H'),'H');
      fb(format_date(time(), 'm'),'m');
      fb(format_date(time(), 's'),'s');
      fb(format_date(time(), 'E'),'E');
      fb(format_date(time(), 'D'),'D');
      fb(format_date(time(), 'F'),'F');
      fb(format_date(time(), 'W'),'W');
      fb(format_date(time(), 'w'),'w');
      fb(format_date(time(), 'a'),'a');
      fb(format_date(time(), 'k'),'k');
      fb(format_date(time(), 'K'),'K');
      fb(format_date(time(), 'z'),'z');
</pre>
<p>A smarty egyszerű <img src='http://blog.tlsys.hu/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<pre class="brush: php; title: ; notranslate">
        {assign var='createdat' value=$current_page-&gt;getCreatedAt()}
        {assign var='createdat' value=$createdat|strtotime}
        {capture assign='createdat'}
          {format_date date=$createdat format=&quot;D&quot;}
        {/capture}
        &lt;p class=&quot;date&quot;&gt;{$createdat}&lt;/p&gt;

        // Mert PHP-ban ennyi:
        &lt;?php echo format_date(strtotime($current_page-&gt;getCreatedAt())), 'D'); ?&gt;
</pre>
<p><a href="http://snipt.net/Tram/symfony-12-add-a-custom-filter-field-for-generated-admin/"><br />
Add a custom filter field for generated admin<br />
</a></p>
<pre class="brush: php; title: ; notranslate">
  public function configure() {

    $this-&gt;widgetSchema['title'] = new sfWidgetFormFilterInput();

    $this-&gt;validatorSchema['title'] = new sfValidatorPass(array('required' =&gt; false));
  }//configure

  public function getFields() {
    return array_merge(array(
        'title'=&gt; 'Title',
      ), parent::getFields()
    );
  } //getFields

  protected function addTitleColumnCriteria(Criteria $criteria, $field, $values) {

    // $values['text'] contains the field value, use it to change $criteria object

    // es. $criteria-&gt;add ('column', $values['text'])

  }//addTitleColumnCriteria
</pre>
<p>loggolás külön fájlba.</p>
<pre class="brush: php; title: ; notranslate">
    $text = var_export($this-&gt;getObject()-&gt;toArray(), true);
    $file = sfConfig::get('sf_log_dir').DIRECTORY_SEPARATOR.'debug.log';
    $dispatcher = sfContext::getInstance()-&gt;getEventDispatcher();
    $logger = new sfFileLogger($dispatcher, array('file' =&gt; $file) );
    $dispatcher-&gt;disconnect('application.log', array($logger, 'listenToLogEvent'));
    $logger-&gt;err($text);
    $logger-&gt;notice($text);
    $logger-&gt;info($text);
</pre>
<p>Doctrine:</p>
<pre class="brush: php; title: ; notranslate">
//kapcsolt táblák lekérdezése:
foreach (Doctrine_Core::getTable('CompanyLog')-&gt;getRelations() as $name =&gt; $relation)
{
  echo $name . &quot;:\n&quot;; echo &quot;Local - &quot; . $relation-&gt;getLocal() . &quot;\n&quot;; echo &quot;Foreign - &quot; . $relation-&gt;getForeign() . &quot;\n\n&quot;;
}
</pre>
<p><a href="http://stackoverflow.com/questions/3026961/render-each-choice-as-a-row-in-a-table-in-a-symfony-choice-widget">hogyan formázzunk egy sfWidgetFormChoice widgetet?</a></p>
<pre class="brush: php; title: ; notranslate">
// a widget
$this-&gt;widgetSchema ['my_widget'] = new sfWidgetFormChoice(array('multiple' =&gt; true, 'expanded' =&gt; true, 'choices' =&gt; my_choices, 'renderer_class' =&gt; 'sfWidgetFormSelectCheckbox', 'renderer_options' =&gt; array('formatter' =&gt; array('MyForm', 'MyFormatter'))));

$this-&gt;validatorSchema ['my_widget'] = new sfValidatorChoice(array('multiple' =&gt; true, 'choices' =&gt; array_keys(my_choices), 'required' =&gt; false));

// és a formban:
public static function MyFormatter($widget, $inputs) {
       $result = '&lt;table&gt;';
       foreach ($inputs as $input) {
          $result .= '&lt;tr&gt;&lt;td&gt;' . $input ['label'] . '   ' . $input ['input'] . '&lt;/td&gt;&lt;/tr&gt;';
        }
        $result .= '&lt;/table&gt;';
        return $result;
}
</pre>
<p>néha szükségünk lehet egy olyan widgetre, ami egy tömböt/listát tartalmaz.<br />
Én most egy két dimenziós tömböt fogok megjeleníteni:</p>
<pre class="brush: php; title: ; notranslate">

    protected function getWidgetFormSchemaForMyField($choices)
    {
      $widget = new sfWidgetFormSchema(array(
         'mezo1' =&gt;  new sfWidgetFormPlain(),
         'mezo2' =&gt;  new sfWidgetFormInputHidden(),
         'mezo3'   =&gt;  new sfWidgetFormChoice(array('choices'=&gt;$choices))
      ));

      // a mezők a táblázat egyes cellái lesznek, tehát egymás mellett lesznek:
      $widget-&gt;getFormFormatter()-&gt;setRowFormat('&lt;td&gt;%error%%field%%help%%hidden_fields%&lt;/td&gt;');
      return $widget;
    }

    public function configure()
    {
        ...
        // itt le kell kérni a rekordokat
        // a choices tömbnek is értéket kell adni

        $widgetrows = array();
        foreach ($records as $key=&gt;$record)
        {
          $widgetrows[$key] = $this-&gt;getWidgetFormSchemaForMyField($choices);
        }
        $widget = new sfWidgetFormSchema($widgetrows);
        $formatter = $widget-&gt;getFormFormatter();
        // a táblázat egyes sorai (a fenti három mező egy sorban, de azokból több sor lesz):
        $formatter-&gt;setRowFormat('&lt;tr&gt;%error%%field%%help%%hidden_fields%&lt;/tr&gt;');

        $this-&gt;widgetSchema['mezo'] = new sfWidgetFormSchema(array($widget));
        $formatter = $this-&gt;widgetSchema['mezo']-&gt;getFormFormatter();
        // bele kell tenni az egészet egy táblázatba:
        $formatter-&gt;setRowFormat('&lt;table&gt;%error%%field%%help%%hidden_fields%&lt;/table&gt;');

        ...
    }
</pre>
<p>Egy jó postvalidator leírás:<br />
<a href="http://blog.codeclarity.com/2010/03/09/conditional-validation-in-symfony-forms/"><br />
blog.codeclarity.com/2010/03/09/conditional-validation-in-symfony-forms/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tlsys.hu/symfony-parancsok/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony widgetek</title>
		<link>http://blog.tlsys.hu/symfony-widgetek/</link>
		<comments>http://blog.tlsys.hu/symfony-widgetek/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 14:16:32 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Symfony]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.tlsys.hu/symfony-widgetek/</guid>
		<description><![CDATA[
			
			
			
			
			
			
			Tweet
						
						
			Symfony widgeteket fogok ide kirakni, néhol egy icipici kis magyarázattal.

datePicker:

class datePickerWidget extends sfWidgetFormInput
{

  public function configure($options = array(), $attributes = array())
  {
    $this-&#62;addOption('ifFormat', &#34;%Y-%m-%d&#34;);
    parent::configure($options, $attributes);
  }

  public function render($name, $value = null, $attributes = array(), $errors = array())
  {
    use_helper('Javascript', [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="border:1px solid #808080;background-color:#F0F4F9;">
			<div style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.tlsys.hu%2Fsymfony-widgetek%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div>
			<div style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://blog.tlsys.hu/symfony-widgetek/"></g:plusone>
			</div>
			<div style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://blog.tlsys.hu/symfony-widgetek/"  data-text="Symfony widgetek" data-count="horizontal">Tweet</a>
			</div><div style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://blog.tlsys.hu/symfony-widgetek/" data-counter="right"></script></div>			
			<div style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://blog.tlsys.hu/symfony-widgetek/"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>Symfony widgeteket fogok ide kirakni, néhol egy icipici kis magyarázattal.<br />
<span id="more-139"></span></p>
<p><strong>datePicker:</strong></p>
<pre class="brush: php; title: ; notranslate">
class datePickerWidget extends sfWidgetFormInput
{

  public function configure($options = array(), $attributes = array())
  {
    $this-&gt;addOption('ifFormat', &quot;%Y-%m-%d&quot;);
    parent::configure($options, $attributes);
  }

  public function render($name, $value = null, $attributes = array(), $errors = array())
  {
    use_helper('Javascript', 'wtCurrency');
    $response = sfContext::getInstance()-&gt;getResponse();
    $response-&gt;addStylesheet('/sf/calendar/calendar-system.css');
    $response-&gt;addJavascript('/sf/calendar/calendar.js');
    $response-&gt;addJavascript('/sf/calendar/lang/calendar-en.js');
    $response-&gt;addJavascript('/sf/calendar/calendar-setup.js');
    $response-&gt;addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/prototype');

    $picker = javascript_tag(&quot;
      Calendar.setup(
      {
        inputField  : '&quot;.$this-&gt;generateId($name).&quot;',
        ifFormat    : '&quot;.$this-&gt;getOption('ifFormat').&quot;',
        button      : 'trigger',    // ID of the button
      })
    &quot;);
    return parent::render($name, $value, $attributes, $errors) . $picker;
  }
}
</pre>
<p><strong>Autocompliter:</strong><br />
<a href="http://www.symfony-project.org/plugins/sfExtraWidgetsPlugin/1_0_5">innen az eredeti</a></p>
<pre class="brush: php; title: ; notranslate">
class sfExtraWidgetFormInputAutocomplete extends sfWidgetFormInput
{
    public function configure($options = array(), $attributes = array())
    {
        $this-&gt;addRequiredOption('url');
        $this-&gt;addOption('param', 'autocomplete');
        $this-&gt;addOption('min_chars', 2);
        $this-&gt;addOption('afterUpdateElement','');
        parent::configure($options, $attributes);
    }

    public function render($name, $value = null, $attributes = array(), $errors = array())
    {
        $response = sfContext::getInstance()-&gt;getResponse();
        $response-&gt;addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/prototype');
        $response-&gt;addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/scriptaculous.js');
        sfLoader::loadHelpers(array('Javascript'));
        $response-&gt;addStylesheet('/sfExtraWidgetsPlugin/css/autocompleter.css');

        $autocompleteDiv = content_tag('div' , '', array('id' =&gt; $this-&gt;generateId($name) . '_autocomplete', 'class' =&gt; 'autocomplete'));

        $autocompleteJs = javascript_tag(
            &quot;function ac_update_&quot; . $this-&gt;generateId($name) . &quot;(text, li)
            {
                $('&quot; . $this-&gt;generateId($name) . &quot;').value = li.innerHTML;
                &quot;.$this-&gt;getOption('afterUpdateElement').&quot;
            }

            new Ajax.Autocompleter(
                '&quot; . $this-&gt;generateId($name) . &quot;',
                '&quot; . $this-&gt;generateId($name) . '_autocomplete' . &quot;',
                '&quot; . url_for($this-&gt;getOption('url')) . &quot;',
                {
                    paramName: '&quot; . $this-&gt;getOption('param') . &quot;',
                    indicator: 'indicator-&quot; . $this-&gt;generateId($name) . &quot;',
                    minChars: &quot; . $this-&gt;getOption('min_chars') . &quot;,
                    afterUpdateElement: ac_update_&quot; . $this-&gt;generateId($name) . &quot;
                });&quot;
            );

        return parent::render($name, $value, $attributes, $errors) .
        '&lt;span id=&quot;indicator-' . $this-&gt;generateId($name) . '&quot; style=&quot;display: none;&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;img src=&quot;/sfExtraWidgetsPlugin/img/ajax-loader.gif&quot; align=&quot;absmiddle&quot; alt=&quot;Loading&quot; /&gt;&lt;/span&gt;' .
        $autocompleteDiv .
        $autocompleteJs;
    }
}
</pre>
<p>használata:<br />
widget:</p>
<pre class="brush: php; title: ; notranslate">
$this-&gt;widgetSchema['nevsearch']     = new sfExtraWidgetFormInputAutocomplete(array(
            'url'=&gt;'modul/action',
            'afterUpdateElement'=&gt;'afterUpdateElement_nevsearch(text, li)'));
// ezt a javascript függvényt létre kell hozni.
//vagy egyszerűen az eredti módszerrel:
$this-&gt;widgetSchema['projekt']   = new sfExtraWidgetFormInputAutocomplete(array('url'=&gt;'modul/action'));
</pre>
<p>actionSuccess.php</p>
<pre class="brush: php; title: ; notranslate">
&lt;ul&gt;
  &lt;?php foreach ($words as $value):?&gt;
    &lt;li id='&lt;?php echo $value?&gt;'&gt;&lt;?php echo $value?&gt;&lt;/li&gt;
  &lt;?php endforeach?&gt;
&lt;/ul&gt;
</pre>
<p><strong> checkbox</strong></p>
<pre class="brush: php; title: ; notranslate">$this-&gt;widgetSchema['checkbox'] = new sfWidgetFormInputCheckbox();
$this-&gt;validatorSchema['checkbox'] = new sfValidatorPass();</pre>
<p><strong> checkbox rejtett false értékkel</strong><br />
A&#8217; la cakephp. A lényeg hogy vizsgálhassuk a mező értékét, mert a symfonyban alapból nem jön semmi a post adatokkal, ha a checkbox nincs kiválasztva&#8230;</p>
<pre class="brush: php; title: ; notranslate">
class sfWidgetFormInputCheckboxExtend extends sfWidgetFormInputCheckbox
{
  public function render($name, $value = null, $attributes = array(), $errors = array())
  {
    $hidden = new sfWidgetFormInputHidden();
    $hidden = $hidden-&gt;render($name, 0, array('id'=&gt;false));

    $value = ($value == 0) ? null : $value;
    $attributes['value'] = 1;

    return $hidden.parent::render($name, $value, $attributes, $errors);
  }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.tlsys.hu/symfony-widgetek/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adatok exportálása csv fájlba</title>
		<link>http://blog.tlsys.hu/adatok-exportalasa-csv-fajlba/</link>
		<comments>http://blog.tlsys.hu/adatok-exportalasa-csv-fajlba/#comments</comments>
		<pubDate>Wed, 13 Jan 2010 14:15:40 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Symfony]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.tlsys.hu/?p=33</guid>
		<description><![CDATA[
			
			
			
			
			
			
			Tweet
						
						
			a eredeti hogyan:
Symfony Howto: Export tabular data to a csv file?
Ennek teljese kidolgozott változata található itt.
A mymodule/Csv az adatokat ;-vel elválasztva megjeleníti.
Action:

&#60;?php
class mymoduleActions extends autoMyActions
{
  public function executeCsv(sfWebRequest $request)
  {
    $this-&#62;pager = $this-&#62;getPager();
    $c=$this-&#62;pager-&#62;getCriteria();
    $c-&#62;setLimit(false);
    $this-&#62;rows=$this-&#62;pager-&#62;getResults();
     // [...]]]></description>
			<content:encoded><![CDATA[<div class="bottomcontainerBox" style="border:1px solid #808080;background-color:#F0F4F9;">
			<div style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.tlsys.hu%2Fadatok-exportalasa-csv-fajlba%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div>
			<div style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<g:plusone size="medium" href="http://blog.tlsys.hu/adatok-exportalasa-csv-fajlba/"></g:plusone>
			</div>
			<div style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;">
			<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://blog.tlsys.hu/adatok-exportalasa-csv-fajlba/"  data-text="Adatok exportálása csv fájlba" data-count="horizontal">Tweet</a>
			</div><div style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://blog.tlsys.hu/adatok-exportalasa-csv-fajlba/" data-counter="right"></script></div>			
			<div style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://blog.tlsys.hu/adatok-exportalasa-csv-fajlba/"></script></div>			
			</div><div style="clear:both"></div><div style="padding-bottom:4px;"></div><p>a eredeti hogyan:<br />
<a href="http://trac.symfony-project.org/wiki/HowToExportTabularData#SymfonyHowto:Exporttabulardatatoacsvfile">Symfony Howto: Export tabular data to a csv file?</a><br />
Ennek teljese kidolgozott változata található itt.<br />
<span id="more-33"></span>A mymodule/Csv az adatokat ;-vel elválasztva megjeleníti.<br />
Action:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
class mymoduleActions extends autoMyActions
{
  public function executeCsv(sfWebRequest $request)
  {
    $this-&gt;pager = $this-&gt;getPager();
    $c=$this-&gt;pager-&gt;getCriteria();
    $c-&gt;setLimit(false);
    $this-&gt;rows=$this-&gt;pager-&gt;getResults();
     // $response = $this-&gt;getResponse();
     // $response-&gt;setHttpHeader('Content-type', 'application/msexcel');
     // $response-&gt;setHttpHeader('Content-Disposition', 'attachment; filename=akarmi.csv');
  }
}
</pre>
<p>csvSuccess.php:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
 use_helper('I18N');
 $rowBefore = '';
 $rowAfter  = &quot;\r\n&quot;;
 $cellBefore = '';
 $cellAfter = ';';
 $cellHeadBefore = '';
 $cellHeadAfter =';';
 echo $rowBefore;
 echo $cellHeadBefore.iconv('UTF-8', 'WINDOWS-1250', __('Head1')).$cellHeadAfter;
 echo $cellHeadBefore.iconv('UTF-8', 'WINDOWS-1250', __('Head1')).$cellHeadAfter;
 echo $rowAfter;
 foreach($rows as $row)
 {
   echo $rowBefore;
   echo $cellBefore.iconv('UTF-8', 'WINDOWS-1250', $row-&gt;getMezo1()).$cellAfter;
   echo $cellBefore.iconv('UTF-8', 'WINDOWS-1250', $row-&gt;getMezo2()).$cellAfter;
   echo $rowAfter;
 }
</pre>
<p>Ezután már csak a következőket kell beállítani:</p>
<ul>
<li>vigyünk fel egy új routing szabályt a routing.yml fájlba
<pre class="brush: plain; title: ; notranslate">
export_excel:
  url:    /export.csv
  param:  {module: myModule, action: csv}
</pre>
</li>
</ul>
<ul>
<li>Apache mod_rewrite esetén egy új szabályra van szükség az apache .htaccess fájlba a .csv fájlok elérése végett.
<pre class="brush: plain; title: ; notranslate">RewriteCond %{REQUEST_URI} !\.csv$</pre>
</li>
</ul>
<ul>
<li>A mymodule/config/view.yml fájlba vigyük fel az aléábbi sorokat:
<pre class="brush: plain; title: ; notranslate">
csvSuccess:
  has_layout: off
  http_metas:
    content-type: application/msexcel
    Content-Disposition: attachment; filename=mymodule_&lt;?php echo date('Ymd')?&gt;.csv</pre>
</li>
<li> vagy az actionben
<pre class="brush: php; title: ; notranslate">
      $response = $this-&gt;getResponse();
      $response-&gt;setHttpHeader('Content-type', 'application/msexcel');
      $response-&gt;setHttpHeader('Content-Disposition', 'attachment; filename=mymodule-'.date('Ymd').'.csv');
      $this-&gt;setLayout(false);
</pre>
</li>
</ul>
<p><a href="http://weblogs.asp.net/michu/archive/2004/06/15/155851.aspx">még egy fontos dolog:</a><br />
Vagyis ha a szokványos módon csak egy táblázatot teszünk ki és azt mondjuk hogy az egy Excel fájl, akkor néha szükség lehet egy cellában több sorra is, akkor a &lt;br&gt; az alábbi stílussal fog működni:</p>
<pre class="brush: php; title: ; notranslate">
br {mso-data-placement:same-cell;}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.tlsys.hu/adatok-exportalasa-csv-fajlba/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

