<?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>{5} Setfive - Talking to the World &#187; php</title>
	<atom:link href="http://shout.setfive.com/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://shout.setfive.com</link>
	<description></description>
	<lastBuildDate>Wed, 18 Jan 2012 21:09:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>AJAX Request Slow With PHP?  Here&#8217;s Why</title>
		<link>http://shout.setfive.com/2012/01/18/ajax-request-slow-with-php-heres-why/</link>
		<comments>http://shout.setfive.com/2012/01/18/ajax-request-slow-with-php-heres-why/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 21:09:19 +0000</pubDate>
		<dc:creator>Matt Daum</dc:creator>
				<category><![CDATA[Free Advice]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sessions]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://shout.setfive.com/?p=1372</guid>
		<description><![CDATA[Recently I was working on a project where we had a page which loads tons of data from numerous sources. I decided after a while that we wanted to AJAX each section of data so that the page would load a bit quicker. After splitting up the requests and sending them asyncronously, there was little [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I was working on a project where we had a page which loads tons of data from numerous sources.  I decided after a while that we wanted to AJAX each section of data so that the page would load a bit quicker.  After splitting up the requests and sending them asyncronously, there was little improvement.  I thought at first it may be due to the fact we were pinging a single API for most of the data multiple times, that wasn&#8217;t it.  Maybe it was a browser limit? Nope was still far below the 6 requests most allow.  I setup xdebug and kcachegrind and to my surprise it was the session_start() that was taking the most time on the requests.  </p>
<p>I looked around the web for a while trying to figure out what in the world was going on.  It turns out that PHP&#8217;s default session_start will block future session_starts for the same session until the session is closed.  This is because the default method uses a file on the filesystem which it locks until you close it.  If you want more information on this and how to close it you can read a bit more <a href="http://konrness.com/php5/how-to-prevent-blocking-php-requests" target="_blank">here</a>.</p>
<p>We switched over to database based sessions and it fixed it.  In symfony 1.4 the default session storage uses the file system, however switching over to <a href="http://trac.symfony-project.org/browser/branches/1.4/lib/storage/sfPDOSessionStorage.class.php">sfPDOSessionStorage</a> is very easy and quick.  </p>
]]></content:encoded>
			<wfw:commentRss>http://shout.setfive.com/2012/01/18/ajax-request-slow-with-php-heres-why/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Facebook: How-to force users to LIKE page</title>
		<link>http://shout.setfive.com/2011/12/16/facebook-how-to-force-users-to-like-page-to-access-content/</link>
		<comments>http://shout.setfive.com/2011/12/16/facebook-how-to-force-users-to-like-page-to-access-content/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 20:39:41 +0000</pubDate>
		<dc:creator>Ashish Datta</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[mashup]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://shout.setfive.com/?p=1122</guid>
		<description><![CDATA[With Facebook&#8217;s move to deprecate FBML for tabs the documentation around how to make a &#8220;please Like! before&#8230;&#8221; has become much more choppy and inconsistent. Anyway, I recently found myself in a position where I needed to make this happen so here goes. With in-line FBML deprecated, the only way to accomplish this without using [...]]]></description>
			<content:encoded><![CDATA[<p>With Facebook&#8217;s move to deprecate <a href="https://developers.facebook.com/docs/reference/fbml/" target="_blank">FBML</a> for tabs the documentation around how to make a &#8220;please Like! before&#8230;&#8221; has become much more choppy and inconsistent. Anyway, I recently found myself in a position where I needed to make this happen so here goes. </p>
<p>With in-line FBML deprecated, the only way to accomplish this without using a third party branded solution is to create a Facebook iframe app. Here are the steps you need to take to get something up using PHP and the Facebook PHP SDK.</p>
<p><strong>1.</strong> Create a new Facebook Application at https://developers.facebook.com/apps</p>
<p><strong>2.</strong> Configure your new Facebook App the enable &#8220;Website&#8221; and &#8220;Page Tab&#8221;. You&#8217;ll need to enter a valid URL for the following fields:</p>
<ul>
<li>Site URL</li>
<li>Page Tab URL</li>
<li>Secure Page Tab URL</li>
</ul>
<p>You&#8217;ll also want to use a HTTPs URL since Facebook sessions default to HTTPs by default and your iframe will be marked insecure if its over vanilla HTTP. For this walk through, lets assume were using https://www.setfive.com/fb/index.php? as the URL.</p>
<p><strong>3.</strong> Now, you&#8217;ll want to add your new App to a Facebook Page. The easiest way to do this is to use this URL https://www.facebook.com/dialog/pagetab?app_id=YOUR_APP_ID&#038;next=YOUR_URL replacing YOUR_APP_ID and YOUR_URL with your App ID and then a URL that is derived from your endpoint (or even just your endpoint). When you load that URL, you&#8217;ll be prompted to add your app to a page &#8211; select the page you want and submit the form.</p>
<p><strong>4.</strong> The final piece is throwing together the actual PHP script. You&#8217;ll need the Facebook PHP SDK available on GitHub &#8211; https://github.com/facebook/php-sdk. Clone that and then this is the PHP script you&#8217;ll need:</p>
<pre name="code" class="php">

&lt;?php
require 'php-sdk/src/facebook.php';

$facebook = new Facebook(array(
  'appId'  =&gt; 'YOUR_APP_ID',
  'secret' =&gt; 'YOUR_APP_SECRET',
));

$req = $facebook-&gt;getSignedRequest();
?&gt;

&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;xmlns:fb=&quot;http://ogp.me/ns/fb#&quot;&gt;

&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot; /&gt;
    &lt;title&gt;&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;

&lt;?php if( $req[&quot;page&quot;][&quot;liked&quot;] ): ?&gt;

	Content for users that have LIKED the page.

&lt;?php else: ?&gt;

	Content for users that HAVE NOT LIKED the page.

&lt;?php endif; ?&gt;

&lt;/body&gt;

&lt;/html&gt;
</pre>
<p>And thats it! Now you&#8217;ll be able to gate content from non-fans while growing the fanbase of your Facebook Page.</p>
<p>Drop any questions in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://shout.setfive.com/2011/12/16/facebook-how-to-force-users-to-like-page-to-access-content/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Fixing blank CCK Location fields in Views</title>
		<link>http://shout.setfive.com/2011/09/25/fixing-blank-cck-location-fields-in-views/</link>
		<comments>http://shout.setfive.com/2011/09/25/fixing-blank-cck-location-fields-in-views/#comments</comments>
		<pubDate>Sun, 25 Sep 2011 21:42:25 +0000</pubDate>
		<dc:creator>Ashish Datta</dc:creator>
				<category><![CDATA[open source]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://shout.setfive.com/?p=992</guid>
		<description><![CDATA[Recently, we inherited a Drupal 6 site via a client of ours and ran into a pretty irritating bug with the Location module. The site had been configured to allow users to create profiles using Node Profile along with the Location to allow users to input their street addresses. Anyway, the issue was that when [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, we inherited a Drupal 6 site via a client of ours and ran into a pretty irritating bug with the Location module.</p>
<p>The site had been configured to allow users to create profiles using <a href="http://drupal.org/project/nodeprofile">Node Profile</a> along with the <a href="http://drupal.org/project/location">Location</a> to allow users to input their street addresses.</p>
<p>Anyway, the issue was that when we created a View that included Location fields the fields were always rendering as blank even when we confirmed there was data in the database. A bit of poking around lead to <a href="http://drupal.org/node/427432">this</a> issue.</p>
<p>It turns out that due to an optimization in CCK or Views that the tables that have the data for the location fields are not getting JOIN&#8217;ed in when the view is executed. Unfortunately, the patch provided on the issue doesn&#8217;t work on the latest 3.x release of the Location module.</p>
<p>The fix that worked for us is <a href="http://drupal.org/node/427432#comment-2251824">#14</a> (copied below)</p>
<pre name="code" class="php">
/**
* Preprocess hook for location().
*/
function yourtheme_preprocess_location(&#038;$variables) {
  if (!isset($variables['location']['name']) &#038;&#038; isset($variables['location']['lid'])) {
    $variables['location'] = array_merge($variables['location'], location_load_location($variables['location']['lid']));
    template_preprocess_location($variables);
  }
}
</pre>
<p>Basically, you&#8217;ll need to add the above snippet to a template.php file in your theme and change the name to reflect the theme you&#8217;re using. What this function does is basically pre-process the location fields to pull in the data so that the View will work properly.</p>
<p>Anyway, enough blogging it&#8217;s football time.</p>
]]></content:encoded>
			<wfw:commentRss>http://shout.setfive.com/2011/09/25/fixing-blank-cck-location-fields-in-views/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adding a task/command in Symfony2</title>
		<link>http://shout.setfive.com/2011/09/09/adding-a-taskcommand-in-symfony2/</link>
		<comments>http://shout.setfive.com/2011/09/09/adding-a-taskcommand-in-symfony2/#comments</comments>
		<pubDate>Fri, 09 Sep 2011 20:04:13 +0000</pubDate>
		<dc:creator>Ashish Datta</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[cli]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://shout.setfive.com/?p=822</guid>
		<description><![CDATA[I recently took the Symfony2 plunge and started working on a little fun side project (more on that later). Anyway, this particular project involves sending out daily text messages using the rather awesome Twilio API so I decided to use a Symfony2 task for this. The documentation on how to actually add your own task [...]]]></description>
			<content:encoded><![CDATA[<p>I recently took the Symfony2 plunge and started working on a little fun side project (more on that later).</p>
<p>Anyway, this particular project involves sending out daily text messages using the rather awesome Twilio API so I decided to use a Symfony2 task for this. The documentation on how to actually add your own task is a bit sparse so I figured I&#8217;d share.</p>
<p>The process is actually pretty straight forward:</p>
<ol>
<li>In your bundle create a directory named &#8220;Command&#8221; (without the quotes).</li>
<li>Create a file that extends ContainerAwareCommand</li>
<li>Create a protected function configure &#8211; &#8220;protected function configure()&#8221; to allow you to configure the name of your task and add any options or arguments you might need.</li>
<li>Create a protected function execute &#8211; &#8220;protected function execute(InputInterface $input, OutputInterface $output)&#8221; to actually do whatever needs to be done.</li>
<li>Thats it! Now you can run app/console and you&#8217;ll see your task.</li>
</ol>
<p>Here is the code for mine:</p>
<pre name="code" class="php">
namespace Setfive\SextDejourBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class SendTextsCommand extends ContainerAwareCommand
{

    protected function configure()
    {
        parent::configure();

        $this-&gt;setName('sj:sendTexts')
             -&gt;setDescription('Sends the day\'s sexts to everyone.');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {

         $ph = $this-&gt;getContainer()-&gt;get('doctrine')
                    -&gt;getRepository("SextDejourBundle:Phonenumber")
                    -&gt;createQueryBuilder("u")
                    -&gt;getQuery()
                    -&gt;getResult();

         $msg = $this-&gt;getContainer()-&gt;get('doctrine')
                    -&gt;getRepository("SextDejourBundle:Message")
                    -&gt;createQueryBuilder("u")
                    -&gt;where("u.is_used = false")
                    -&gt;setMaxResults(1)
                    -&gt;getQuery()
                    -&gt;getResult();
         $msg = array_pop( $msg );

         $msg-&gt;setIsUsed( true );
         // $this-&gt;getContainer()-&gt;get('doctrine')-&gt;getEntityManager()-&gt;flush();

         $accountId = $this-&gt;getContainer()-&gt;getParameter("twilio_app_id");
         $authToken = $this-&gt;getContainer()-&gt;getParameter("twilio_token");
         $myNumber = $this-&gt;getContainer()-&gt;getParameter("twilio_number");

         $client = new \Services_Twilio($accountId, $authToken);

         foreach( $ph as $p ){

           $sms = $p-&gt;getGender() == 0 ? $msg-&gt;getGuyText() : $msg-&gt;getGirlText();

           $res = $client-&gt;account-&gt;sms_messages-&gt;create ( $myNumber, $p-&gt;getPhoneNumber(), $sms );

           $output-&gt;writeln( $p-&gt;getPhoneNumber() . " =&gt; " . $sms );

         }

         return 0;
    }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://shout.setfive.com/2011/09/09/adding-a-taskcommand-in-symfony2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Congrats RentPrefs!</title>
		<link>http://shout.setfive.com/2011/07/29/congrats-rentprefs/</link>
		<comments>http://shout.setfive.com/2011/07/29/congrats-rentprefs/#comments</comments>
		<pubDate>Fri, 29 Jul 2011 15:27:03 +0000</pubDate>
		<dc:creator>Ashish Datta</dc:creator>
				<category><![CDATA[Launch]]></category>
		<category><![CDATA[dogpatch]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[xconomy]]></category>

		<guid isPermaLink="false">http://shout.setfive.com/?p=797</guid>
		<description><![CDATA[Last week we launched RentPrefs a new take on renting an apartment. RentPrefs flips the process around by allowing renters to post their preferences and then allowing agents to match them with listings that fit their criteria. Anyway, yesterday Xconomy did an awesome write up about them so definitely check it out. We also got [...]]]></description>
			<content:encoded><![CDATA[<p>Last week we launched <a href="https://www.rentprefs.com" target="_blank">RentPrefs</a> a new take on renting an apartment. RentPrefs flips the process around by allowing renters to post their preferences and then allowing agents to match them with listings that fit their criteria.</p>
<p>Anyway, yesterday <a href="http://www.xconomy.com/boston/2011/07/28/rentprefs-with-matchmaking-approach-to-apartment-rentals-rolls-out-beta-service/" target="_blank">Xconomy</a> did an awesome write up about them so definitely check it out. We also got a nice mention at the end there!</p>
<p>Happy Friday! </p>
]]></content:encoded>
			<wfw:commentRss>http://shout.setfive.com/2011/07/29/congrats-rentprefs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Drupal 7: Batch insert nodes with Drush</title>
		<link>http://shout.setfive.com/2011/02/09/drupal-7-batch-insert-nodes-with-drush/</link>
		<comments>http://shout.setfive.com/2011/02/09/drupal-7-batch-insert-nodes-with-drush/#comments</comments>
		<pubDate>Thu, 10 Feb 2011 04:05:49 +0000</pubDate>
		<dc:creator>Ashish Datta</dc:creator>
				<category><![CDATA[open source]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[php code]]></category>

		<guid isPermaLink="false">http://shout.setfive.com/?p=557</guid>
		<description><![CDATA[Well D7 has been out for a little while now and we finally got a chance to use it on a site this week. Anyway, this site is one of the heavier Drupal sites we&#8217;ve done and it involved loading ~200+ nodes of data just to set things up. This presented two problems, how to [...]]]></description>
			<content:encoded><![CDATA[<p>Well <a href="http://drupal.org/drupal-7.0" target="_blank">D7</a> has been out for a little while now and we finally got a chance to use it on a site this week.</p>
<p>Anyway, this site is one of the heavier Drupal sites we&#8217;ve done and it involved loading ~200+ nodes of data just to set things up. This presented two problems, how to batch load data and then how to load custom content types with several custom fields.</p>
<p>The Drupal module documentation has example code for adding a node with drupal_exeucte <a href="http://drupal.org/node/293663" target="_blank">here</a> but it doesn&#8217;t deal with how to set custom fields on your content type. On top of this, <a href="http://api.drupal.org/api/drupal/includes--form.inc/function/drupal_execute/6" target="_blank">drupal_execute</a> has been renamed to <a href="http://api.drupal.org/api/drupal/includes--form.inc/function/drupal_form_submit/7" target="_blank">drupal_form_submit</a> in Drupal 7 and the function signature has changed a bit.</p>
<p>Anyway, I dug around a bit and finally managed to get this working. You&#8217;ll obviously need <a href="http://drupal.org/project/drush" target="_blank">Drush</a> installed for the following code to work but you could rip it out and use it outside a Drush command. I was looking to basically replicate the &#8220;load-data&#8221; task from Symfony so that I could seed my Drupal database with Nodes at any point so I chose to make this a Drush command.</p>
<p>Here&#8217;s what you need:</p>
<p>- You&#8217;ll need a module to hold the Drush task. I used <a href="http://drupal.org/project/module_builder" target="_blank">Module Builder</a> to generate my scaffolding.<br />
- Create a file named [modulename].drush.inc in your module directory<br />
- Here is the code I&#8217;m using for [modulename].drush.inc Replace &#8220;cm&#8221; with the name of your module:</p>
<pre class="php" name="code">

/**
* Implementation of hook_drush_command().
*/

function cm_drush_command() {

        // callback is the function that will be called when the command is executed
	$items['load-rep-data'] = array(
	    'callback' => 'cm_load_rep_data',
            'description' => 'Loads the representative data.',
            'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL,
	);

	return $items;
}

function cm_load_rep_data( ){
   // you need this to autoload the functions to create nodes
   module_load_include('inc', 'node', 'node.pages');

  // do some business logic to load your data from where it is
  foreach( $arr as $res ){

    // define the custom node type
    $node = array('type' => 'representative');

   // set up the form array
   $form_state = array();

   // set the title of the node
   $form_state['values']['title'] = $res["title"];

   // set a custom field that is a text type
   $form_state['values']['field_first_name']['und']['0']['value'] = $res["first_name"];

   // set a long text field and enable full_html - NOTE you'll need to allow anonymous users to use this for Drush to work
   $form_state['values']['body']['und']['0']['format'] = 'full_html';
   $form_state['values']['body']['und']['0']['value'] = $res["bio"];

  // set some custom select fields
  $form_state['values']['field_house_committees']['und'][ 0 ] = 34;
  $form_state['values']['field_house_committees']['und'][ 0 ] = 37;

  // can't leave this out or the form wont save
  $form_state['values']['op'] = t('Save');

  // actually try and "submit" the form
  drupal_form_submit('representative_node_form', $form_state, (object)$node);

  // printing from Drush is easy
  drush_print( $res["title"] );
  }
}
</pre>
<p>Thats about it. </p>
<p>With <a href="http://getfirebug.com/" target="_blank">Firebug</a>, it&#8217;s really easy to see the field names and the values that you can set by just looking at a form to create whatever type of node you want.</p>
<p>drupal_form_submit can also be used to &#8220;submit&#8221; any other type of form in Drupal.</p>
<p>An open question is how to &#8220;fill out&#8221; an ImageField field via the command line since nothing is actually going to be uploaded.</p>
]]></content:encoded>
			<wfw:commentRss>http://shout.setfive.com/2011/02/09/drupal-7-batch-insert-nodes-with-drush/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>sfSCMIgnoresTaskPlugin for Symfony released, windows compatible!</title>
		<link>http://shout.setfive.com/2010/03/19/sfscmignorestaskplugin-for-symfony-released-windows-compatible/</link>
		<comments>http://shout.setfive.com/2010/03/19/sfscmignorestaskplugin-for-symfony-released-windows-compatible/#comments</comments>
		<pubDate>Fri, 19 Mar 2010 16:40:56 +0000</pubDate>
		<dc:creator>Matt Daum</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[symfony git]]></category>
		<category><![CDATA[symfony plugin]]></category>

		<guid isPermaLink="false">http://shout.setfive.com/?p=343</guid>
		<description><![CDATA[Recently I received an email from Davert.  He noted that the sfSCMIgnoresTaksPlugin would not work on Windows as Windows has a different directory separator.  He sent over a patch which uses PHP&#8217;s DIRECTORY_SEPARATOR instead of the coded &#8220;/&#8221;.  This makes the plugin compatible on Windows.  Thanks Davert.  You can read more about the plugin and [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I received an email from Davert.  He noted that the sfSCMIgnoresTaksPlugin would not work on Windows as Windows has a different directory separator.  He sent over a patch which uses PHP&#8217;s DIRECTORY_SEPARATOR instead of the coded &#8220;/&#8221;.  This makes the plugin compatible on Windows.  Thanks Davert.  You can read more about the plugin and download the most recent release at <a href="http://www.symfony-project.org/plugins/sfSCMIgnoresTaskPlugin">http://www.symfony-project.org/plugins/sfSCMIgnoresTaskPlugin</a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://shout.setfive.com/2010/03/19/sfscmignorestaskplugin-for-symfony-released-windows-compatible/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Retrieve session timeout in Symfony</title>
		<link>http://shout.setfive.com/2009/12/01/symfony-session-timeout/</link>
		<comments>http://shout.setfive.com/2009/12/01/symfony-session-timeout/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 19:10:28 +0000</pubDate>
		<dc:creator>Ashish Datta</dc:creator>
				<category><![CDATA[open source]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sfGuard]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://shout.setfive.com/?p=321</guid>
		<description><![CDATA[We were recently working on an application that required users to enter a significant amount of complex data that often meant that they had to look things up in between saves. Users kept running into the problem that their sfGuard sessions would timeout before they were able to click &#8220;Save&#8221; on the form which in [...]]]></description>
			<content:encoded><![CDATA[<p>We were recently working on an application that required users to enter a significant amount of complex data that often meant that they had to look things up in between saves. Users kept running into the problem that their sfGuard sessions would timeout before they were able to click &#8220;Save&#8221; on the form which in turn caused them to loose all of their hard work. Obviously, this is lame so we decided to add a popup warning users that their session had expired and prompting them to login again before saving their data.</p>
<p>We decided to implement this by using setTimeout in Javascript to pop up a window once the user&#8217;s session had expired.</p>
<p>Setting the session length for a Symfony user is easy enough, open up app/config/factories.yml and add the following:</p>
<pre class="html" name="code">
all:
  user:
    class: myUser
    param:
      timeout: 1800 # this is the default but you can change it at will (its in seconds)
</pre>
<p>As it turns out, the tricky part is how do you access this value inside the application? Un-characteristically, I couldn&#8217;t find anything in the Symfony documentation about how to access these variables. For whatever reason, sfConfig::get() doesn&#8217;t provide access to the variables in factories.yml.</p>
<p>In order to get that timeout value I used (inside a template):</p>
<pre class="php" name="code">
  $userOptions = $sf_user->getOptions();
  $timeout = $userOptions["timeout"];
</pre>
<p>Anyway, once I figured that out the rest is pretty straightforward.</p>
<p>After $timeout a Javascript function opens a jQuery UI Dialog box informing the user that their session has expired and presents the standard sfGuard sign in form. I override the onSubmit of this form to perform the request via AJAX in the background (so the user doesn&#8217;t loose their data) and then if the credentials are valid the dialog closes and the user can go on their way. If the credentials are invalid, the form re-populates with any errors and the user can correct them to re-login to the app.</p>
<p>Hope everyone had a good Thanksgiving! </p>
]]></content:encoded>
			<wfw:commentRss>http://shout.setfive.com/2009/12/01/symfony-session-timeout/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Adding ORDER BY FIELD to Propel Criterias</title>
		<link>http://shout.setfive.com/2009/10/13/adding-order-by-field-to-propel-criterias/</link>
		<comments>http://shout.setfive.com/2009/10/13/adding-order-by-field-to-propel-criterias/#comments</comments>
		<pubDate>Tue, 13 Oct 2009 23:22:49 +0000</pubDate>
		<dc:creator>Ashish Datta</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Propel]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://shout.setfive.com/?p=313</guid>
		<description><![CDATA[Every now and then, we use Sphinx to provide full text searching in MySQL InnoDB tables. Sphinx is pretty solid. It&#8217;s easy to set up, pretty fast, and easy to deploy. My one big issue with Sphinx has always been making it play nice with Symfony, specifically Propel. The way Sphinx returns a result set [...]]]></description>
			<content:encoded><![CDATA[<p>Every now and then, we use <a href="http://www.sphinxsearch.com/" target="_blank">Sphinx</a> to provide full text searching in MySQL InnoDB tables. Sphinx is pretty solid. It&#8217;s easy to set up, pretty fast, and easy to deploy. </p>
<p>My one big issue with Sphinx has always been making it play nice with Symfony, specifically Propel. The way Sphinx returns a result set is as an ordered list of [id, weight] for each document it matched. As outlined <a href="http://www.sphinxsearch.com/faq.html#row-storage" target="_blank">here</a> the idea is to then hit your MySQL server to return the actual documents and use &#8220;ORDER BY FIELD(id, [id list])&#8221; to keep them in the right order that you received the list.</p>
<p>The problem is, Propel Criteria objects provide no mechanism to set an ORDER BY FIELD. This is an issue because if you drop Criterias you loose Propel Pagers which generally adds to a lot of duplicated code and is honestly just not very elegant.</p>
<p>Anyway, after some thought I came up with this solution.</p>
<p>If you read through the definition of &#8220;Criteria::addDescendingOrderByColumn()&#8221;:</p>
<pre class="php" name="code">
	/**
	 * Add order by column name, explicitly specifying descending.
	 *
	 * @param      string $name The name of the column to order by.
	 * @return     Criteria Modified Criteria object (for fluent API)
	 */
	public function addDescendingOrderByColumn($name)
	{
		$this->orderByColumns[] = $name . ' ' . self::DESC;
		return $this;
	}
</pre>
<p>All it really does is add the second part of the ORDER BY clause to an array which then gets joined up to build the final SQL. Because of this, you can actually just add an element onto the orderByColumns array which will cause Propel to execute an ORDER BY FIELD SQL statement.</p>
<p>To make the magic happen, I sub-classed Criteria and then added a addOrderByField() function to let me add a field to order by as well as a list to order by.</p>
<pre class="php" name="code">

class sfCriteria extends Criteria {

  private $myOrderByColumns = array();

  /**
   * Add an ORDER BY FIELD clause.
   *
   * @param String $name The field to order by.
   * @param Array $elements A list to order the elements by.
   * @return unknown
   */
  public function addOrderByField($name, $elements)
  {
    $this->myOrderByColumns[] = ' FIELD(' . $name . ', ' . join(", ", $elements) . ')';
    return $this;
  }

  public function getOrderByColumns(){
    return array_merge( $this->myOrderByColumns, parent::getOrderByColumns() );
  }
}
</pre>
<p>To use it, do something like this:</p>
<pre class="php" name="code">
$ids = array(1, 3, 7);
$c = new sfCriteria();
$c->add( SomeModelPeer::ID, $ids, Criteria::IN);
$c->addOrderByField( SomeModelPeer::ID, $ids);
$results = SomeModelPeer::doSelect( $c );
</pre>
<p>And thats about it. Since sfCriteria is a sub-class of Criteria the code works seamlessly with existing PropelPagers and anything else that expects a Propel Criteria. </p>
]]></content:encoded>
			<wfw:commentRss>http://shout.setfive.com/2009/10/13/adding-order-by-field-to-propel-criterias/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Regex To Extract URLs From Plain Text</title>
		<link>http://shout.setfive.com/2009/10/07/regex-to-extract-urls-from-plain-text/</link>
		<comments>http://shout.setfive.com/2009/10/07/regex-to-extract-urls-from-plain-text/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 16:00:55 +0000</pubDate>
		<dc:creator>Matt Daum</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[regex]]></category>
		<category><![CDATA[url extraction]]></category>

		<guid isPermaLink="false">http://shout.setfive.com/?p=296</guid>
		<description><![CDATA[Recently for a project we had the problem that it pulled data from numerous API&#8217;s and sometimes the data would contain urls that were not HTML links (ie. they were just http://www.mysite.com instead of &#60;a href=&#8221;http://www.mysite.com&#8221;&#62;http://mysite.com&#60;/a&#62; .  I searched around the web for a while and had no luck finding a regex that would extract [...]]]></description>
			<content:encoded><![CDATA[<p>Recently for a project we had the problem that it pulled data from numerous API&#8217;s and sometimes the data would contain urls that were not HTML links (ie. they were just http://www.mysite.com instead of &lt;a href=&#8221;http://www.mysite.com&#8221;&gt;http://mysite.com&lt;/a&gt; .  I searched around the web for a while and had no luck finding a regex that would extract only urls that are not currently wrapped already inside of a html tag.  I came up with the following regex:</p>
<pre class="php" name="code">/(?&lt;![\&gt;https?:\/\/|href=\"'])(?&lt;http&gt;(https?:[\/][\/]|www\.)([a-z]|[A-Z]|[0-9]|[\/.]|[~])*)/</pre>
<p>Parts of it are taken from other examples of URL extractors.  However none of the examples I found had lookarounds to make sure it isn&#8217;t already linked.  I am not a master of regex, so there may be a better expression than I wrote.  The above expression is written to be compatible with PHP&#8217;s preg_replace method.  A more generic one is as follows:</p>
<pre class="php" name="code">(?&lt;![\&gt;https?://|href="'])(?&lt;http&gt;(https?:[/][/]|www.)([a-z]|[A-Z]|[0-9]|[/.]|[~])*)</pre>
<p>This expression will match http://www.mysite.com and www.mysite.com and any subdomains of a website.  The first matched group is the URL.  One thing to note is if you are using this that you need to check if the URL that is matched has an http:// on the front of it, if it does not, append one otherwise the link will be relative and cause something like http://www.mysite.com/www.mysite.com . </p>
<p>One tool that was very helpful in making this was <a href="http://gskinner.com/RegExr">http://gskinner.com/RegExr</a> it is incredibly helpful.  It gives you a visual representation in real time as you create your expression of what it will match.</p>
<p><strong>Note: </strong> You will lose the battle in trying to extract URL&#8217;s using regex.  For example the above expression will fail on a style=&#8221;background:url(http://mysite.com/image.jpg)&#8221;.  For a more robust solution it may be worth while looking into parsing the DOM and running regex per element then.</p>
]]></content:encoded>
			<wfw:commentRss>http://shout.setfive.com/2009/10/07/regex-to-extract-urls-from-plain-text/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

