<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Symfony Guru at opensky.com.
Discussing web development, Symfony and fatherhood.</description><title>Kris Wallsmith</title><generator>Tumblr (3.0; @kriswallsmith)</generator><link>http://kriswallsmith.net/</link><item><title>Keep a trim autoloader</title><description>&lt;p&gt;The symfony 1.4 autoloader works by scanning your PHP class files and
remembering where each class and interface is defined, so it can magically
load it when needed. This class-to-filename mapping is stored as an array in
your application&amp;#8217;s cache directory.&lt;/p&gt;

&lt;p&gt;You can (and should) look at this array by opening this cache file in your
text editor from time to time:
&lt;code&gt;cache/%SF_APP%/%SF_ENVIRONMENT%/config/config_autoload.yml.php&lt;/code&gt;. Inside
you&amp;#8217;ll see a big array with &lt;code&gt;// comment&lt;/code&gt; headers.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php
// auto-generated by sfAutoloadConfigHandler
// date: 2010/10/24 05:29:41
return array(

  // sfDoctrineGuardPlugin_lib
  'pluginsfguardgroupformfilter' =&amp;gt; '/path/to/plugins/sfDoctrineGuardPlugin/lib/filter/doctrine/PluginsfGuardGroupFormFilter.class.php',
  'pluginsfguardpermissionformfilter' =&amp;gt; '/path/to/plugins/sfDoctrineGuardPlugin/lib/filter/doctrine/PluginsfGuardPermissionFormFilter.class.php',
  'pluginsfguarduserformfilter' =&amp;gt; '/path/to/plugins/sfDoctrineGuardPlugin/lib/filter/doctrine/PluginsfGuardUserFormFilter.class.php',

  // ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A few things to look for in this file:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;You should &lt;strong&gt;not&lt;/strong&gt; see any reference to libraries that have their own
autoloader. This includes the symfony core classes, Swiftmailer, Zend
Framework, etc. If you see references to classes from one of these
libraries, your autoloader is not configured correctly.&lt;/li&gt;
&lt;li&gt;You should &lt;strong&gt;not&lt;/strong&gt; see any non-runtime classes.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;You&amp;#8217;ll probably need to add some configuration to accomplish that second
point. For example, your tasks and Doctrine migration classes will never be
involved in a runtime request, so they should not be included in the
autoloader&amp;#8217;s cache.&lt;/p&gt;

&lt;h2&gt;Configure the autoloader&lt;/h2&gt;

&lt;p&gt;Fortunately, excluding these files is easy enough using &lt;code&gt;autoload.yml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add this file to your project…&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/autoload.yml
autoload:
  # extend the "project" configuration block defined in the symfony core
  project:
    exclude: [vendor, symfony, model, migration, task]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Clear your cache…&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ php symfony cache:clear
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Visit your site in the browser to prime the cache, and re-inspect the cached
&lt;code&gt;config_autoload.yml.php&lt;/code&gt; file. Your task and Doctrine migration classes
should no longer be represented there.&lt;/p&gt;

&lt;h2&gt;Add this to your installer&lt;/h2&gt;

&lt;p&gt;The new installer mechanism in symfony 1.4 is the perfect place to add this
sort of thing since you&amp;#8217;re going to want to do it on every project. For an
example of how this is done, check out commit &lt;a href="http://github.com/kriswallsmith/symfony-installer/commit/dede92eefc5e54d6c913e354486c045e3b6b03cc" target="_blank"&gt;dede92e&lt;/a&gt; on my GitHub
&lt;a href="http://github.com/kriswallsmith/symfony-installer" target="_blank"&gt;symfony-installer&lt;/a&gt; project.&lt;/p&gt;

&lt;h2&gt;Read more&lt;/h2&gt;

&lt;p&gt;If you want to learn more about configuring the symfony 1.4 autoloader, please
read through &lt;a href="http://www.symfony-project.org/reference/1_4/en/" target="_blank"&gt;The symfony Reference Guide&lt;/a&gt;, specifically the section on
&lt;a href="http://www.symfony-project.org/reference/1_4/en/14-Other-Configuration-Files#chapter_14_autoload_yml" target="_blank"&gt;autoload.yml&lt;/a&gt;.&lt;/p&gt;</description><link>http://kriswallsmith.net/post/1389089654</link><guid>http://kriswallsmith.net/post/1389089654</guid><pubDate>Sun, 24 Oct 2010 05:46:00 -0700</pubDate><category>symfony</category></item><item><title>Doctrine and MySQL integers</title><description>&lt;p&gt;I just pasted this somewhere handy for my own reference. It&amp;#8217;s the logic Doctrine uses to translate the integer data types you specify in &lt;code&gt;schema.yml&lt;/code&gt; into a MySQL data type. If you&amp;#8217;ve ever wondered why the length you set on an integer isn&amp;#8217;t directly translated to the table definition used in your database, here&amp;#8217;s why.&lt;/p&gt;

&lt;script src="http://gist.github.com/152120.js"&gt;&lt;/script&gt;&lt;p&gt;For example, the &lt;code&gt;id&lt;/code&gt; columns in &lt;code&gt;sfDoctrineGuardPlugin&lt;/code&gt; are defined as &lt;code&gt;integer(4)&lt;/code&gt;, which translates to &lt;code&gt;id INT&lt;/code&gt; in the table definition. Where did the 4 go? Now you know&amp;#8230;&lt;/p&gt;</description><link>http://kriswallsmith.net/post/146880991</link><guid>http://kriswallsmith.net/post/146880991</guid><pubDate>Wed, 22 Jul 2009 09:37:22 -0700</pubDate><category>doctrine</category><category>symfony</category></item><item><title>Symfony: Denote Required Form Fields</title><description>&lt;blockquote&gt;
  &lt;p&gt;You can checkout the full gist for this tutorial
  &lt;a href="http://gist.github.com/149461" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The symfony form framework separates a form&amp;#8217;s presentation and validation into
two distinct collections of classes: widgets and validators. For the most
part, these two codebases live happily without any knowledge of eachother.
When data from the validators needs to be shown in the presentation layer,
such as in the case of error messages, symfony provides the &lt;code&gt;sfFormField&lt;/code&gt;
class, which bridges this divide.&lt;/p&gt;

&lt;p&gt;One common requirement for web forms is that required fields must be apparent
to the user. Implementing this in the symfony form framework may not seem
possible, because of the divide between widgets and validators, but it is in
fact quite possible, and easily implemented.&lt;/p&gt;

&lt;p&gt;This is a quick tutorial on how to do just that.&lt;/p&gt;

&lt;h3&gt;Validator, meet Widget&lt;/h3&gt;

&lt;p&gt;The first step is for the form&amp;#8217;s validators to inform the form&amp;#8217;s widgets which
of its fields are required. We can do this by passing a array of field names
to the widget schema once the form is fully configured:&lt;/p&gt;

&lt;script src="http://gist.github.com/149462.js"&gt;&lt;/script&gt;&lt;p&gt;The &lt;code&gt;getRequiredFields()&lt;/code&gt; method returns a simple array of formatted field
names that corresponds to those validators marked as required. It accomplishes
this by recurrisively iterating through the form&amp;#8217;s validators:&lt;/p&gt;

&lt;script src="http://gist.github.com/149463.js"&gt;&lt;/script&gt;&lt;h3&gt;Label Formats&lt;/h3&gt;

&lt;p&gt;Once the form&amp;#8217;s widgets know which fields are required, it&amp;#8217;s up to the form
formatter to decorate those fields accordingly. I&amp;#8217;ve done this using an
extension of the standard table formatter class:&lt;/p&gt;

&lt;script src="http://gist.github.com/149464.js"&gt;&lt;/script&gt;&lt;p&gt;Finally, we just add this custom formatter to our forms by adding the
following to the overloaded &lt;code&gt;__construct()&lt;/code&gt; method from above:&lt;/p&gt;

&lt;script src="http://gist.github.com/149465.js"&gt;&lt;/script&gt;&lt;p&gt;Your forms&amp;#8217; required fields should now render with labels that include the
&lt;code&gt;required&lt;/code&gt; class. Of course, you can do something different in the formatter
to suit your needs, add a &lt;code&gt;*&lt;/code&gt; or add a class to the entire row, but hopefully
the implementation should now be clear.&lt;/p&gt;</description><link>http://kriswallsmith.net/post/144021872</link><guid>http://kriswallsmith.net/post/144021872</guid><pubDate>Sat, 18 Jul 2009 00:45:46 -0700</pubDate><category>symfony</category><category>forms</category></item><item><title>Managing Master and Slave Database Connections with symfony and Doctrine</title><description>&lt;p&gt;This is one of those things that should be much easier than it is. Since I
started using Doctrine a few months ago, I&amp;#8217;ve been impressed with how complete
it is, but I can definitely see room for improvement as the project matures.
Setting up read and write connections is one of those areas.&lt;/p&gt;

&lt;p&gt;My challenge was to get the project I&amp;#8217;m on ready to be hosted on Amazon EC2,
with the help of &lt;a href="http://rightscale.com" target="_blank"&gt;RightScale&lt;/a&gt;. If your hosting on the
cloud and have the funds available, check out RightScale. They have a number
of server templates with best practices already implemented, and great online
tutorials.&lt;/p&gt;

&lt;p&gt;The environment I&amp;#8217;m setting up includes one master and (potentially) multiple
slave MySQL servers (setup with &lt;a href="http://support.rightscale.com/03-Tutorials/02-AWS/02-Website_Edition/2.1_MySQL_Setup/Create_a_MySQL-EBS_Database_Setup" target="_blank"&gt;EBS
storage&lt;/a&gt;).
Setting up these servers was a piece of cake, thanks to the heavy lifting
RightScale had done for me with their server templates and tutorials. The
challenge I met was in getting symfony (1.2) and Doctrine (1.1) setup to
choose the right connection for each query.&lt;/p&gt;

&lt;h3&gt;Code Slingin&amp;#8217; Below&lt;/h3&gt;

&lt;p&gt;The first order of business is organizing the database connections. I decided
to go with a simple naming syntax and assume the master connection is named
&lt;code&gt;master&lt;/code&gt; and the slave connection names begin with &lt;code&gt;slave&lt;/code&gt;. I added these
methods to &lt;code&gt;ProjectConfiguration&lt;/code&gt; so these connections are accessible:&lt;/p&gt;

&lt;script src="http://gist.github.com/181262.js"&gt;&lt;/script&gt;&lt;p&gt;Now I can easily grab the master connection by calling
&lt;code&gt;ProjectConfiguration::getActive()-&amp;gt;getMasterConnection()&lt;/code&gt; from anywhere in
my project, and get a slave connection by calling &lt;code&gt;-&amp;gt;getSlaveConnection()&lt;/code&gt;.
This is cool, but it turned out to be the easiest part, by far.&lt;/p&gt;

&lt;h3&gt;Smartly Forcing a Master or Slave Connection&lt;/h3&gt;

&lt;p&gt;I started with a tutorial on &lt;a href="http://trac.doctrine-project.org/browser/docs/branches/1.1/cookbook/en/master-and-slave-connections.txt" target="_blank"&gt;master and slave
connections&lt;/a&gt;
in the Doctrine documentation repository. This was easy to implement, but it&amp;#8217;s
not a complete solution. There are write queries in the Doctrine core that
don&amp;#8217;t go though either &lt;code&gt;Doctrine_Query::preQuery()&lt;/code&gt; or
&lt;code&gt;Doctrine_Record::save()&lt;/code&gt;, so they end up using the current connection, which
is usually the slave connection.&lt;/p&gt;

&lt;p&gt;I came up with a solution, but I&amp;#8217;m witholding judgement on how stable it is.
I&amp;#8217;m using Doctrine events to filter all queries run through Doctrine and swap
out the PDO object used inside the &lt;code&gt;Doctrine_Connection&lt;/code&gt; object with either
the master or slave PDO object:&lt;/p&gt;

&lt;script src="http://gist.github.com/181270.js"&gt;&lt;/script&gt;&lt;p&gt;Then simply add this listener to each of you &lt;code&gt;Doctrine_Connection&lt;/code&gt; objects by
using the (undocumented?) &lt;code&gt;ProjectConfiguration::configureDoctrineConnection()&lt;/code&gt;
method:&lt;/p&gt;

&lt;script src="http://gist.github.com/181271.js"&gt;&lt;/script&gt;&lt;p&gt;This seems to be working for my purposes, but I feel a bit dirty hacking into
&lt;code&gt;Doctrine_Connection&lt;/code&gt; objects like this. For a brief moment as each query is
run, the &lt;code&gt;Doctrine_Connection&lt;/code&gt; object that includes the name &lt;code&gt;master&lt;/code&gt; may in
fact include a &lt;code&gt;slave&lt;/code&gt; PDO object, and vice versa.&lt;/p&gt;

&lt;h3&gt;One More Thing&lt;/h3&gt;

&lt;p&gt;This new environment includes multiple database servers, so it naturally
includes multiple load-balanced web servers, which precludes the use of
&lt;code&gt;sfSessionStorage&lt;/code&gt; because of it&amp;#8217;s reliance on a local filesystem. I decided
to go with &lt;code&gt;sfPDOSessionStorage&lt;/code&gt; for the time being.&lt;/p&gt;

&lt;p&gt;I was expecting to have to extend &lt;code&gt;sfPDOSessionStorage&lt;/code&gt; to choose between
master and slave connections for each storage operation. However, upon looking
at the code I realized that every operation may possibly include a write
query, so I just specified the master connection in &lt;code&gt;factories.yml&lt;/code&gt;:&lt;/p&gt;

&lt;script src="http://gist.github.com/181272.js"&gt;&lt;/script&gt;&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;
  This configuration assumes there is always a connection named &lt;code&gt;master&lt;/code&gt;,
  whereas the method in &lt;code&gt;ProjectConfiguration&lt;/code&gt; includes a fallback to the
  current Doctrine connection.&lt;/p&gt;
&lt;/blockquote&gt;</description><link>http://kriswallsmith.net/post/139070229</link><guid>http://kriswallsmith.net/post/139070229</guid><pubDate>Fri, 10 Jul 2009 07:53:00 -0700</pubDate><category>symfony</category><category>doctrine</category><category>amazonaws</category><category>rightscale</category></item><item><title>Doctrine Timestamps and User Timezones</title><description>&lt;p&gt;I recently added a &amp;#8220;timezone&amp;#8221; dropdown to the user preferences screen on a symfony application currently in development. This simple extension to the &lt;code&gt;sfDoctrineRecord&lt;/code&gt; class makes it easy to present times from the database in the current user&amp;#8217;s timezone.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;abstract class myRecord extends sfDoctrineRecord
{
  protected function _get($fieldName, $load = true)
  {
    if ($value = parent::_get($fieldName, $load))
    {
      $column = $this-&amp;gt;getTable()-&amp;gt;getColumnDefinition($fieldName);
      if ($column &amp;amp;&amp;amp; 'timestamp' == $column['type'])
      {
        $timezone = date_default_timezone_get();
        if (ProjectConfiguration::DEFAULT_TIMEZONE != $timezone)
        {
          // shift value to the current timezone
          date_default_timezone_set(ProjectConfiguration::DEFAULT_TIMEZONE);
          $time = strtotime($value);

          date_default_timezone_set($timezone);
          $value = date('Y-m-d H:i:s', $time);
        }
      }
    }

    return $value;
  }

  protected function _set($fieldName, $value, $load = true)
  {
    $column = $this-&amp;gt;getTable()-&amp;gt;getColumnDefinition($fieldName);
    if ($column &amp;amp;&amp;amp; 'timestamp' == $column['type'] &amp;amp;&amp;amp; $time = strtotime($value))
    {
      $timezone = date_default_timezone_get();
      if (ProjectConfiguration::DEFAULT_TIMEZONE != $timezone)
      {
        // shift value to the default timezone
        date_default_timezone_set(ProjectConfiguration::DEFAULT_TIMEZONE);
        $value = date('Y-m-d H:i:s', $time);

        date_default_timezone_set($timezone);
      }
    }

    return parent::_set($fieldName, $value, $load);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To get &lt;code&gt;sfDoctrinePlugin&lt;/code&gt; to use this class instead of the default, &lt;code&gt;sfDoctrineRecord&lt;/code&gt;, add the following to your &lt;code&gt;ProjectConfiguration&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// config/ProjectConfiguration.class.php
class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
    // ...

    sfConfig::set('doctrine_model_builder_options', array(
      'baseClassName' =&amp;gt; 'myRecord',
    ));
  }

  // ...
}
&lt;/code&gt;&lt;/pre&gt;</description><link>http://kriswallsmith.net/post/136226720</link><guid>http://kriswallsmith.net/post/136226720</guid><pubDate>Sun, 05 Jul 2009 22:14:00 -0700</pubDate><category>doctrine</category><category>symfony</category></item><item><title>Two ZendCon proposals</title><description>&lt;p&gt;I submitted two 400-character proposals to &lt;a href="http://zendcon.com/" target="_blank"&gt;ZendCon&lt;/a&gt; yesterday.&lt;/p&gt;

&lt;h3&gt;Someone else&amp;#8217;s symfony&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Taking on development of a symfony application started by another
  developer can be a daunting task, especially for those not familiar
  with the framework. This will be a practical exploration of
  symfony from the perspective of a developer taking on an existing
  project. Topics will include getting started, automated testing, the
  anatomy of a symfony request, refactoring and symfony best practices.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think this is a really juicy topic I&amp;#8217;ve never seen covered. The current symfony documentation is geared toward either someone &lt;strong&gt;new&lt;/strong&gt; to symfony starting a &lt;strong&gt;new&lt;/strong&gt; project or someone &lt;strong&gt;experienced&lt;/strong&gt; with symfony working on an &lt;strong&gt;existing&lt;/strong&gt; project. I think the population of devs new to symfony on an existing project could use some luv. This also seems like a new and refreshing way to introduce symfony.&lt;/p&gt;

&lt;h3&gt;The Community Stack&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;A vital ingredient to any open source project is a vibrant
  community. Drawing from his experience as Community Manager for the
  symfony framework, Kris will examine the makeup of a successful
  &amp;#8220;community stack&amp;#8221; and propose three basic layers: devs/users, the
  larger OSS community, and the society as a whole. How these layers
  interact and grow will be the focus of this session.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The idea here is to acknowledge the importance of community in an open source project with the same significance you would any other solution stack you depend on. I&amp;#8217;ve been working on some meat for each of those three layers, but haven&amp;#8217;t had a chance to give this talk yet. Here&amp;#8217;s hoping that will change!&lt;/p&gt;</description><link>http://kriswallsmith.net/post/116380868</link><guid>http://kriswallsmith.net/post/116380868</guid><pubDate>Mon, 01 Jun 2009 12:40:00 -0700</pubDate><category>symfony</category><category>zendcon</category></item></channel></rss>

