<?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>Sandbox Web Solutions &#187; Frameworks</title>
	<atom:link href="http://sandbox-ws.com/category/frameworks/feed" rel="self" type="application/rss+xml" />
	<link>http://sandbox-ws.com</link>
	<description>Personal Blog of Ahmed El.Hussaini</description>
	<lastBuildDate>Mon, 23 Aug 2010 11:33:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>How to Embed Forms in Symfony 1.2 Admin Generator Part 3</title>
		<link>http://sandbox-ws.com/frameworks/symfony-frameworks/how-to-embed-forms-in-symfony-12-admin-generator-part-3</link>
		<comments>http://sandbox-ws.com/frameworks/symfony-frameworks/how-to-embed-forms-in-symfony-12-admin-generator-part-3#comments</comments>
		<pubDate>Sun, 18 Jan 2009 22:13:28 +0000</pubDate>
		<dc:creator>Ahmed El.Hussaini</dc:creator>
				<category><![CDATA[symfony]]></category>
		<category><![CDATA[admin generator]]></category>
		<category><![CDATA[i18n]]></category>

		<guid isPermaLink="false">http://sandbox-ws.com/?p=294</guid>
		<description><![CDATA[In the last part of this series of articles we introduced the ability to edit multiple child models in the edit screen of the parent model. In this part we will take it a step further by adding I18N behavior to the child models. To make things a little bit clear before we start coding [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fsandbox-ws.com%2Fframeworks%2Fsymfony-frameworks%2Fhow-to-embed-forms-in-symfony-12-admin-generator-part-3"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fsandbox-ws.com%2Fframeworks%2Fsymfony-frameworks%2Fhow-to-embed-forms-in-symfony-12-admin-generator-part-3&amp;source=sandboxws&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p>In the last <a href="http://sandbox-ws.com/how-to-embed-forms-in-symfony-12-admin-generator-part-2">part</a> of this series of articles we introduced the ability to edit multiple child models in the edit screen of the parent model. In this part we will take it a step further by adding I18N behavior to the child models. To make things a little bit clear before we start coding please take a look at the result we want to achieve below.</p>
<p><span id="more-294"></span></p>
<p><img src="http://sandbox-ws.com/wp-content/uploads/2009/01/embed_i18n.png" alt="embed_i18n" title="embed_i18n" width="540" height="330" class="aligncenter size-full wp-image-295" /></p>
<p>Before starting I strongly recommend reading part <a href="http://sandbox-ws.com/how-to-embed-forms-in-symfony-12-admin-generator">one</a>, and <a href="http://sandbox-ws.com/how-to-embed-forms-in-symfony-12-admin-generator-part-2">two</a> if you haven&#8217;t done so already. OK lets get started, we will be modifying the following files:</p>
<ul>
<li><strong>CategoryForm.class.php</strong> which represents the parent model</li>
<li><strong>SubcategoryI18nForm.class.php</strong> which represents the form of the i18n model of the child model</li>
<li><strong>Subcategory.class.php</strong> which represents the child model</li>
</ul>
<h3>Files need for this article</h3>
<ul>
<li><a href="http://sandbox-ws.com/wp-content/uploads/2009/01/sfWidgetFormInputDelete.class.php.zip">sfWidgetFormInputDelete</a></li>
</ul>
<h4>Schema</h4>
<pre class="brush: php;">
  category:
      _attributes: { phpName: Category }
      id: { type: INTEGER, size: '11', primaryKey: true, autoIncrement: true, required: true }
      name: { type: VARCHAR, size: '255', required: true }
      created_at: { type: TIMESTAMP, required: false }
      updated_at: { type: TIMESTAMP, required: false }
  subcategory:
      _attributes: { phpName: Subcategory, isI18N: true, i18nTable: subcategory_i18n }
      id:          { type: integer, required: true, primaryKey: true, autoincrement: true }
      category_id: { type: INTEGER, size: '11', required: true, foreignTable: category, foreignReference: id, onDelete: CASCADE}
      created_at: { type: TIMESTAMP, required: false }
      updated_at: { type: TIMESTAMP, required: false }

  subcategory_i18n:
    _attributes: { phpName: SubcategoryI18n }
    id:          { type: integer, required: true, primaryKey: true, foreignTable: subcategory, foreignReference: id, onDelete: CASCADE }
    culture:     { isCulture: true, type: varchar, size: 7, required: true, primaryKey: true }
    name:        { type: varchar, size: 50 }
</pre>
<h4>SubcategoryI18nForm</h4>
<pre class="brush: php;">
public function configure() {
    unset($this['culture'], $this['id']);
}
</pre>
<h4>Subcategory</h4>
<pre class="brush: php;">
public function getI18nObject($culture = 'en') {

    $this-&gt;setCulture($culture);

    $i18ns = $this-&gt;getSubcategoryI18ns();

    if (isset($i18ns[0])) {

        return $i18ns[0];

    }

    return null;

}
</pre>
<h4>CategoryForm</h4>
<pre class="brush: php;">
public function configure() {

// remove timestamps
unset($this['created_at'], $this['updated_at']);

	// embed forms only when editing
	if (!$this-&gt;isNew()) {

		$user_culture = sfContext::getInstance()-&gt;getUser()-&gt;getCulture();

		// embed all subcategory forms
		foreach ($this-&gt;getObject()-&gt;getSubcategorys() as $subcategory) {

			// get the subcategory_i18n model object relative to the current user culture
			$subcategory_i18n_object = $subcategory-&gt;getI18nObject($user_culture);

			// create a new subcategory_i18n form for the current subcategory model object
			$subcategory_i18n_form = new SubcategoryI18nForm($subcategory-&gt;getI18nObject('en'));

			// get widget schema of subcategory_i18n form
			$subcategory_i18n_form_widget_schema = $subcategory_i18n_form-&gt;getWidgetSchema();

			// set the input delete widget
			$subcategory_i18n_form_widget_schema['name'] = new sfWidgetFormInputDelete(array(
			'url' =&gt; 'category/deleteSubcategory',      // required
			'model_id' =&gt; $subcategory-&gt;getId(),        // required
			'confirm' =&gt; 'Sure???',                     // optional
			));

			// create a new subcategory form for the current subcategory model object
			$subcategory_form = new SubcategoryForm($subcategory);

			// embed the i18n form
			$subcategory_form-&gt;embedForm('subcategory_i18n'.$subcategory_i18n_object-&gt;getId(), $subcategory_i18n_form);

			// subcategory form widget schema
			$subcategory_form_widget_schema = $subcategory_form-&gt;getWidgetSchema();

			// disable label
			$subcategory_form_widget_schema['subcategory_i18n'.$subcategory_i18n_object-&gt;getId()]-&gt;setLabel(false);

			// embed the subcategory form in the main category form
			$this-&gt;embedForm('subcategory'.$subcategory-&gt;getId(), $subcategory_form);

			// set a custom label for the embedded form
			$this-&gt;widgetSchema['subcategory'.$subcategory-&gt;getId()]-&gt;setLabel('Subcategory: '.$subcategory-&gt;getName());

		}

		// create a new subcategory form for a new subcategory model object
		$subcategory_form = new SubcategoryForm();

		// create a new subcategory form for a new subcategory_i18n model object
		$subcategory_i18n_form = new SubcategoryI18nForm();

		// embed the subcategory_i18n form in the parent subcategory form
		$subcategory_form-&gt;embedForm('subcategory_i18n', $subcategory_i18n_form);

		// subcategory form widget schema
		$subcategory_form_widget_schema = $subcategory_form-&gt;getWidgetSchema();

		// disable label
		$subcategory_form_widget_schema['subcategory_i18n']-&gt;setLabel(false);

		// embed the subcategory form in the main category form
		$this-&gt;embedForm('subcategory', $subcategory_form);

		// set a custom label for the embedded form
		$this-&gt;widgetSchema['subcategory']-&gt;setLabel('New Subcategory');

	}
}
public function bind(array $taintedValues = null, array $taintedFiles = null) {

		if(!$this-&gt;isNew()) {

			$user_culture = sfContext::getInstance()-&gt;getUser()-&gt;getCulture();

			// remove the embedded new form if the name field was not provided
			if (is_null($taintedValues['subcategory']['subcategory_i18n']['name']) || strlen($taintedValues['subcategory']['subcategory_i18n']['name']) === 0 ) {

				unset($this-&gt;embeddedForms['subcategory'], $taintedValues['subcategory']);

				// pass the new form validations
				$this-&gt;validatorSchema['subcategory'] = new sfValidatorPass();

			} else {

				// set the category of the new subcategory form object
				$this-&gt;embeddedForms['subcategory']-&gt;getObject()-&gt;setCategory($this-&gt;getObject());

				// get subcategory embedded forms
				$subcategory_embedded_forms = $this-&gt;embeddedForms['subcategory']-&gt;getEmbeddedForms();

				// set subcategory parent of the subcategory_i18n model object
				$subcategory_embedded_forms['subcategory_i18n']-&gt;getObject()-&gt;setSubcategory($this-&gt;embeddedForms['subcategory']-&gt;getObject());

				// set the culture of the subcategory_i18n model object
				$subcategory_embedded_forms['subcategory_i18n']-&gt;getObject()-&gt;setCulture($user_culture);
			}

		}

		// call parent bind method
		parent::bind($taintedValues, $taintedFiles);

	}
</pre>
<p>As you can see this is a lot of code to copy and paste every time you need the functionality, that&#8217;s why I&#8217;m currently working on extending the Admin Generator in order to have this functionality available when you generate an admin module by default.</p>
]]></content:encoded>
			<wfw:commentRss>http://sandbox-ws.com/frameworks/symfony-frameworks/how-to-embed-forms-in-symfony-12-admin-generator-part-3/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to Embed Forms in Symfony 1.2 Admin Generator Part 2</title>
		<link>http://sandbox-ws.com/frameworks/symfony-frameworks/how-to-embed-forms-in-symfony-12-admin-generator-part-2</link>
		<comments>http://sandbox-ws.com/frameworks/symfony-frameworks/how-to-embed-forms-in-symfony-12-admin-generator-part-2#comments</comments>
		<pubDate>Wed, 07 Jan 2009 12:13:50 +0000</pubDate>
		<dc:creator>Ahmed El.Hussaini</dc:creator>
				<category><![CDATA[symfony]]></category>
		<category><![CDATA[admin generator]]></category>

		<guid isPermaLink="false">http://sandbox-ws.com/?p=261</guid>
		<description><![CDATA[In part one of this article we saw how to embed forms in a one-to-one relationship. But I often run into a situation where I want to edit a parent model, it&#8217;s children models, and maybe add a new child model while I&#8217;m at it, greedy I know, but isn&#8217;t that the reason why we [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fsandbox-ws.com%2Fframeworks%2Fsymfony-frameworks%2Fhow-to-embed-forms-in-symfony-12-admin-generator-part-2"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fsandbox-ws.com%2Fframeworks%2Fsymfony-frameworks%2Fhow-to-embed-forms-in-symfony-12-admin-generator-part-2&amp;source=sandboxws&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p>In part <a href="http://sandbox-ws.com/how-to-embed-forms-in-symfony-12-admin-generator">one</a> of this article we saw how to embed forms in a one-to-one relationship. But I often run into a situation where I want to edit a parent model, it&#8217;s children models, and maybe add a new child model while I&#8217;m at it, greedy I know, but isn&#8217;t that the reason why we use the admin generator. Anyway in this article we will examine the one-to-many relationship.<br />
<span id="more-261"></span></p>
<p style="text-align: center;">Before we get started here&#8217;s a sneak peak of the <strong>CategoryForm</strong> after the modifications to be done.<br />
<img class="aligncenter size-full wp-image-269" title="embed_2" src="http://sandbox-ws.com/wp-content/uploads/2009/01/embed_2.png" alt="embed_2" width="600" height="343" /></p>
<h3>Files need for this article</h3>
<ul>
<li><a href="http://sandbox-ws.com/wp-content/uploads/2009/01/sfWidgetFormInputDelete.class.php.zip">sfWidgetFormInputDelete</a></li>
</ul>
<p>Ok, lets get started, consider the following schema:</p>
<pre class="brush: php;">category:
    _attributes: { phpName: Category }
    id: { type: INTEGER, size: '11', primaryKey: true, autoIncrement: true, required: true }
    name: { type: VARCHAR, size: '255', required: true }
    created_at: { type: TIMESTAMP, required: false }
    updated_at: { type: TIMESTAMP, required: false }
subcategory:
    _attributes: { phpName: Subcategory }
    id: { type: INTEGER, size: '11', primaryKey: true, autoIncrement: true, required: true }
    name: { type: VARCHAR, size: '255', required: true }
    category_id: { type: INTEGER, size: '11', required: true, foreignTable: category, foreignReference: id, onDelete: CASCADE, onUpdate: RESTRICT }
    created_at: { type: TIMESTAMP, required: false }
    updated_at: { type: TIMESTAMP, required: false }</pre>
<h3>Steps needed to achieve the required result</h3>
<ol>
<li>Modify the <strong>CategoryForm</strong> to include embedded forms for all available subcategories of the current category.</li>
<li>Modify the widget of the <strong>name</strong> field in the subcategory</li>
<li>Modify the CategoryForm to add a new blank subcategory form</li>
<li>Override the <strong>bind</strong> method of the <strong>sfForm</strong> class to skip saving and validating the new subcategory form if the <strong>name</strong> field was left blank</li>
<li>Remove fields from <strong>SubcategoryForm</strong></li>
</ol>
<h4>Embedded forms for all available subcategories of the current category [step 1, 2, and 3]</h4>
<pre class="brush: php;">// lib/forms/CategoryForm.class.php
public function configure() {

  // remove timestamps
  unset($this['created_at'], $this['updated_at']);

  // embed forms only when editing
  if (!$this-&gt;isNew()) {

    // embed all subcategory forms
    foreach ($this-&gt;getObject()-&gt;getSubcategorys() as $subcategory) {

    // create a new subcategory form for the current subcategory model object
    $subcategory_form = new SubcategoryForm($subcategory);

    // embed the subcategory form in the main category form
    $this-&gt;embedForm('subcategory'.$subcategory-&gt;getId(), $subcategory_form);

    // set a custom label for the embedded form
    $this-&gt;widgetSchema['subcategory'.$subcategory-&gt;getId()]-&gt;setLabel('Subcategory: '.$subcategory-&gt;getName());

    // change the name widget to sfWidgetFormInputDelete
    $this-&gt;widgetSchema['subcategory'.$subcategory-&gt;getId()]['name'] = new sfWidgetFormInputDelete(array(
    'url' =&gt; 'category/deleteSubcategory',      // required
    'model_id' =&gt; $subcategory-&gt;getId(),        // required
    'confirm' =&gt; 'Sure???',                     // optional
    ));

  }

  // create a new subcategory form for a new subcategory model object
  $subcategory_form = new SubcategoryForm();

  // embed the subcategory form in the main category form
  $this-&gt;embedForm('subcategory', $subcategory_form);

  // set a custom label for the embedded form
  $this-&gt;widgetSchema['subcategory']-&gt;setLabel('New Subcategory');

  }
}</pre>
<h4>Override the bind method</h4>
<pre class="brush: php;">public function bind(array $taintedValues = null, array $taintedFiles = null) {

	// remove the embedded new form if the name field was not provided
	if (is_null($taintedValues['subcategory']['name']) || strlen($taintedValues['subcategory']['name']) === 0 ) {

		unset($this-&gt;embeddedForms['subcategory'], $taintedValues['subcategory']);

		// pass the new form validations
		$this-&gt;validatorSchema['subcategory'] = new sfValidatorPass();

	} else {

		// set the category of the new subcategory form object
		$this-&gt;embeddedForms['subcategory']-&gt;getObject()-&gt;
                setCategory($this-&gt;getObject());

	}

	// call parent bind method
	parent::bind($taintedValues, $taintedFiles);

}</pre>
<h4>Remove fields from SubcategoryForm</h4>
<pre class="brush: php;">public function configure(){
  unset($this['created_at'], $this['updated_at'], $this['category_id']);
}</pre>
<h4>Now we create the action <em>deleteSubcategory</em> in <strong>category module</strong></h4>
<pre class="brush: php;">
// apps/backend/modules/category/actions/actions.class.php
public function executeDeleteSubcategory(sfWebRequest $request) {
  $sub_category = SubcategoryPeer::retrieveByPk($request-&gt;getParameter('id'));
  $sub_category-&gt;delete();
  $this-&gt;redirect('@category_edit?id='.$sub_category-&gt;getCategory()-&gt;getId());
}
</pre>
<p>That&#8217;s it, I hop that you enjoyed this article.</p>
]]></content:encoded>
			<wfw:commentRss>http://sandbox-ws.com/frameworks/symfony-frameworks/how-to-embed-forms-in-symfony-12-admin-generator-part-2/feed</wfw:commentRss>
		<slash:comments>58</slash:comments>
		</item>
		<item>
		<title>Functional Testing a Secured Module</title>
		<link>http://sandbox-ws.com/frameworks/symfony-frameworks/functional-testing-a-secured-module</link>
		<comments>http://sandbox-ws.com/frameworks/symfony-frameworks/functional-testing-a-secured-module#comments</comments>
		<pubDate>Mon, 05 Jan 2009 16:08:32 +0000</pubDate>
		<dc:creator>Ahmed El.Hussaini</dc:creator>
				<category><![CDATA[symfony]]></category>
		<category><![CDATA[lime]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://sandbox-ws.com/?p=244</guid>
		<description><![CDATA[Most of the modules we work on in symfony are secured with the popular sfGuardPlugin, but by default you can&#8217;t test a secured module each time you will try to access an action from your functional testing file will result in failure of the test. To make my point a little bit clear consider that [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fsandbox-ws.com%2Fframeworks%2Fsymfony-frameworks%2Ffunctional-testing-a-secured-module"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fsandbox-ws.com%2Fframeworks%2Fsymfony-frameworks%2Ffunctional-testing-a-secured-module&amp;source=sandboxws&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p>Most of the modules we work on in <a href="http://symfony-project.org/" target="_blank">symfony</a> are secured with the popular <a href="http://www.symfony-project.org/plugins/sfGuardPlugin" target="_blank">sfGuardPlugin</a>, but by default you can&#8217;t test a secured module each time you will try to access an action from your functional testing file will result in failure of the test. To make my point a little bit clear consider that we have a module called <b>foobar</b> in an application called <b>backend</b>. Of course as you know that when you create the module, automatically a file called <b>foobarActionsTest.php</b> is created in <b>test/functional/backend</b>.<br />
<span id="more-244"></span><br />
So we edit the <b>foobarActionsTest.php</b> contents to match the following snippet:</p>
<pre class="brush: php;">
// test/functional/backend/foobarActionsTest.php
include(dirname(__FILE__).'/../../bootstrap/functional.php');

$browser = new sfTestFunctional(new sfBrowser());
$browser-&gt;get('foobar/index')-&gt;isStatusCode(200);
</pre>
<p>Now we run the following command to test the module:</p>
<pre class="brush: php;">
php symfony test:functional backend foobarActions
</pre>
<p>Since the backend application is secured, the above test will result in the following error:<br />
<img src="http://sandbox-ws.com/wp-content/uploads/2009/01/test_1.png" alt="test_1" title="test_1" width="630" height="126" class="aligncenter size-full wp-image-248" /></p>
<p>The 401 response code we got means Unauthorized access, since the user isn&#8217;t logged, so this is what we need to make the test successful, we need the user to login first before we try to access the foobar/index action.</p>
<p>The solutions is rather simple, first we create a file called <b>sf_guard.php</b>:</p>
<pre class="brush: php;">
// test/functional/sf_guard.php
function signin($username, $password, $browser) {
  $browser = new sfTestFunctional(new sfBrowser());
  return $browser-&gt;
    info(sprintf('Signin user using username &quot;%s&quot; and password &quot;%s&quot;', $username, $password))-&gt;
    post('/sfGuardAuth/signin', array('signin' =&gt; array('username' =&gt; $username, 'password' =&gt; $password,)))-&gt;
    isRedirected()
  ;
}
</pre>
<p>Next we modify the <b>foobarActionsTest.php</b>:</p>
<pre class="brush: php;">
include(dirname(__FILE__).'/../sf_guard.php');
include(dirname(__FILE__).'/../../bootstrap/functional.php');

$username = 'admin';
$password = 'admin';
$browser = new sfTestFunctional(new sfBrowser());
signin($username, $password, $browser)-&gt;get('/foobar/index')-&gt;isStatusCode(200);
</pre>
<p>Now we run the test again, and it passes gracefully<br />
<img src="http://sandbox-ws.com/wp-content/uploads/2009/01/test_2.png" alt="test_2" title="test_2" width="590" height="128" class="aligncenter size-full wp-image-250" /></p>
<p>Now as <a href="http://prendreuncafe.com/">Niko</a> mentioned in his comment, her is another better and simpler way:<br />
 First we create a class <b>sfGuardTestFunctional</b> in <b>lib</b> folder</p>
<pre class="brush: php;">
class sfGuardTestFunctional extends sfTestFunctional {

	public function signin($username, $password) {
		return $this-&gt;
			info(sprintf('Signin user using username &quot;%s&quot; and password &quot;%s&quot;', $username, $password))-&gt;
			post('/sfGuardAuth/signin', array('signin' =&gt; array('username' =&gt; $username, 'password' =&gt; $password,)))-&gt;
			isRedirected()
		;
	}
}
</pre>
<p>Next we modify the <b>foobarActionsTest.php</b></p>
<pre class="brush: php;">
include(dirname(__FILE__).'/../../bootstrap/functional.php');

$username = 'admin';
$password = 'admin';

$browser = new sfGuardTestFunctional(new sfBrowser());
$browser-&gt;
	get('/foobar/index')-&gt;
	isStatusCode(401)-&gt;
	signin($username, $password)-&gt;
	get('/foobar/index')-&gt;
	isStatusCode(200)
;
</pre>
<p>That way it&#8217;s much simpler and more efficient, thanks again <a href="http://prendreuncafe.com/">Niko</a></p>
]]></content:encoded>
			<wfw:commentRss>http://sandbox-ws.com/frameworks/symfony-frameworks/functional-testing-a-secured-module/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>sfJqueryWidgetsPlugin</title>
		<link>http://sandbox-ws.com/frameworks/symfony-frameworks/sfjquerywidgetsplugin</link>
		<comments>http://sandbox-ws.com/frameworks/symfony-frameworks/sfjquerywidgetsplugin#comments</comments>
		<pubDate>Thu, 01 Jan 2009 17:12:31 +0000</pubDate>
		<dc:creator>Ahmed El.Hussaini</dc:creator>
				<category><![CDATA[symfony]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[widgets]]></category>

		<guid isPermaLink="false">http://sandbox-ws.com/?p=233</guid>
		<description><![CDATA[The sfJqueryWidgetsPlugin is a symfony plugin that adds two jquery widgets to the list of available widgets bundled in the framework. The two widgets are: Drop down list that fires an Ajax request upon DOM event. Sortable list that fires an Ajax request upon change. Installation Install the Plugin &#60;code&#62;$ symfony plugin:install sfJqueryWidgetsPlugin Clear Your [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fsandbox-ws.com%2Fframeworks%2Fsymfony-frameworks%2Fsfjquerywidgetsplugin"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fsandbox-ws.com%2Fframeworks%2Fsymfony-frameworks%2Fsfjquerywidgetsplugin&amp;source=sandboxws&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p>The <strong><a href="http://www.symfony-project.org/plugins/sfJqueryWidgetsPlugin?">sfJqueryWidgetsPlugin</a></strong> is a symfony plugin that adds two jquery widgets to the list of available widgets bundled in the framework.</p>
<p><span id="more-233"></span></p>
<p>The two widgets are:</p>
<ul>
<li>Drop down list that fires an Ajax request upon DOM event.</li>
<li>Sortable list that fires an Ajax request upon change.</li>
</ul>
<h5>Installation</h5>
<ol class="steps">
<li><span>Install the Plugin</span>
<pre class="brush: php;">&lt;code&gt;$ symfony plugin:install sfJqueryWidgetsPlugin
</pre>
</li>
<li>Clear Your Cache
<pre class="brush: php;">&lt;code&gt;$ symfony cc
</pre>
</li>
<li>Publish Plugins Assets
<pre class="brush: php;">&lt;code&gt;$ symfony plugin:publish-assets
</pre>
</li>
</ol>
<h5>Usage</h5>
<h5>sfWidgetFormPropelSelectAjax</h5>
<p>Consider that you want in the admin generator for example to fetch subcategories of a certain category using ajax. You already have in the form the drop down list that shows a list of categories, what is missing is the ajax request fired upon change of the drop down list. Normally the ajax request is sent to an action that fetches the subcategories of the selected category and maybe displays them also in a drop down list.</p>
<h5>Usage</h5>
<p>We need to change the type of widget used to display the category drop down list from sfWidgetFormPropelSelect to sfWidgetFormPropelSelectAjax</p>
<pre class="brush: php;">  $this-&gt;widgetSchema['category'] = new sfWidgetFormPropelSelectAjax(array(
    'model' =&gt; 'Category',
    'method' =&gt; 'getName',
    'url' =&gt; 'test/ajax'
  ));
</pre>
<p>As you can see in the above snippet we simply specify the <strong>model</strong> to be used for fetching the records to be displayed in the drop down list, next we specify the <strong>method</strong> used to display the text in the drop down list, and lastly we specify the <strong>url</strong> to which the<br />
ajax request is sent to.</p>
<p>In the <em>action</em> <strong>test/ajax</strong> you can fetch the <em>id</em> of the selected category from the request parameter <strong>id</strong></p>
<h5>sfWidgetFormPropelJQuerySortable</h5>
<p>This is a really cool and effective widget, it allows sorting of a list of models and it&#8217;s so easy to use.</p>
<h5>Usage</h5>
<pre class="brush: php;">  $this-&gt;widgetSchema['categories'] = new sfWidgetFormPropelJQuerySortable(array(
    'model' =&gt; 'Category',
    'url' =&gt; 'section/new',
  ));
</pre>
<p>In the <em>action</em> <strong>section/new</strong> you can fetch the sorted list using the request parameter <strong>id</strong></p>
<div class="note">
<p>For a complete list of parameters and examples please refer to the phpdocs included in he plugin</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://sandbox-ws.com/frameworks/symfony-frameworks/sfjquerywidgetsplugin/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>How to embed forms in symfony 1.2 admin generator</title>
		<link>http://sandbox-ws.com/frameworks/symfony-frameworks/how-to-embed-forms-in-symfony-12-admin-generator</link>
		<comments>http://sandbox-ws.com/frameworks/symfony-frameworks/how-to-embed-forms-in-symfony-12-admin-generator#comments</comments>
		<pubDate>Sat, 20 Dec 2008 18:00:01 +0000</pubDate>
		<dc:creator>Ahmed El.Hussaini</dc:creator>
				<category><![CDATA[symfony]]></category>
		<category><![CDATA[admin generator]]></category>

		<guid isPermaLink="false">http://sandbox-ws.com/?p=163</guid>
		<description><![CDATA[Symfony 1.2 added a lot of new and exciting new features to an already great and powerful PHP framework. One of those features is the ability to embed a form into another. So what excatly does this mean? First consider the model shown in the diagram below: As shown in the above figure, there is [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fsandbox-ws.com%2Fframeworks%2Fsymfony-frameworks%2Fhow-to-embed-forms-in-symfony-12-admin-generator"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fsandbox-ws.com%2Fframeworks%2Fsymfony-frameworks%2Fhow-to-embed-forms-in-symfony-12-admin-generator&amp;source=sandboxws&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p>Symfony 1.2 added a lot of new and exciting new features to an already great and powerful PHP framework. One of those features is the ability to embed a form into another. So what excatly does this mean?</p>
<p><span id="more-163"></span></p>
<p>First consider the model shown in the diagram below:<br />
<img class="aligncenter size-full wp-image-169" title="company_contact" src="http://sandbox-ws.com/wp-content/uploads/2008/12/company_contact.jpg" alt="company_contact" width="516" height="117" /></p>
<p>As shown in the above figure, there is a one-to-one relationship between the company and the contact model.</p>
<p>Here is the schema.yml:</p>
<pre class="brush: php;">propel:
  _attributes:
    package: lib.model
    defaultIdMethod: native
  company:
    _attributes: { phpName: Company }
    id: { type: INTEGER, size: '11', primaryKey: true, autoIncrement: true, required: true }
    name: { type: VARCHAR, size: '255', required: true }
    contact_id: { type: INTEGER, size: '11', required: false, foreignTable: contact, foreignReference: id, onDelete: SET NULL, onUpdate: RESTRICT }
    _indexes: { company_FI_1: [contact_id] }
  contact:
    _attributes: { phpName: Contact }
    id: { type: INTEGER, size: '11', primaryKey: true, autoIncrement: true, required: true }
    first_name: { type: VARCHAR, size: '255', required: true }
    last_name: { type: VARCHAR, size: '255', required: true }
    company_id: { type: INTEGER, size: '11', required: false, foreignTable: company, foreignReference: id, onDelete: SET NULL, onUpdate: RESTRICT }
    _indexes: { contact_FI_1: [company_id] }</pre>
<p>Note that both foriegn keys are not required, that is a must for us to be able to embed the Contact form in the Company form.</p>
<p>Now that we have the schema ready, let us build the sql schema, models, forms, filters, and create the tables.</p>
<pre class="brush: php;">$ php symfony propel:build-sql
$ php symfony propel:build-model
$ php symfony propel:build-forms
$ php symfony propel:build-filters
$ php symfony propel:insert-sql --env=dev</pre>
<p>Now let us generate a module using symfony&#8217;s admin generator and see how the generator will handle this relationship.</p>
<pre class="brush: php;">$ php symfony propel:generate-admin backend Company</pre>
<p style="text-align: center;">By browsing to the category module we just created above we can see the below figure:<br />
<img class="aligncenter size-full wp-image-184" title="company_1" src="http://sandbox-ws.com/wp-content/uploads/2008/12/company_1.jpg" alt="company_1" width="560" height="150" /></p>
<p style="text-align: center;">Now if we click on the &#8220;New&#8221; link we get the following screen:<br />
<img class="aligncenter size-full wp-image-186" title="company_2" src="http://sandbox-ws.com/wp-content/uploads/2008/12/company_2.jpg" alt="company_2" width="560" height="146" /></p>
<p>Notice that the &#8220;contact_id&#8221; foreign column was interpreted by the admin generator as a drop down list. Of course that is not what we had in mind, we want to be able to add a new &#8220;Company&#8221; along with it&#8217;s &#8220;Contact&#8221;. Thanks to symfony 1.2 ability to embed forms, this can be done very easily.</p>
<p>First open &#8220;CompanyForm.class.php&#8221; file and edit the configure method to match the following:</p>
<pre class="brush: php;">public function configure() {

	// get Contact model object
	$contact = $this-&amp;gt;getObject()-&amp;gt;getContact();

	// contact object is null
	if (is_null($contact)) {

		// create a new Contact object
		$contact = new Contact();

		// set the copmany of the newly created object to the current company
		$contact-&amp;gt;setCompany($this-&amp;gt;getObject());

		// set the contact of the current company
		$this-&amp;gt;getObject()-&amp;gt;setContact($contact);

	}

	// create a new contact form
	$contact_form = new ContactForm($contact);

	// embed the contact form in the current company form
	$this-&amp;gt;embedForm('contact', $contact_form);

	// remove the contact_id from the form
	unset($this['contact_id']);

}</pre>
<p>Next, open the ContactForm.class.php and edit as follows:</p>
<pre class="brush: php;">public function configure() {

	unset($this['company_id']);

}</pre>
<p>Now modify the <strong>Company.php</strong> model class to delete the contact while delete the company</p>
<pre class="brush: php;">public function delete(PropelPDO $con = null) {
	$this-&amp;gt;getContact()-&amp;gt;delete($con);
	parent::delete($con);
}</pre>
<p>And last but not least, edit the generator.yml to match the following(this step is optional):</p>
<pre class="brush: php;">generator:
  class: sfPropelGenerator
  param:
    model_class:           Company
    theme:                 admin
    non_verbose_templates: true
    with_show:             false
    singular:              ~
    plural:                ~
    route_prefix:          company
    with_propel_route:     1

    config:
      actions: ~
      fields:
          contact_id: { label: Company Contact }
      list:
          display: [=name, contact]
      filter:  ~
      form:    ~
      edit:    ~
      new:     ~</pre>
<p style="text-align: center;">Now go to the add new &#8220;Company&#8221; screen and you should see the following:<br />
<img class="aligncenter size-full wp-image-187" title="company_3" src="http://sandbox-ws.com/wp-content/uploads/2008/12/company_3.jpg" alt="company_3" width="560" height="198" /></p>
<p style="text-align: center;">Try adding, editing, and deleting some records now to make sure it&#8217;s working.<br />
<img class="aligncenter size-full wp-image-189" title="company_4" src="http://sandbox-ws.com/wp-content/uploads/2008/12/company_4.jpg" alt="company_4" width="560" height="183" /><br />
<img class="aligncenter size-full wp-image-190" title="company_5" src="http://sandbox-ws.com/wp-content/uploads/2008/12/company_5.jpg" alt="company_5" width="560" height="189" /></p>
]]></content:encoded>
			<wfw:commentRss>http://sandbox-ws.com/frameworks/symfony-frameworks/how-to-embed-forms-in-symfony-12-admin-generator/feed</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>Installing Symfony on Mac OS X 10.5.2</title>
		<link>http://sandbox-ws.com/frameworks/installing-symfony-on-mac</link>
		<comments>http://sandbox-ws.com/frameworks/installing-symfony-on-mac#comments</comments>
		<pubDate>Wed, 12 Nov 2008 19:53:24 +0000</pubDate>
		<dc:creator>Ahmed El.Hussaini</dc:creator>
				<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://sandbox-ws.com/sb_wordpress/?p=155</guid>
		<description><![CDATA[The purpose of this article is to simplify the installation process of symfony. Symfony installation can be a very tricky process and at some point might get very annoying that you might consider using another framework with an easy installation steps just like CakePHP. Symfony can be installed or used into two different ways: PEAR [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fsandbox-ws.com%2Fframeworks%2Finstalling-symfony-on-mac"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fsandbox-ws.com%2Fframeworks%2Finstalling-symfony-on-mac&amp;source=sandboxws&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p>The purpose of this article is to simplify the installation process of symfony. <a href="http://www.symfony-project.org/" target="_blank">Symfony</a> installation can be a very tricky process and at some point might get very annoying that you might consider using another framework with an easy installation steps just like CakePHP. Symfony can be installed or used into two different ways:</p>
<ul>
<li>PEAR installation(suitable for hosting that provides <a href="http://en.wikipedia.org/wiki/Secure_Shell" target="_blank">SSH</a> access)</li>
<li>Sandbox installation(suitable for shared hosting with no SSH access, note: the name Sandbox here is not related to Sandbox Web Solutions)</li>
</ul>
<p><span id="more-155"></span><br />
But before describing the steps of each installation type lets first understand the difference between the two and which type is most suitable for your hosting plan or account after all, you will eventually publish your projects online. <a href="http://en.wikipedia.org/wiki/PHP_Extension_and_Application_Repository" target="_blank">PEAR</a> or PHP Extension and Application Repository is simply an online <a href="http://en.wikipedia.org/wiki/Software_repository" target="_blank">repository</a> of PHP libraries, you can find Symfony and a lot more of PHP very good and time saving libraries on PEAR. But before using libraries from PEAR repository you need first to install PEAR and then download PEAR packages or libraries. The idea is simple you download Symfony as a PEAR package or library to your own PEAR installation(wither its local or online) and use the same library for multiple concurrent projects at the same time, this decreases your project overall size since you don&#8217;t include the actual Symfony libraries in the project which can increase uploading time as you&#8217;ll see in the Sandbox installation.</p>
<p>Sandbox installation on the other hand include the Symfony library in every project you use, so for example consider that you&#8217;re going to start 2 projects, and the Symfony library is simply a folder, then you&#8217;ll have to copy the Symfony folder to each project&#8217;s folder in order to use it. Some might think that Sandbox installation is a very bad idea, but i think that both installation are good enough if they are used wisely. So now that you have enough information to know the difference between the two installations <span class="note">(note: both installations will have almost all symfony features)</span> and you probably have decided by now which one is more suitable for you(if you&#8217;re unsure if your hosting supports SSH access, then start with the Sandbox installation) then lets start the installation steps.</p>
<h3>PEAR Installation</h3>
<h4>Mac OS X 10.5.2</h4>
<p>This is by far the simplest form of installing Symfony as a PEAR package so lets the fun begins.<br />
The process is divided into 3 steps:</p>
<ol>
<li>Installing PEAR</li>
<li>Enabling PHP module in Apache 2 HTTP Server which is pre installed along with PHP in your Mac</li>
<li>Installing Symfony 1.0.18</li>
</ol>
<h5>Installing PEAR</h5>
<p>Open the terminal and follow the following steps(thanks to <a href="http://clickontyler.com/blog/2008/01/how-to-install-pear-in-mac-os-x-leopard/" target="_blank">this</a> source)</p>
<pre class="brush: plain;">cd ~/
mkdir PEAR
cd PEAR</pre>
<pre class="brush: plain;">curl http://pear.php.net/go-pear &amp;gt; go-pear.php
sudo php -q go-pear.php</pre>
<p>Press enter to select all the default choices and go ahead to the next step</p>
<pre class="brush: plain;">sudo cp /etc/php.ini.default /etc/php.ini</pre>
<p>If you&#8217;re asked for your account&#8217;s password enter it then continue to the next step.</p>
<pre class="brush: plain;">mate /etc/php.ini</pre>
<p>Now search for the following &#8220;; UNIX: &#8220;/path1:/path2&#8243;, it should be around line 468. Below this line you should find something similar to the following:</p>
<pre class="brush: plain;">;include_path = &quot;.:/php/includes&quot;</pre>
<p>modify the line above to match the following <span class="note">(note keep any paths you&#8217;ve added)</span></p>
<pre class="brush: plain;">include_path = &quot;.:/php/includes:/Users/YOUR_HOME_FOLDER_NAME/PEAR/PEAR&quot;</pre>
<h5>Enabling PHP Module</h5>
<p>Open your terminal</p>
<pre class="brush: plain;">mate /etc/apache2/httpd.conf</pre>
<p>Search for &#8220;php5_module&#8221; and remove the &#8220;#&#8221; from the beginning of the line if it&#8217;s available. Now restart the apache web server using the following command <span class="note">(note: enter your account&#8217;s password when prompted)</span></p>
<pre class="brush: plain;">sudo apachectl restart</pre>
<h5>Installing Symfony</h5>
<p>Now comes the easy part, close any terminal window opened and then open a new terminal window and type the following <span class="note">(note: enter your account&#8217;s password when prompted)</span></p>
<pre class="brush: plain;">sudo pear channel.discover pear.symfony-project.com
sudo pear install symfony/symfony-1.0.18</pre>
<p>After PEAR finished installing symfony type the following to make sure everything is OK</p>
<pre class="brush: plain;">symfony --version</pre>
<p>You should now get the following output</p>
<pre class="brush: plain;">symfony version 1.0.18</pre>
<p>Pretty easy, you&#8217;ve now finished installing Symfony using PEAR on Mac OS X 10.5.2</p>
]]></content:encoded>
			<wfw:commentRss>http://sandbox-ws.com/frameworks/installing-symfony-on-mac/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
