<?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>-= n8v =- &#187; symfony</title>
	<atom:link href="http://n8v.enteuxis.org/tags/symfony/feed/" rel="self" type="application/rss+xml" />
	<link>http://n8v.enteuxis.org</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Wed, 17 Feb 2010 05:59:32 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=3.0-alpha</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Symfony log management with `logrotate` on Linux</title>
		<link>http://n8v.enteuxis.org/2009/10/symfony-log-management-with-logrotate-on-linux/</link>
		<comments>http://n8v.enteuxis.org/2009/10/symfony-log-management-with-logrotate-on-linux/#comments</comments>
		<pubDate>Fri, 16 Oct 2009 20:44:34 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[logs]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=282</guid>
		<description><![CDATA[It sucks when server disks fill up.  I have Nagios set up to notify me well before it&#8217;s a problem, but it happens annoyingly frequently, and it&#8217;s always the same cause:  log files.

Symfony&#8217;s production environments don&#8217;t create logs, but the development environments do, and for one project I had several batch jobs logging [...]]]></description>
			<content:encoded><![CDATA[<p>It sucks when server disks fill up.  I have <a href="http://www.nagios.org/">Nagios</a> set up to notify me well before it&#8217;s a problem, but it happens annoyingly frequently, and it&#8217;s always the same cause:  log files.</p>

<p>Symfony&#8217;s production environments don&#8217;t create logs, but the development environments do, and for one project I had several batch jobs logging to the <var>myproject/log</var> directory.  (Troubleshooting batch jobs without logs is just crazy).</p>

<p>I was going to use <a href="http://www.symfony-project.org/book/1_2/16-Application-Management-Tools#chapter_16_sub_symfony_logs"><code>symfony log:rotate</code></a>, but</p>

<ul>
<li>I would need one cron job for each log</li>
<li>I had permission issues since some of the logs belong to <var>apache</var> and others to <var>root</var></li>
<li>Everything else on the machine, pretty much, is managed with the standard Linux utility <a href="http://linux.die.net/man/8/logrotate"><var>logrotate</var></a>.  Logrotate has been around for about 174 Linux Years, and is common to most distributions.</li>
</ul>

<p>So here&#8217;s how I did it using with <var>logrotate</var>.</p>

<p><span id="more-282"></span></p>

<ol>

    <li><strong>WARNING</strong>:  You might want to make a convenient copy of your log directory before you do this.  I accidently wiped all the logs out while messing with it.
</li>

    <li>Create a file <var>config/myproject.logrotate</var>.  Very simple, I just want it to use the same rotation schedule specified for the whole machine in <var>/etc/logrotate.conf</var>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="sy0">/</span>path<span class="sy0">/</span>to<span class="sy0">/</span>myproject<span class="sy0">/</span>log<span class="sy0">/*</span>.log <span class="br0">&#123;</span>
        weekly
        rotate <span class="nu0">4</span>
<span class="br0">&#125;</span></pre></div></div>



</li>

    <li>Check that it will do stuff by running it with the debug flag


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">logrotate <span class="re5">-df</span> config<span class="sy0">/</span>badge.logrotate</pre></div></div>


</li>


    <li>Make a symlink to it in <var>/etc/logrotate.d</var>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">ln</span> <span class="re5">-s</span> <span class="sy0">/</span>path<span class="sy0">/</span>to<span class="sy0">/</span>myproject<span class="sy0">/</span>config<span class="sy0">/</span>myproject.logrotate  <span class="sy0">/</span>etc<span class="sy0">/</span>logrotate.d<span class="sy0">/</span>myproject</pre></div></div>



</li>

    <li>Run it the first time manually to rotate your logs and make sure it does the right thing!


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">sudo</span> logrotate <span class="re5">-fv</span> <span class="sy0">/</span>etc<span class="sy0">/</span>logrotate.d<span class="sy0">/</span>myproject</pre></div></div>



</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2009/10/symfony-log-management-with-logrotate-on-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Making a symfony plug-in for visual theme and custom errors</title>
		<link>http://n8v.enteuxis.org/2009/06/making-a-symfony-plug-in-for-visual-theme-and-custom-errors/</link>
		<comments>http://n8v.enteuxis.org/2009/06/making-a-symfony-plug-in-for-visual-theme-and-custom-errors/#comments</comments>
		<pubDate>Fri, 26 Jun 2009 00:13:38 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[style]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[theme]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=255</guid>
		<description><![CDATA[I manage a growing number of symfony-based Intranet apps that share a common look-and-feel.  I use the same stylesheet and images on them all, and it I am nervous every time I make Yet Another Copy of the same files, knowing that I&#8217;m duplicating them and causing trouble for myself.

Also, as I wrote in [...]]]></description>
			<content:encoded><![CDATA[<p>I manage a growing number of symfony-based Intranet apps that share a common look-and-feel.  I use the same stylesheet and images on them all, and it I am nervous every time I make Yet Another Copy of the same files, knowing that I&#8217;m duplicating them and causing trouble for myself.</p>

<p>Also, as I wrote in <a href="/2009/03/completely-custom-symfony-error-pages/">my post about custom error pages</a>, I have error pages set up for each, and I hate copying them.  So I have invested some time into building a plugin containing the visual assets and the customized error pages, so that it&#8217;s easier to keep them uniform across all the apps I work on, and so that it will be that much quicker to build new projects.</p>

<p>I don&#8217;t think anyone outside my company will want my plug-in, but these instructions will hopefully be useful for anyone who wants to do the same thing.</p>

<p><span id="more-255"></span></p>

<p>These instructions are for symfony 1.1 but they should apply equally to 1.0 and 1.2.</p>

<h2>Plugin organization</h2>

<p>Here are the files and directories in my plugin:</p>

<p><pre>plugins/myThemePlugin/
  config/
    view.yml
  modules/
    default/
      config/
        view.yml
      templates/
        disabledSuccess.php
        error404Success.php
  README
  web/
    css/
      mystyles.css
      myerrors.css
      mymain.css
    errors/
      error500.php
      unavailable.php
    images/
      my_swoop.jpg
      bg_sfTAlert.jpg
      bg_sfTLock.jpg
      bg_sfTMessage.jpg
      indicator.gif
      tall_gradient.jpg
</pre></p>

<h2>Using <code>svn:externals</code> to install the plugin in each symfony project</h2>

<p>I only want one copy of this thing, with version control, so I use svn:externals (for my other plugins too ).</p>

<p><pre>$ svn propget svn:externals plugins
myThemePlugin/        https://mysvnserver.com/svn/web/myThemePlugin
sfGuardPlugin/        http://svn.symfony-project.com/plugins/sfGuardPlugin/branches/1.1/
$ svn up
</pre></p>

<h2>Publishing the assets</h2>

<p>The <a href="http://www.symfony-project.org/book/1_2/17-Extending-Symfony#chapter_17_sub_anatomy_of_a_plug_in">chapter on plugins</a> in the <cite>The Definitive Guide to symfony</cite> explains:</p>

<blockquote>
  <p>Web assets (images, scripts, style sheets, etc.) are made available to the server. When you install a plug-in via the command line, symfony creates a symlink to the project <code>web/</code> directory if the system allows it, or copies the content of the module <code>web/</code> directory into the project one. If the plug-in is installed from an archive or a version control repository, you have to copy the plug-in <code>web/</code> directory by hand (as the <code>README</code> bundled with the plug-in should mention).</p>
</blockquote>

<p>As I showed above, I prefer to use <code>svn:externals</code> for my plugins, so this is a bit of a problem for me.  Also, I develop on Windows (with XAMPP and Cygwin), so the more elegant symlink solution is not an option.   Symfony 1.2 has a task called <code>plugin:publish_assets</code> that makes the copies, but that messes up my version control strategy. SO:  I am going to use <code>svn:externals</code> to get the web assets from my plugin too.</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw2">svn</span> propset <span class="kw2">svn</span>:externals <span class="st0">&quot;myThemePlugin  https://my_svn_server/svn/web/myThemePlugin/web/&quot;</span> web
$ <span class="kw2">svn</span> propget <span class="kw2">svn</span>:externals web
    myThemePlugin  https:<span class="sy0">//</span>my_svn_server<span class="sy0">/</span><span class="kw2">svn</span><span class="sy0">/</span>web<span class="sy0">/</span>myThemePlugin<span class="sy0">/</span>web<span class="sy0">/</span>
$ <span class="kw2">svn</span> up</pre></div></div>


<p>This lets me keep the plugin in its own repository.  You could get a similar effect by just checking out the files, but it would clutter up the SVN for your main project.</p>

<p>The end result:  I have one copy of the web assets in the SVN repository, but they&#8217;re checked out twice into each project (once under <var>plugins/myThemePlugin/web</var> and once under <var>web/myThemePlugin</var>).</p>

<h2><var>view.yml</var> files</h2>

<p>Now the overall <var>view.yml</var> file in <var>plugins/myThemePlugin/config/</var> sets stylesheets for my whole project:</p>


<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">default:
  stylesheets:    
    - /myThemePlugin/css/main: { position: last }
    - /myThemePlugin/css/bannerhealth: {position: last}
    - %SF_ADMIN_WEB_DIR%/css/main
    - %SF_CALENDAR_WEB_DIR%/skins/aqua/theme</pre></div></div>


<p>And I have another one to apply some additional stylesheets to my error pages:</p>


<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">error404Success:
  metas:
    title:        404 Not Found
  stylesheets: 
    - /sf/sf_default/css/screen.css
    - /sf/sf_default/css/ie.css
    - /myThemePlugin/css/errors: {position: last}
&nbsp;
disabledSuccess:
  metas:
    title:        Temporarily Unavailable
  stylesheets: 
    - /sf/sf_default/css/screen.css
    - /sf/sf_default/css/ie.css
    - /myThemePlugin/css/errors: {position: last}</pre></div></div>


<h3>relative image paths in stylesheets and error pages</h3>

<p>I use relative paths in my stylesheets (served out of <var>myprojecturl/myThemePlugin/css/</var>) so they can find the images (<var>myprojecturl/myThemePlugin/images/</var>):</p>


<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw1">background-image</span><span class="sy0">:</span> <span class="kw2">url</span><span class="br0">&#40;</span><span class="co2">../images/tall_gradient.jpg</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>


<p>I&#8217;d do the same if my error templates (like <var>plugins/myThemePlugin/modules/default/templates/error404Success.php</var>) used images, but they don&#8217;t.</p>

<p>The pages in <var>plugins/myThemePlugin/web/errors</var> (which are installed via <code>svn:externals</code> now in <var>web/myThemePlugin/errors</var>) are used when things are so broken symfony can&#8217;t build template pages, so they have full HTML structure, including full stylesheet tags:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">&lt;?php</span> <span class="re0">$path</span> <span class="sy0">=</span> <span class="st_h">'..'</span><span class="sy0">;</span> <span class="sy1">?&gt;</span>
&nbsp;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; media=&quot;screen&quot; href=&quot;<span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$path</span> <span class="sy1">?&gt;</span>/../sf/sf_default/css/screen.css&quot; /&gt;
&lt;!--[if lt IE 7.]&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; media=&quot;screen&quot; href=&quot;<span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$path</span> <span class="sy1">?&gt;</span>/../sf/sf_default/css/ie.css&quot; /&gt;
&lt;![endif]--&gt;
&nbsp;
&nbsp;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; media=&quot;screen&quot; href=&quot;<span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$path</span> <span class="sy1">?&gt;</span>/css/main.css&quot; /&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; media=&quot;screen&quot; href=&quot;<span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$path</span> <span class="sy1">?&gt;</span>/css/bannerhealth.css&quot; /&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; media=&quot;screen&quot; href=&quot;<span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$path</span> <span class="sy1">?&gt;</span>/css/errors.css&quot; /&gt;</pre></div></div>


<h2>Apache error page configuration</h2>

<p>Finally, I tell Apache to use my customized error pages for errors in this project.</p>


<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">  &lt;<span class="kw3">Directory</span> <span class="st0">&quot;/path/to/myproject/web&quot;</span>&gt;
        <span class="kw1">ErrorDocument</span> <span class="nu0">404</span> /myproject/default/error404
	<span class="kw1">ErrorDocument</span> <span class="nu0">500</span> /myproject/bhThemePlugin/errors/error500.php
  &lt;/<span class="kw3">Directory</span>&gt;</pre></div></div>


<p>There we go!   Now I have a lot less to do each time I make a new app; all the pretty stuff is in my plugin, and there aren&#8217;t any surprisingly brown symfony pages to throw off any users.</p>

<p>What do you think?  Any errors or ommissions or problems?</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2009/06/making-a-symfony-plug-in-for-visual-theme-and-custom-errors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wordpress plugin to make code samples prettier</title>
		<link>http://n8v.enteuxis.org/2009/03/wordpress-plugin-to-make-code-samples-prettier/</link>
		<comments>http://n8v.enteuxis.org/2009/03/wordpress-plugin-to-make-code-samples-prettier/#comments</comments>
		<pubDate>Thu, 26 Mar 2009 00:24:52 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Giving back]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[syntax]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[wp-syntax]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=215</guid>
		<description><![CDATA[I&#8217;ve always had a weakness for &#8220;preferences&#8221;.  I spent hours going through all the available preference panes on the first Mac I had access to (an SE II I think, ca. 1989), tweaking this and that to get it to look as &#8220;customized&#8221; as possible.  Hours setting up font and styles on school [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve always had a weakness for &#8220;preferences&#8221;.  I spent hours going through all the available preference panes on the first Mac I had access to (an <var>SE II</var> I think, ca. 1989), tweaking this and that to get it to look as &#8220;customized&#8221; as possible.  Hours setting up font and styles on school assignments, days banging on my Emacs config to be more like I want.</p>

<p>So it&#8217;s been secretly irking me for a while that although I installed the very nice <a href="http://wordpress.org/extend/plugins/wp-syntax/">WP-Syntax code highlighting plugin </a>for this WordPress blog, it was hard to get it to display things in reverse-video like I prefer for all my terminal and text editor windows, and like I love in <a href="http://www.symfony-project.org/book/">the online Symfony documentation</a>.  It&#8217;s just nicer on the eyes, you know?  Digging in, I found the <a href="http://qbnz.com/highlighter/">GeSHI syntax highlighter</a> to be impressive in scope but scary in its inline-style-generating detail.</p>

<p>So today, to solve the problem for more than just me, I published <a href="http://wordpress.org/extend/plugins/wp-syntax-hacktify/">my very first WordPress plugin, wp-syntax-hacktify</a>.  Very educational!  I like the plugin system at wordpress.org.</p>

<p>The plugin tells GeSHI to use stylesheets instead and provides a <a href="http://svn.wp-plugins.org/wp-syntax-hacktify/trunk/hacktified.css">slightly more commented/documented stylesheet</a> as an example for if you&#8217;d like to override it with your own color scheme.</p>

<p>So now my code samples can be all nicer and stuff, like this:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">  <span class="co4">/**
   * Print a string to the log using 'debug' level.  For printf-style
   * debugging.
   *
   * @param      string $m      The string to log
   * @return     nothing
   */</span>
  <span class="kw2">public</span> <a href="http://www.php.net/static"><span class="kw3">static</span></a> <span class="kw2">function</span> debug <span class="br0">&#40;</span><span class="re0">$m</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw1">if</span> <span class="br0">&#40;</span>sfConfig<span class="sy0">::</span><span class="me2">has</span><span class="br0">&#40;</span><span class="st_h">'sf_logging_enabled'</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'sf_logging_enabled'</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
      <span class="br0">&#123;</span>
        <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$logger</span> <span class="sy0">=</span> sfContext<span class="sy0">::</span><span class="me2">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getLogger</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
          <span class="re0">$logger</span><span class="sy0">-&gt;</span><span class="me1">debug</span><span class="br0">&#40;</span><span class="re0">$m</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="br0">&#125;</span>
      <span class="br0">&#125;</span>
    <span class="kw1">elseif</span> <span class="br0">&#40;</span>sfConfig<span class="sy0">::</span><span class="me2">has</span><span class="br0">&#40;</span><span class="st_h">'bhLDAP_echo_debugging'</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'bhLDAP_echo_debugging'</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
      <span class="br0">&#123;</span>
        <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&quot;# <span class="es4">$m</span><span class="es1">\n</span>&quot;</span><span class="sy0">;</span>
      <span class="br0">&#125;</span>
    <span class="kw1">else</span>
      <span class="br0">&#123;</span>
<span class="co1">//      echo $m;</span>
      <span class="br0">&#125;</span>
  <span class="br0">&#125;</span>
&nbsp;
  <span class="co4">/**
   * Dump a data structure to the log at the 'debug' level.  Uses
   * print_r() formatting.
   *
   * @param      mixed $v         The variable/data structure to dump
   * @param      string $label    An optional label to print in front of the dump
   * @return     nothing
   */</span>
  <span class="kw2">public</span> <a href="http://www.php.net/static"><span class="kw3">static</span></a> <span class="kw2">function</span> debugDump <span class="br0">&#40;</span><span class="re0">$v</span><span class="sy0">,</span> <span class="re0">$label</span> <span class="sy0">=</span> <span class="st0">&quot;var dump&quot;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw2">self</span><span class="sy0">::</span><span class="me2">debug</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es4">$label</span>:  &quot;</span> <span class="sy0">.</span> <a href="http://www.php.net/print_r"><span class="kw3">print_r</span></a><span class="br0">&#40;</span><span class="re0">$v</span><span class="sy0">,</span> <span class="kw2">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span></pre></div></div>


<p>Now the code on my blog can look nice even if it&#8217;s terrifically hacky!</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2009/03/wordpress-plugin-to-make-code-samples-prettier/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Completely custom Symfony error pages</title>
		<link>http://n8v.enteuxis.org/2009/03/completely-custom-symfony-error-pages/</link>
		<comments>http://n8v.enteuxis.org/2009/03/completely-custom-symfony-error-pages/#comments</comments>
		<pubDate>Tue, 17 Mar 2009 22:39:58 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=177</guid>
		<description><![CDATA[For every Symfony project I work on, I eventually want to get rid of the tasteful brown error pages with the Symfony logo on them and install my own, so the users don&#8217;t get weirded out and somehow start thinking &#8220;Symfony = error&#8221;.  Also, I&#8217;m probably overly optimistic, but it would be nice if [...]]]></description>
			<content:encoded><![CDATA[<p>For every Symfony project I work on, I eventually want to get rid of the tasteful brown error pages with the Symfony logo on them and install my own, so the users don&#8217;t get weirded out and somehow start thinking &#8220;Symfony = error&#8221;.  Also, I&#8217;m probably overly optimistic, but it would be nice if there was a valid email address on the error page so I could hear users complain.</p>

<p><a href="http://www.symfony-project.org/book/1_1/19-Mastering-Symfony-s-Configuration-Files#chapter_19_sub_default_modules_and_actions">The documentation</a> is good, but I want a simpler recipe that also accounts for all the forseeable errors, even those that don&#8217;t get to Symfony.  Some details vary by version, but in short, for symfony 1.1:
<span id="more-177"></span></p>

<h3>Test URLs</h3>

<p>We want to ultimately make sure that these URLs behave the right way:</p>

<h4>Normal errors (must have)&#8211; 404 Not Found and 500 Server Error</h4>

<table cellpadding="3">
<tr style="background: rgb(218, 231, 180);"><td>
<var>http://<samp>localhost/myapp</samp>/default/error404</var>
</td><td>
The &#8220;real&#8221; 404 page&#8230; it&#8217;s actually strangely &#8220;found&#8221; in this case.
</td></tr>

<tr><td>

http://<samp>localhost/myapp/mymodule/view</samp>/id/22222

</td><td>
A <code>forward404Unless</code> style forwarding should get the custom 404 page.  This is really the most likely case&#8211; if a user follows a link to an object another user has deleted, I want them to see the nice page.

</td></tr>



<tr style="background: rgb(218, 231, 180);"><td>
http://<samp>localhost/myapp/</samp>junk.php , or 

http://<samp>localhost/myapp/</samp>images/junk.gif

</td><td>
A request that Apache handles should display the custom 404 page too.
</td></tr>

<tr><td>

http://<samp>localhost/myapp</samp>/errors/error500.php

</td><td>
The &#8220;real&#8221; URL of the 500 error page should work.
</td></tr>

<tr style="background: rgb(218, 231, 180);"><td>

http://<samp>localhost/myapp</samp>/awfijwef/awfijawfo

</td><td>
Another real 404 error&#8211; Symfony forwards nonsensical module/action stuff to the custom 404 page.
</td></tr>


</table>

<p>I have seen error 500 pages countless times during app development, but I just could <strong>NOT</strong> reproduce one to test the 500 error page.  Any quick recipes for that, anyone?</p>

<h4>More esoteric error conditions&#8211; app unavailable/locked, module disabled</h4>

<table cellpadding="3">
<tr><td>
<var>http://localhost/myapp/errors/unavailable.php</var>
</td><td>
The &#8220;unavailable&#8221; page for when a whole symfony app is locked with <kbd>symfony project:disable <samp>app env</samp></kbd>*, or while the cache is being cleared.
</td></tr>


<tr style="background: rgb(218, 231, 180);"><td>
any application URL after I run <kbd>symfony project:disable</kbd> and I have the <code>check_lock</code> setting on*
</td><td>
should go to the &#8216;unavailable&#8217; page (unavailable.php)
</td></tr>

<tr><td>
<var>http://localhost/myapp/default/disabled</var>
</td><td>
The real &#8220;I&#8217;m disabled&#8221; page for when a module is locked with <kbd></kbd> in the <a href="http://www.symfony-project.org/book/1_1/06-Inside-the-Controller-Layer#chapter_06_module_configuration">module&#8217;s config file</a>, e.g. <var>apps/frontend/modules/<samp>mymodule</samp>/config/module.yml</var>
</td></tr>

<tr style="background: rgb(218, 231, 180);"><td>
http://<samp>localhost/myapp/</samp>mymodule/myaction , when I&#8217;ve explicitly disabled the module by putting this in <var>apps/frontend/mymodule/config/module.yml</var>:
<pre>
all:
  enabled:     false
</pre>
</td><td>
The disabled page (above)
</td></tr>


</table>

<h3>Steps</h3>

<ol>

    <li>manually create a few files for the <var>default</var> module.  <strong>DO NOT</strong> use <code>symfony generate:module</code> because you only want to override a small bit of the built-in <var>default</var> module (found in <var>/path/to/symfony/lib/controller/default/templates/</var>* incidentally, if you ever want to see what you&#8217;re overriding).


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw2">mkdir</span> apps<span class="sy0">/</span>frontend<span class="sy0">/</span>modules<span class="sy0">/</span>default
$ <span class="kw2">mkdir</span> apps<span class="sy0">/</span>frontend<span class="sy0">/</span>modules<span class="sy0">/</span>default<span class="sy0">/</span>config
$ <span class="kw2">mkdir</span> apps<span class="sy0">/</span>frontend<span class="sy0">/</span>modules<span class="sy0">/</span>default<span class="sy0">/</span>templates
$ <span class="kw2">touch</span> apps<span class="sy0">/</span>frontend<span class="sy0">/</span>modules<span class="sy0">/</span>default<span class="sy0">/</span>config<span class="sy0">/</span>view.yml
$ <span class="kw2">touch</span> apps<span class="sy0">/</span>frontend<span class="sy0">/</span>modules<span class="sy0">/</span>default<span class="sy0">/</span>templates<span class="sy0">/</span>error404Success.php
$ <span class="kw2">touch</span> apps<span class="sy0">/</span>frontend<span class="sy0">/</span>modules<span class="sy0">/</span>default<span class="sy0">/</span>templates<span class="sy0">/</span>disabledSuccess.php</pre></div></div>



</li>

    <li>Edit the templates I just made&#8211; remember, the content for these goes inside your sitewide <var>layout.php</var>.

I started out by copying the default templates in <var>lib/controller/default/templates/</var> from my Symfony distribution.
</li>
    <li>create mostly static pages for <var>web/errors/error500.php</var> and <var>unavailable.php</var>***  They won&#8217;t be wrapped in layout.php so they need to have the full page structure, and basically no symfony-involving PHP code (like helpers, too bad), though I do use a bit of really basic stuff, like including the URL in my mailto form on the 500 page:


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">  &lt;dl class=&quot;sfTMessageInfo&quot;&gt;
    &lt;dt&gt;Something is terribly broken.&lt;/dt&gt;
    &lt;dd&gt;
	  &lt;p&gt;
Please 
&lt;a href=&quot;mailto:webmaster@mycompany.com?subject=500 error at http://
<span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$_SERVER</span><span class="br0">&#91;</span><span class="st_h">'SERVER_NAME'</span><span class="br0">&#93;</span> <span class="sy0">.</span> <span class="st_h">'/'</span><span class="sy0">.</span> <span class="re0">$_SERVER</span><span class="br0">&#91;</span><span class="st_h">'REQUEST_URI'</span><span class="br0">&#93;</span>  <span class="sy1">?&gt;</span>
<span class="kw2">&lt;?php</span> 
<span class="kw1">if</span> <span class="br0">&#40;</span><a href="http://www.php.net/array_key_exists"><span class="kw3">array_key_exists</span></a><span class="br0">&#40;</span><span class="st_h">'HTTP_REFERER'</span><span class="sy0">,</span> <span class="re0">$_SERVER</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
  <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&quot;&amp;body=Referrer: &quot;</span><span class="sy0">.</span><span class="re0">$_SERVER</span><span class="br0">&#91;</span><span class="st_h">'HTTP_REFERER'</span><span class="br0">&#93;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
 <span class="sy1">?&gt;</span>&quot;&gt;
e-mail us at webmaster@mycompany.com&lt;/a&gt; and let us know what you were doing when this error occurred. We will fix it as soon as possible.
&lt;/p&gt;
	  &lt;p&gt;
   If you have an urgent problem, please call the Support Desk at XXXX.
&lt;/p&gt;
	  &lt;p&gt;
   You may also find the &lt;a href=&quot;/README.html&quot;&gt;documentation&lt;/a&gt; useful.
&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;</pre></div></div>



</li>

    <li>Include my stylesheets, in <var>view.yml</var>:

<pre>
error404Success:
  metas:
    title:        ED Log 404 Not Found
  stylesheets:
    - -*
    - mystyles1: { position: last }
    - mystyles2: {position: last}
    - /sf/sf_default/css/screen.css
    - /sf/sf_default/css/ie.css
    - errors: {position: last}
</pre>
(and the same thing for <code>disabledSuccess:</code>)

My <var>web/css/errors.css</var>  overrides some of the default symfony error page styles (compare <var>web/sf/sf_default/css/screen.css</var> in your symfony distribution) to make them less brown, but I keep the general thing.
</li>

    <li>If your application has security on by default, make sure to un-secure the error pages so people can see them without logging in.  Add these above the <code>default</code> rule in <var>apps/frontend/config/security.yml</var>:

<pre>
error404:
  is_secure: off

disabled:
  is_secure: off
</pre>
</li>


    <li>Tell Apache where to find total 500 errors and 404 errors that don&#8217;t make it to symfony (like anything that doesn&#8217;t get to a front controller, like a misspelled controller or image name):


<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">  &lt;<span class="kw3">Directory</span> <span class="st0">&quot;/var/www/my_sf_app/web&quot;</span>&gt;
        <span class="kw1">ErrorDocument</span> <span class="nu0">404</span> /default/error404
	<span class="kw1">ErrorDocument</span> <span class="nu0">500</span> /errors/error500.php
  &lt;/<span class="kw3">Directory</span>&gt;</pre></div></div>



</li>

<li>Hrm, the table of URLs above sounds like a good test script&#8230; <strong>BUT</strong>, it resists scripting because most of the error URLs are outside symfony, so you don&#8217;t get the custom error pages when going to an actual error with sfTestBrowser, or even a regular sfBrowser, because instead you get fancy exception stuff.  

So, here&#8217;s a pretty lame test script I put in <var>test/functional/frontend/customErrors.php</var> that tests the easiest cases, but it&#8217;s not hard to manually try the others with a browser.  I welcome suggestions for improvement!


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">&nbsp;
<span class="kw2">&lt;?php</span>
&nbsp;
<span class="kw1">include</span><span class="br0">&#40;</span><a href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><span class="kw2">__FILE__</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st_h">'/../../bootstrap/functional.php'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="re0">$e404_regexp</span> <span class="sy0">=</span> <span class="st0">&quot;webmaster@mycompany&quot;</span><span class="sy0">;</span>
<span class="re0">$disabled_regexp</span> <span class="sy0">=</span> <span class="st0">&quot;xXXXX&quot;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// create a new test browser</span>
<span class="re0">$browser</span> <span class="sy0">=</span> <span class="kw2">new</span> sfTestBrowser<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="coMULTI">/* http://localhost/myapp/default/error404	 
The &quot;real&quot; 404 page */</span>
&nbsp;
<span class="re0">$browser</span><span class="sy0">-&gt;</span>
  <span class="me1">get</span><span class="br0">&#40;</span><span class="st_h">'/default/error404'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">isStatusCode</span><span class="br0">&#40;</span><span class="nu0">404</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">isRequestParameter</span><span class="br0">&#40;</span><span class="st_h">'module'</span><span class="sy0">,</span> <span class="st_h">'default'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">isRequestParameter</span><span class="br0">&#40;</span><span class="st_h">'action'</span><span class="sy0">,</span> <span class="st_h">'error404'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">checkResponseElement</span><span class="br0">&#40;</span><span class="st_h">'body'</span><span class="sy0">,</span> <span class="st0">&quot;/<span class="es4">$e404_regexp</span>/&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp;
<span class="coMULTI">/* http://localhost/myapp/default/disabled	 
The &quot;unavailable&quot; page for when symfony is locked with symfony project:disable */</span>
&nbsp;
<span class="re0">$browser</span><span class="sy0">-&gt;</span>
  <span class="me1">get</span><span class="br0">&#40;</span><span class="st_h">'/default/disabled'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">isStatusCode</span><span class="br0">&#40;</span><span class="nu0">200</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">isRequestParameter</span><span class="br0">&#40;</span><span class="st_h">'module'</span><span class="sy0">,</span> <span class="st_h">'default'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">isRequestParameter</span><span class="br0">&#40;</span><span class="st_h">'action'</span><span class="sy0">,</span> <span class="st_h">'disabled'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">checkResponseElement</span><span class="br0">&#40;</span><span class="st_h">'body'</span><span class="sy0">,</span> <span class="st0">&quot;/<span class="es4">$disabled_regexp</span>/&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>




And a few passing tests is better than none, right?

<pre>
$ <kbd>php ./symfony test:functional frontend customError</kbd>
# get /default/error404
ok 1 - status code is 404
ok 2 - request parameter module is default
ok 3 - request parameter action is error404
ok 4 - response selector body matches regex /webmaster@mycompany/
# get /default/disabled
ok 5 - status code is 200
ok 6 - request parameter module is default
ok 7 - request parameter action is disabled
ok 8 - response selector body matches regex /xXXXX/
1..8
 Looks like everything went fine.
</pre>
</li>

</ol>

<p>Sheesh, it&#8217;s still a little too involved for such a small benefit.  If anyone has any ideas on how to streamline this procedure, let me know!  Maybe it could be a plugin or an enhancement to symfony?</p>

<ul>
<li>Disabling projects only works if the <a href="http://www.symfony-project.org/book/1_1/19-Mastering-Symfony-s-Configuration-Files#chapter_19_sub_default_modules_and_actions"><code>check_lock</code>  option</a> is enabled in e.g. <var>apps/frontend/config/settings.yml</var></li>
</ul>

<p>** Symfony 1.0 default templates are found in <var>&#8230;/symfony/data/modules/default/templates/</var> and include an &#8216;unavailable&#8217; template in addition to &#8216;disabled&#8217;.  Symfony 1.2 templates are in the same place as in 1.1.</p>

<p>*** Symfony 1.2 wants its 500 error page in <var>config/error/error.html.php</var></p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2009/03/completely-custom-symfony-error-pages/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>LDAP powered by MySQL on RHEL5</title>
		<link>http://n8v.enteuxis.org/2009/02/ldap-powered-by-mysql-on-rhel5/</link>
		<comments>http://n8v.enteuxis.org/2009/02/ldap-powered-by-mysql-on-rhel5/#comments</comments>
		<pubDate>Tue, 24 Feb 2009 02:01:12 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[LDAP]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=133</guid>
		<description><![CDATA[Background

We need a quick-and-dirty LDAP server with basically a list of usernames and passwords to point Cisco ACS gear at, in order to provide people with limited-time authentication tokens to a wireless network.  I need to populate that with an HL7 interface in Perl and make a web app UI frontend (preferably using symfony). [...]]]></description>
			<content:encoded><![CDATA[<h3>Background</h3>

<p>We need a quick-and-dirty <abbrev title="Lightweight Directory Access Protocol">LDAP</abbrev> server with basically a list of usernames and passwords to point Cisco ACS gear at, in order to provide people with limited-time authentication tokens to a wireless network.  I need to populate that with an <a href="http://hl7toolkit.sf.net">HL7 interface in Perl</a> and make a web app UI frontend (preferably using symfony).  The latter two interfaces are well established around here with MySQL, so I am trying to use OpenLDAP&#8217;s SQL backend to make that happen naturally.</p>

<h4>Simplifications</h4>

<p>Unlike other similar implementations out there, I have smaller goals:</p>

<ul>
    <li>The database will be updated/written by the HL7 interface and web interface.  The LDAP tools don&#8217;t need to write to it.</li>
    <li>All my user data should fit nicely into two tables (users and groups&#8230; and another table to relate many-to-many), and two Objectclasses in LDAPland.</li>
</ul>

<p><span id="more-133"></span></p>

<h3>Resources</h3>

<p>These were unexpectedly hard to Google up, which is partly why I&#8217;m documenting them here for Posterity.</p>

<ul>
    <li>Zytrax has an open source book about LDAP entitled <a href="http://www.zytrax.com/books/ldap/">LDAP for Rocket Scientists</a>, which has <a href="http://www.zytrax.com/books/ldap/ch2/index.html#basic">an excellent chapter about LDAP concepts</a>, which is nice since I don&#8217;t really understand LDAP like I do the other technologies involved.</li>

    <li><a href="http://www.openldap.org/doc/admin24/backends.html#SQL">Section &#8220;10.10.2. back-sql Configuration&#8221; of the OpenLDAP manual</a></li>
    <li>The <a href="http://linux.die.net/man/5/slapd-sql">slapd-sql man page</a> is indispensible.  See especially the &#8220;METAINFORMATION USED&#8221; section.</li>
    <li>The <a href="http://www.openldap.org/devel/cvsweb.cgi/~checkout~/servers/slapd/back-sql/rdbms_depend/README?rev=1.4.4.1&#038;hideattic=1&#038;sortbydate=0">README that comes with the back-sql samples</a></li>
    <li>The samples themselves (either unpack <var>servers/slapd/back-sql/rdbms_depend/mysql</var> from the <a href="http://www.openldap.org/software/download/">source tarball </a>or <a href="http://www.openldap.org/devel/cvsweb.cgi/servers/slapd/back-sql/rdbms_depend/mysql/?hideattic=1&#038;sortbydate=0">browse them</a>, but you&#8217;ll probably want them unpacked so you can feed the schema to the <var>mysql </var> client.  MOST OF WHAT YOU NEED TO LEARN is demonstrated in the samples.</li>
    <li>This <a href="http://www.flatmtn.com/article/setting-ldap-back-sql#LdapBacksql-2">4-year-old blog article at/by &#8220;Flat Mountain&#8221;</a> is sketchy but an improvement over the documents above!</li>
    <li><a href="http://www.docunext.com/blog/2006/10/31/openldap-mysql-documentation/">Albert Lash at DocuNext has a 2-year-old post similar to this one </a> with another list of fine references! 
    <li>This <a href="http://www.darold.net/projects/ldap_pg/HOWTO/index.html">HOWTO for OpenLDAP and Postgresql</a> by Gilles Darold is far superior than the other articles, but needs adaptation of course for MySQL</li>
    <li>Likewise, here&#8217;s <a href="http://www.easysoft.com/applications/openldap/back-sql-odbc.html">a good article for doing the same thing with Oracle/MSSQL</a></li>
    <li>And here are some <a href="http://www.cmu.edu/acs/ldap/sql_notes">extended notes from someone who did it with Oracle</a>, including another explanation of the data mapping part.</li>

</ul>

<h3>I. Install Stuff</h3>

<p>I&#8217;m using <abbr title="Red Hat Enterprise Linux 5.0">RHEL5</abbr> on a virtual machine.  Your package system may vary.  You may in fact have to compile from source to get SQL support in LDAP.</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw2">sudo</span> yum <span class="kw2">install</span> openldap openldap-clients openldap-servers openldap-devel openldap-servers-sql</pre></div></div>


<h3>II. Get and unpack the source code for the MySQL samples</h3>

<ol>
    <li><a href="http://www.openldap.org/software/download/">Download the source tarball</a> to your machine</li>
    <li>Unpack it


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">tar</span> zxf openldap-stable-20080813.tgz</pre></div></div>



</li>
</ol>

<h3>III. Create the database and tables</h3>

<p>Make sure the mysql server is running of course.  We&#8217;re assuming it&#8217;s on the same host as the LDAP server.</p>

<p>Create the database (<samp>my_db_name</samp>) and a password-having user (<samp>my_mysql_user</samp>) with all privileges to that database (I recommend the MySQL Administrator GUI for this, strangely enough since I usually dislike clicking on stuff).  You should be able to connect to your database like this now:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ mysql -umy_mysql_user <span class="re5">-pxxxxxxxxxxxxx</span>  my_db_name</pre></div></div>


<p>Build the tables that configure how OpenLDAP talks to the database.</p>

<ol>
    <li><var>cd</var> into <var>servers/slapd/back-sql/rdbms_depend/mysql</var> from the unpacked openldap source</li>
    <li>Feed <var>backsql_create.sql</var> to the &#8216;mysql&#8217; client


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ mysql -umy_mysql_user <span class="re5">-pxxxxxxxxxxxxx</span>  my_db_name <span class="sy0">&lt;</span> backsql_create.sql</pre></div></div>



</li>
</ol>

<h3>IV. Hack the basic config files</h3>

<h4>a. <var>slapd.conf</var></h4>

<p>Basically I&#8217;m starting from the <var>slapd.conf</var> in the rdbms_depend/mysql sample (see above), but folding in some RedHatese file locations from the distributed <var>slapd.conf</var>.</p>

<p>I define an adminstrative user with the <code>rootdn </code> and <code>rootpw</code> directives.  Use <var>slappasswd</var> to generate the hashed password:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ slappasswd <span class="re5">-h</span> <span class="br0">&#123;</span>crypt<span class="br0">&#125;</span></pre></div></div>


<p>and type in the password.  It will spit out the string you need, which is prefixed by the algorithm in curly braces.</p>


<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"># See slapd.conf<span class="br0">&#40;</span><span class="nu0">5</span><span class="br0">&#41;</span> for details on configuration options.
# This file should NOT be world readable.
#
include         /etc/openldap/schema/core.schema
include         /etc/openldap/schema/cosine.schema
include         /etc/openldap/schema/inetorgperson.schema
&nbsp;
pidfile         /var/run/openldap/slapd.pid
argsfile        /var/run/openldap/slapd.args
# Timeout in seconds, <span class="nu0">0</span> <span class="sy0">=</span><span class="re2"> never</span>
idletimeout     <span class="nu0">30</span>
threads         <span class="nu0">32</span>
# Debuging level, <span class="nu0">0</span> <span class="sy0">=</span><span class="re2"> none</span>
loglevel        <span class="nu0">32</span>
&nbsp;
# THIS IS IMPORTANT-- without it you will get <span class="st0">&quot;&lt;database&gt; failed init (sql)!&quot;</span>
# Load dynamic backend modules:
modulepath    /usr/lib/openldap
# modules available in openldap-servers-sql RPM package:
moduleload back_sql.la
&nbsp;
&nbsp;
#######################################################################
# SQL Database Definitions
#######################################################################
&nbsp;
database        sql
suffix          <span class="st0">&quot;ou=Junk,ou=AK,DC=mycompany,DC=com&quot;</span>
rootdn          <span class="st0">&quot;cn=root,ou=Users,ou=Junk,ou=AK,DC=,mycompany,DC=com&quot;</span>
rootpw          <span class="br0">&#123;</span>CRYPT<span class="br0">&#125;</span>xxxxxxxxxxxx
&nbsp;
#  The name of the ODBC datasource <span class="br0">&#40;</span>from odbc.ini,
#     not necessarily the database instance<span class="br0">&#41;</span> to use.
dbname          my_database
dbuser          my_database_user
dbpasswd        xxxxxxxxxxxxxxxx
&nbsp;
# this is important because my simple view for the ldap_entries table
# has no 'organization' object.  See `man slapd-sql`.
baseObject
&nbsp;
subtree_cond    <span class="st0">&quot;ldap_entries.dn LIKE CONCAT('%',?)&quot;</span>
insentry_stmt   <span class="st0">&quot;INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) VALUES (?,?,?,?)&quot;</span>
has_ldapinfo_dn_ru      no
&nbsp;
&nbsp;
#######################################################################
# Access Control
#    see http://www.openldap.org/doc/admin24/access-control.html
#    and `man slapd.access`
#######################################################################
&nbsp;
# Here we define who can see which parts of the directory
&nbsp;
# Hide the password attribute <span class="br0">&#40;</span>except for the root user of course<span class="br0">&#41;</span> but
#   allow authentication against it
access to attrs<span class="sy0">=</span><span class="re2">userPassword</span>
        by anonymous auth
        by * none
&nbsp;
# don't allow anonymous access
# allow authenticated users to see their own entry
access to *
        by self read
        by * none</pre></div></div>


<p>I started without the Access Control section and added it after I had things basically working.</p>

<h4>b. ODBC config files</h4>

<p>In my case they are in <var>/etc/odbc.ini</var> and <var>/etc/odbcinst.ini</var> already existed and just needed a MySQL section added to <var>odbcinst.ini</var> and a section for this particular database in <var>odbc.ini</var>, but I had to get the paths right for Red Hat.  See the MySQL section of step 2 of the <a href="http://www.openldap.org/devel/cvsweb.cgi/~checkout~/servers/slapd/back-sql/rdbms_depend/README?rev=1.5&#038;hideattic=1&#038;sortbydate=0">samples README document</a></p>

<p><var>/etc/odbcinst.ini</var>:</p>


<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"># Driver from the MyODBC package
# Setup from the unixODBC package
<span class="re0"><span class="br0">&#91;</span>MySQL<span class="br0">&#93;</span></span>
<span class="re1">Description</span>     <span class="sy0">=</span><span class="re2"> ODBC for MySQL</span>
<span class="re1">Driver</span>          <span class="sy0">=</span><span class="re2"> /usr/lib/libmyodbc3.so  # note, filename includes a <span class="nu0">3</span>, differs from docs</span>
<span class="re1">Setup</span>           <span class="sy0">=</span><span class="re2"> /usr/lib/libodbcmyS.so</span>
<span class="re1">FileUsage</span>       <span class="sy0">=</span><span class="re2"> 1</span></pre></div></div>


<p><var>/etc/odbc.ini</var></p>


<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="re0"><span class="br0">&#91;</span>my_database<span class="br0">&#93;</span></span>
<span class="re1">Description</span>         <span class="sy0">=</span><span class="re2"> my database</span>
<span class="re1">Driver</span>              <span class="sy0">=</span><span class="re2"> MySQL</span>
<span class="re1">Trace</span>               <span class="sy0">=</span><span class="re2"> No</span>
<span class="re1">Database</span>            <span class="sy0">=</span><span class="re2"> my_db_name</span>
<span class="re1">Servername</span>          <span class="sy0">=</span><span class="re2"> localhost</span>
<span class="re1">UserName</span>            <span class="sy0">=</span><span class="re2"> my_database_user</span>
<span class="re1">Password</span>            <span class="sy0">=</span><span class="re2"> xxxxxxxxxxxxxxxxx</span>
<span class="re1">ReadOnly</span>            <span class="sy0">=</span><span class="re2"> No</span>
<span class="re1">RowVersioning</span>       <span class="sy0">=</span><span class="re2"> No</span>
<span class="re1">ShowSystemTables</span>    <span class="sy0">=</span><span class="re2"> No</span>
<span class="re1">ShowOidColumn</span>       <span class="sy0">=</span><span class="re2"> No</span>
<span class="re1">FakeOidIndex</span>        <span class="sy0">=</span><span class="re2"> No</span>
<span class="re1">ConnSettings</span>        <span class="sy0">=</span>
<span class="re1">SOCKET</span>              <span class="sy0">=</span><span class="re2"> /var/lib/mysql/mysql.sock</span></pre></div></div>


<p>(OK, here&#8217;s where I dinked with the example database and read lots of examples and stuff, but hopefully you can skip that because of this excellent documentation <img src='http://n8v.enteuxis.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  )</p>

<h3>V. Create and populate your user and group tables</h3>

<p>These are my basic tables of users and groups:</p>


<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw1">CREATE</span> <span class="kw1">TABLE</span> my_user <span class="br0">&#40;</span>
  id int<span class="br0">&#40;</span><span class="nu0">10</span><span class="br0">&#41;</span> <span class="kw1">UNSIGNED</span> <span class="kw1">NOT</span> <span class="kw1">NULL</span> <span class="kw1">AUTO_INCREMENT</span><span class="sy0">,</span>
  username varchar<span class="br0">&#40;</span><span class="nu0">45</span><span class="br0">&#41;</span> <span class="kw1">NOT</span> <span class="kw1">NULL</span><span class="sy0">,</span>
  password varchar<span class="br0">&#40;</span><span class="nu0">45</span><span class="br0">&#41;</span> <span class="kw1">NOT</span> <span class="kw1">NULL</span><span class="sy0">,</span>
  first_name varchar<span class="br0">&#40;</span><span class="nu0">45</span><span class="br0">&#41;</span> <span class="kw1">DEFAULT</span> <span class="kw1">NULL</span><span class="sy0">,</span>
  last_name varchar<span class="br0">&#40;</span><span class="nu0">45</span><span class="br0">&#41;</span> <span class="kw1">DEFAULT</span> <span class="kw1">NULL</span><span class="sy0">,</span>
  <span class="kw1">PRIMARY</span> <span class="kw1">KEY</span>  <span class="br0">&#40;</span>id<span class="sy0">,</span>username<span class="br0">&#41;</span>
<span class="br0">&#41;</span>;
&nbsp;
<span class="kw1">CREATE</span> <span class="kw1">TABLE</span> my_group <span class="br0">&#40;</span>
  id int<span class="br0">&#40;</span><span class="nu0">10</span><span class="br0">&#41;</span> <span class="kw1">UNSIGNED</span> <span class="kw1">NOT</span> <span class="kw1">NULL</span> <span class="kw1">AUTO_INCREMENT</span><span class="sy0">,</span>
  <span class="st0">`name`</span> varchar<span class="br0">&#40;</span><span class="nu0">45</span><span class="br0">&#41;</span> <span class="kw1">NOT</span> <span class="kw1">NULL</span><span class="sy0">,</span>
  <span class="kw1">PRIMARY</span> <span class="kw1">KEY</span>  <span class="br0">&#40;</span>id<span class="br0">&#41;</span>
<span class="br0">&#41;</span>;
&nbsp;
<span class="kw1">CREATE</span> <span class="kw1">TABLE</span> my_group_member <span class="br0">&#40;</span>
  <span class="co1">-- unique id isn't necessary but easier for symfony</span>
  id int<span class="br0">&#40;</span><span class="nu0">10</span><span class="br0">&#41;</span> <span class="kw1">UNSIGNED</span> <span class="kw1">NOT</span> <span class="kw1">NULL</span> <span class="kw1">AUTO_INCREMENT</span><span class="sy0">,</span>
  my_user_id int<span class="br0">&#40;</span><span class="nu0">10</span><span class="br0">&#41;</span> <span class="kw1">UNSIGNED</span> <span class="kw1">NOT</span> <span class="kw1">NULL</span><span class="sy0">,</span>
  my_group_id varchar<span class="br0">&#40;</span><span class="nu0">45</span><span class="br0">&#41;</span> <span class="kw1">NOT</span> <span class="kw1">NULL</span><span class="sy0">,</span>
  <span class="kw1">PRIMARY</span> <span class="kw1">KEY</span>  <span class="br0">&#40;</span>id<span class="br0">&#41;</span><span class="sy0">,</span>
  <span class="kw1">UNIQUE</span> <span class="kw1">KEY</span> uniquepair <span class="br0">&#40;</span>my_user_id<span class="sy0">,</span>my_group_id<span class="br0">&#41;</span>
<span class="br0">&#41;</span>;</pre></div></div>


<p>You&#8217;ll need to populate the tables with a user or two and at least one group, of course.</p>

<h3>VI. Insert the special configuration rows</h3>

<p>I entered these data sets using the <a href="http://dev.mysql.com/downloads/gui-tools/">MySQL Administrator</a> GUI.  The most helpful explanation was in the &#8220;METAINFORMATION USED&#8221; section of the <a href="http://linux.die.net/man/5/slapd-sql">slapd-sql man page</a>.</p>

<p>Basically, the <samp>ldap_*</samp> tables show the SQL backend how to map the database tables onto LDAP objects.  <a href="http://www.oav.net/mirrors/LDAP-ObjectClasses.html#atDisplayName">This is a nice reference to the common LDAP object schemas</a>.  That&#8217;s important because you can only map your database fields to fields in the schema for the objectClass you&#8217;re using (unless you want to start making your own schema, which is beyond my scope here).  In my case I&#8217;m using <var>inetOrgPerson</var>, which inherits from <var>organizationalPerson</var>, which inherits from <var>Person</var>, and for groups, <var>groupOfUniqueNames</var>.</p>

<p>The <strong>ldap_entry_objclasses</strong> table needs one row for each objectClass we&#8217;re using:</p>

<table border=1 cellspacing=1 cellpadding=0><tr>
<th>entry_id</th><th>oc_name</th></tr>
<tr>
<td>1</td><td>inetOrgPerson</td></tr>
<tr>
<td>2</td><td>groupOfUniqueNames</td></tr>
</table>

<p>The <strong>ldap_oc_mappings</strong> table also has a row for each objectClass, and it shows the sql backend how to find objects corresponding to those object classes.</p>

<table border=1 cellspacing=1 cellpadding=0><tr>
<th>id</th><th>name</th><th>keytbl</th><th>keycol</th><th>create_proc</th><th>delete_proc</th><th>expect_return</th></tr>
<tr>
<td>1</td><td>inetOrgPerson</td><td>my_user</td><td>id</td><td></td><td></td><td>0</td></tr>
<tr>
<td>2</td><td>groupOfUniqueNames</td><td>my_group</td><td>id</td><td></td><td></td><td>0</td></tr>
</table>

<p>The <strong>ldap_attr_mappings</strong> table is the most complex part.  Basically you&#8217;re showing the sql backend how to build queries that map the database columns onto LDAP attributes.</p>

<table border=1 cellspacing=1 cellpadding=0><tr>
<th>id</th><th>oc_<wbr />map_<wbr />id</th><th>name</th><th>sel_<wbr />expr</th><th>sel_<wbr />expr<wbr />_u</th><th>from_tbls</th><th>join_where</th><th>add_proc</th><th>delete_<wbr />proc</th><th>param_<wbr />order</th><th>expect_<wbr />return</th></tr>
<tr>
<td>1</td><td>1</td><td>cn</td><td>concat( first_name, &#8216; &#8216;, last_name )</td><td></td><td>my_user</td><td></td><td></td><td></td><td>3</td><td>0</td></tr>
<tr>
<td>2</td><td>1</td><td>givenName</td><td>first_name</td><td></td><td>my_user</td><td></td><td></td><td></td><td>3</td><td>0</td></tr>
<tr>
<td>3</td><td>1</td><td>sn</td><td>last_name</td><td></td><td>my_user</td><td></td><td></td><td></td><td>3</td><td>0</td></tr>
<tr>
<td>4</td><td>1</td><td>userPassword</td><td>password</td><td></td><td>my_user</td><td></td><td></td><td></td><td>3</td><td>0</td></tr>
<tr>
<td>5</td><td>1</td><td>uid</td><td>username</td><td></td><td>my_user</td><td></td><td></td><td></td><td>3</td><td>0</td></tr>
<tr>
<td>7</td><td>2</td><td>cn</td><td>name</td><td></td><td>my_group</td><td></td><td></td><td></td><td>3</td><td>0</td></tr>
<tr>
<td>8</td><td>2</td><td>uniqueMember</td><td>dn</td><td></td><td>my_group, my_<wbr />group_<wbr />member gu, my_<wbr />user u, ldap_<wbr />entries</td><td>my_group.id = gu.<wbr />my_<wbr />group_<wbr />id and gu.<wbr />my_<wbr />user_<wbr />id = u.id and oc_<wbr />map_<wbr />id = 1 and keyval = u.id</td><td></td><td></td><td>3</td><td>0</td></tr>
</table>

<h4>Create a view for the <abbrev title="Distinguished Name">DN</abbrev>s in ldap_entries</h4>

<p>I&#8217;m going to use the username field in my DN instead of the common name (CN) in most examples, because it&#8217;s more guaranteed to be unique, and <a href="http://www.zytrax.com/books/ldap/apa/dn-rdn.html">it is apparently OK to do so</a>.</p>


<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw1">DROP</span> <span class="kw1">TABLE</span> ldap_entries;
&nbsp;
<span class="kw1">CREATE</span> <span class="kw1">VIEW</span> ldap_entries <span class="kw1">AS</span>
  <span class="kw1">SELECT</span> 
    <span class="co1">-- differentiate id spaces here </span>
    <span class="br0">&#40;</span><span class="nu0">100000</span> <span class="sy0">+</span> my_user<span class="sy0">.</span>id<span class="br0">&#41;</span> <span class="kw1">AS</span> id<span class="sy0">,</span>
&nbsp;
    <span class="co1">-- calculate a DN for each user</span>
    ucase<span class="br0">&#40;</span>concat<span class="br0">&#40;</span>
     <span class="st0">'uid='</span><span class="sy0">,</span> my_user<span class="sy0">.</span>username<span class="sy0">,</span> 
     <span class="st0">',ou=Users,ou=Junk,ou=AK,DC=mycompany,DC=com'</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">AS</span> dn<span class="sy0">,</span> 
&nbsp;
    <span class="co1">-- the id of the inetOrgUser objectClass in ldap_entry_objclasses</span>
    <span class="nu0">1</span> <span class="kw1">AS</span> oc_map_id<span class="sy0">,</span>    
&nbsp;
    <span class="co1">-- zero for every row </span>
    <span class="co1">-- (see baseObject in the `slapd-sql` man page)</span>
    <span class="nu0">0</span> <span class="kw1">AS</span> parent<span class="sy0">,</span>
&nbsp;
    <span class="co1">-- the real id in the user table</span>
    my_user<span class="sy0">.</span>id <span class="kw1">AS</span> keyval 
&nbsp;
  <span class="kw1">FROM</span>
    my_user 
&nbsp;
<span class="kw1">UNION</span> 
&nbsp;
  <span class="kw1">SELECT</span> 
    <span class="co1">-- a different id space</span>
    <span class="br0">&#40;</span><span class="nu0">200000</span> <span class="sy0">+</span> my_group<span class="sy0">.</span>id<span class="br0">&#41;</span> <span class="kw1">AS</span> id<span class="sy0">,</span>
&nbsp;
    <span class="co1">-- calculate a DN for each object in our group table </span>
    ucase<span class="br0">&#40;</span>concat<span class="br0">&#40;</span>
    <span class="st0">'cn='</span><span class="sy0">,</span>my_group<span class="sy0">.</span>name<span class="sy0">,</span>
     <span class="st0">',ou=Users,ou=Junk,ou=AK,DC=mycompany,DC=com'</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">AS</span> dn
&nbsp;
    <span class="co1">-- the id of groupOfUniqueNames in ldap_entry_objclasses</span>
    <span class="nu0">2</span> <span class="kw1">AS</span>  oc_map_id<span class="sy0">,</span>
&nbsp;
    <span class="co1">-- like above</span>
    <span class="nu0">0</span> <span class="kw1">AS</span> parent<span class="sy0">,</span>
    my_group<span class="sy0">.</span>id <span class="kw1">AS</span> id 
&nbsp;
  <span class="kw1">FROM</span> 
    my_group</pre></div></div>


<h3>VII. Test and stuff</h3>

<h4>Launch the Slap daemon</h4>

<p>It&#8217;s nice to launch <var>slapd</var> in debug mode in one terminal.  This is pretty verbose and will hopefully tell you if you&#8217;ve got something wrong in your mapping tables or anything:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">sudo</span> <span class="sy0">/</span>usr<span class="sy0">/</span>sbin<span class="sy0">/</span>slapd <span class="re5">-d</span> <span class="nu0">5</span></pre></div></div>


<h4>Test connectivity and data with an LDAP client</h4>

<p>Hint:  it would help to <strong>LEARN HOW TO USE <a href="http://linux.die.net/man/1/ldapsearch">ldapsearch</a> correctly.</strong></p>

<p>Connect anonymously and spit out all the LDAP data (if ACL allows it&#8211; by slapd.conf above allows anonymous connections but won&#8217;t show any of the data):</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">ldapsearch <span class="re5">-x</span> <span class="re5">-s</span> sub <span class="re5">-b</span> <span class="st0">&quot;ou=Junk,ou=AK,DC=mycompany,DC=com&quot;</span> <span class="st0">&quot;(objectClass=*)&quot;</span></pre></div></div>


<p>Connect as root (the special account defined in slapd.conf) and show all the data in the directory:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">ldapsearch <span class="re5">-x</span> <span class="re5">-D</span> <span class="re2">uid</span>=root,<span class="re2">ou</span>=USERS,<span class="re2">OU</span>=JUNK,<span class="re2">OU</span>=AK,<span class="re2">DC</span>=MYCOMPANY,<span class="re2">DC</span>=COM <span class="re5">-w</span> xxxxxxxxx <span class="re5">-s</span> sub <span class="re5">-b</span> <span class="st0">&quot;ou=Junk,ou=AK,DC=mycompany,DC=com&quot;</span> <span class="st0">&quot;(objectClass=*)&quot;</span></pre></div></div>


<p>Here&#8217;s an example of what it shows me:</p>


<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"># extended LDIF
#
# LDAPv3
# base &lt;ou<span class="sy0">=</span><span class="re2">Junk,ou=AK,DC=mycompany,DC=com&gt; with scope subtree</span>
# filter: <span class="br0">&#40;</span>objectClass<span class="sy0">=</span><span class="re2">*<span class="br0">&#41;</span></span>
# requesting: ALL
#
&nbsp;
# Junk, AK, mycompany.com
dn: ou<span class="sy0">=</span><span class="re2">Junk,ou=AK,dc=mycompany,dc=com</span>
objectClass: extensibleObject
description: builtin baseObject for back-sql
description: all entries mapped in the <span class="st0">&quot;ldap_entries&quot;</span> table
description: must have <span class="st0">&quot;0&quot;</span> in the <span class="st0">&quot;parent&quot;</span> column
ou: Junk
&nbsp;
# TESTUSER, USERS, JUNK, AK, MYCOMPANY.COM
dn: uid<span class="sy0">=</span><span class="re2">TESTUSER,ou=USERS,OU=JUNK,OU=AK,DC=MYCOMPANY,DC=COM</span>
objectClass: inetOrgPerson
cn: test user
ou: guest
sn: user
uid: testuser
givenName: test
userPassword:: dGVzdHBhc3M<span class="sy0">=</span>
&nbsp;
# <span class="nu0">1234567890</span>, USERS, JUNK, AK, MYCOMPANY.COM
dn: uid<span class="sy0">=</span><span class="re2"><span class="nu0">1234567890</span>,ou<span class="sy0">=</span>USERS,ou<span class="sy0">=</span>JUNK,ou<span class="sy0">=</span>AK,DC<span class="sy0">=</span>MYCOMPANY,DC<span class="sy0">=</span>COM</span>
objectClass: inetOrgPerson
cn: test2 user2
ou: guest
sn: user2
uid: <span class="nu0">1234567890</span>
givenName: test2
userPassword:: MTIzNDU2Nzg5MA<span class="sy0">=</span><span class="re2">=</span>
&nbsp;
...
&nbsp;
# VALIDUSERS, GROUPS, JUNK, AK, MYCOMPANY.COM
dn: cn<span class="sy0">=</span><span class="re2">VALIDUSERS,ou=GROUPS,ou=JUNK,ou=AK,DC=MYCOMPANY,DC=COM</span>
objectClass: groupOfUniqueNames
cn: validUsers
uniqueMember: uid<span class="sy0">=</span><span class="re2"><span class="nu0">1234567890</span>,ou<span class="sy0">=</span>USERS,OU<span class="sy0">=</span>JUNK,OU<span class="sy0">=</span>AK,DC<span class="sy0">=</span>MYCOMPANY,DC<span class="sy0">=</span>COM</span>
...
uniqueMember: uid<span class="sy0">=</span><span class="re2">TESTUSER,ou=USERS,OU=JUNK,OU=AK,DC=MYCOMPANY,DC=COM</span>
&nbsp;
# search result
search: <span class="nu0">2</span>
result: <span class="nu0">0</span> Success
&nbsp;
# numResponses: <span class="nu0">8</span>
# numEntries: <span class="nu0">7</span></pre></div></div>


<p>Connect as a valid user and ask for everything, but according to my ACLs the user can only see itself:
<pre>
ldapsearch -x -D uid=TESTUSER,ou=USERS,OU=JUNK,OU=AK,DC=MYCOMPANY,DC=COM -w testpass -s sub -b "ou=Junk,ou=AK,DC=mycompany,DC=com" "(objectClass=*)"
</pre></p>

<h4>Additional Considerations</h4>

<p><var>chkconfig</var> is the Red Hat tool for managing init scripts&#8211; here&#8217;s how to make sure the slapd starts at boot time.</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw2">sudo</span> chkconfig <span class="re5">--add</span> ldap
$ <span class="kw2">sudo</span> chkconfig ldap on</pre></div></div>


<p>Ah, Mr. Flat Mountain reminds,</p>

<blockquote>
9) Ports for the Firewall

LDAP runs on port 389/tcp by default and LDAP over SSL is 636/tcp.
</blockquote>

<p>Securing communication between the LDAP client and OpenLDAP server with SSL/TLS is beyond my scope here, but it seems to be much better documented.</p>

<p>Good luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2009/02/ldap-powered-by-mysql-on-rhel5/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Fix for slashes hosing Symfony URLs</title>
		<link>http://n8v.enteuxis.org/2009/02/fix-for-slashes-hosing-symfony-urls/</link>
		<comments>http://n8v.enteuxis.org/2009/02/fix-for-slashes-hosing-symfony-urls/#comments</comments>
		<pubDate>Tue, 03 Feb 2009 22:54:31 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=117</guid>
		<description><![CDATA[I found this information in this forum topic, &#8220;Slash in parameter&#8221; which references this ticket, but had snags and wanted to write it all up cleanly here.

The Problem

Sometimes a parameter in a GET string contains slashes, which are interpreted as file path delimeters by Apache and/or parameter name/value separators by Symfony.

So this URL works:
http://myapp/employee/bytitle/title/System+Engineer

But this [...]]]></description>
			<content:encoded><![CDATA[<p>I found this information in <a href="http://forum.symfony-project.org/index.php/m/41010/">this forum topic, &#8220;Slash in parameter&#8221;</a> which references <a href="http://trac.symfony-project.org/ticket/1482">this ticket</a>, but had snags and wanted to write it all up cleanly here.</p>

<h3>The Problem</h3>

<p>Sometimes a parameter in a GET string contains slashes, which are interpreted as file path delimeters by Apache and/or parameter name/value separators by Symfony.</p>

<p>So this URL works:
<samp>http://myapp/employee/bytitle/title/System+Engineer</samp></p>

<p>But this one returns a 404 (Page Not Found) error:
<samp>http://myapp/employee/bytitle/title/Programmer/analyst</samp></p>

<h4>Wrong solution</h4>

<p>Double-escaping the slash into &#8216;%252F&#8217; (e.g. <code>urlencode(str_replace('/', "%2f", $this-&gt;getTitle()))</code>) works <strong>if the URL isn&#8217;t rewritten by Apache</strong>.</p>

<p>This threw me because my URLs would work if they included the name of the controller file, <var>frontend_dev.php</var> or <var>backend.php</var> or even <var>index.php</var> like
<samp>http://myapp/<strong>index.php</strong>/employee/bytitle/title/Programmer%252Fanalyst</samp>,</p>

<p>but they wouldn&#8217;t work through the implicit, controllerless URLs  like
<samp>http://myapp/employee/bytitle/title/Programmer%252Fanalyst</samp></p>

<h3>Right solution</h3>

<p>Both</p>

<ol>
    <li>Turn on the <a href="http://httpd.apache.org/docs/2.2/en/mod/core.html#allowencodedslashes"><var>AllowEncodedSlashes</var> Apache directive</a> by adding this line to your server-wide section or the appropriate VirtualHost:
<pre> AllowEncodedSlashes On</pre>
<strong>AND</strong>,</li>
    <li><strong>DON&#8217;T</strong> double-escape the parameter as above, but do use <var>urlencode()</var> or equivalent to change slashes to <code>%2F</code>, eg. in the view layer,


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> link_to<span class="br0">&#40;</span>
    <span class="re0">$employee</span><span class="sy0">-&gt;</span><span class="me1">getTitle</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span>
    <span class="st_h">'/employee/bytitle?title='</span><span class="sy0">.</span>
    <a href="http://www.php.net/urlencode"><span class="kw3">urlencode</span></a><span class="br0">&#40;</span><span class="re0">$employee</span><span class="sy0">-&gt;</span><span class="me1">getTitle</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
<span class="br0">&#41;</span><span class="sy0">;</span>  <span class="sy1">?&gt;</span></pre></div></div>



</li>
</ol>

<h4>Additional Complication</h4>

<p>Browsers may treat the encoded slash in the URL differently.</p>

<p>IE 7, 8 and Firefox 3, and Safari 3.2.1 on Windows display the URL in the address bar with the %2F intact, as you&#8217;d expect.</p>

<p>In Google Chrome 1.0.154.43, the links work but the address bar displays a slash instead of the encoded %2F, so if you hit the &#8220;Go&#8221; button you get a 404 error.  Weird.  Bug submitted!</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2009/02/fix-for-slashes-hosing-symfony-urls/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Adding many-to-many tables to an existing symfony project</title>
		<link>http://n8v.enteuxis.org/2008/10/adding-many-to-many-tables-to-an-existing-symfony-project/</link>
		<comments>http://n8v.enteuxis.org/2008/10/adding-many-to-many-tables-to-an-existing-symfony-project/#comments</comments>
		<pubDate>Fri, 31 Oct 2008 00:31:28 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=92</guid>
		<description><![CDATA[ 

This is a symfony 1.0 project, but I think everything applies equally to 1.1, except the command syntax has changed from propel-load-data to propel:load-data

In this case, the application helps nurses collect and analyze data about how they&#8217;re administering intravenous therapies to their patients.  At first they wanted plain text lists of the IV drugs [...]]]></description>
			<content:encoded><![CDATA[<p> </p>

<p>This is a symfony 1.0 project, but I think everything applies equally to 1.1, except the command syntax has changed from <code>propel-load-data</code> to <code>propel:load-data</code></p>

<p>In this case, the application helps nurses collect and analyze data about how they&#8217;re administering intravenous therapies to their patients.  At first they wanted plain text lists of the IV drugs and fluids, but in order to filter based on them, we needed to change them to discreet fields.  In the View, it means changing a couple of fields from plain text to arrays of checkboxes.  In the Model, it means adding separate tables, and a &#8220;through class&#8221; associating the therapy with the new class.</p>

<p><span id="more-92"></span></p>

<h3>Changing the database schema and the generated object model</h3>

<p>The original design had only two classes/tables:  <code>Patients</code>, each having one or more <code>Therapies</code>.  Now, each <code>Therapy</code> can have 0 or more <code>Drugs</code> and <code>Fluids</code>.</p>

<p>First I added additional tables to my <var>schema.yml</var>, using the <a href="http://www.symfony-project.org/book/1_1/08-Inside-the-Model-Layer#Basic Schema Syntax">column naming conventions</a> so symfony will get the table relationships right:</p>


<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">  drug:
    id:
    name:             varchar(255)
    created_at:
    updated_at:
&nbsp;
  fluid:
    id:
    name:             varchar(255)
    created_at:
    updated_at:
&nbsp;
  therapy_drug:
    id:
    therapy_id:
    drug_id:
&nbsp;
  therapy_fluid:
    id:
    therapy_id:
    fluid_id:</pre></div></div>


<p>Propel will generate the table creation SQL:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">.<span class="sy0">/</span>symfony propel-build-sql</pre></div></div>


<p>But I don&#8217;t want to obliterate my existing data, so I cut the 4 <code>CREATE TABLE</code> statements for my 4 new tables out of <var>data/sql/lib.model.schema.sql</var> and put it in a file named <var>data/sql/create_drugs_fluids.sql</var> (and added it to Subversion with <code>svn add</code>)</p>

<p>Now I can feed that file to MySQL</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">mysql <span class="re5">-uroot</span> iv_log <span class="sy0">&lt;</span> data<span class="sy0">/</span>sql<span class="sy0">/</span>create_drugs_fluids.sql</pre></div></div>


<p>Next, I wrote a <a href="http://www.symfony-project.org/book/1_1/16-Application-Management-Tools#Populating a Database">fixture file</a> in YAML.</p>

<p>Then I have to clear the cache and rebuild the model in order to populate my new tables from the fixture, but I have all the objects ready to go!</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">.<span class="sy0">/</span>symfony <span class="kw2">cc</span>
.<span class="sy0">/</span>symfony propel-build-model
.<span class="sy0">/</span>symfony propel-load-data frontend</pre></div></div>


<h4>Nicer accessors in the Model</h4>

<p>Next I&#8217;ll do some work in the model layer to make things more convenient and logical for accessing the <code>Drug </code>and <code>Fluid </code>objects attached to each <code>Therapy</code>.</p>

<p>Add accessors to the Therapy model that return the array of through-class objects (TherapyDrug and TherapyFluid), for example in <var>lib/model/Therapy.php</var>:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">  <span class="kw2">public</span> <span class="kw2">function</span> getDrugs<span class="br0">&#40;</span><span class="re0">$criteria</span> <span class="sy0">=</span> <span class="kw2">null</span><span class="sy0">,</span> <span class="re0">$con</span> <span class="sy0">=</span> <span class="kw2">null</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="kw1">return</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getTherapyDrugsJoinDrug</span><span class="br0">&#40;</span><span class="re0">$criteria</span><span class="sy0">,</span> <span class="re0">$con</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span></pre></div></div>


<p>(and a similar <code>getFluids </code>method)</p>

<p>Make a list of through-class objects display like a list of the associated thing.  In <var>lib/model/TherapyDrug.php</var>:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">  <span class="kw2">public</span> <span class="kw2">function</span> __toString <span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="re0">$s</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getDrug</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
      <span class="kw1">return</span> <span class="re0">$s</span><span class="sy0">-&gt;</span>__toString<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>   <span class="co2"># i've had problems not doing this explicitly</span>
  <span class="br0">&#125;</span></pre></div></div>


<p>(and the same for <var>TherapyFluid.php</var>)</p>

<p>Now make sure the attached objects have a good <code>__toString()</code> method.  In <var>lib/model/Drug.php</var></p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co4">/**
 * Method __toString
 *
 *  @return    string   the drug name
 * @package lib.model
*/</span>
  <span class="kw2">public</span> <span class="kw2">function</span> __toString <span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="kw1">return</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span></pre></div></div>


<h3>Changing the Admin Generator GUI</h3>

<p>Now my database and model are all set, I need to make the new tables/objects available in the GUI.
I am using the Admin Generator for all the parts of the application.</p>

<p>First, I want them to be able to edit the list of drugs and fluids, so I build admin modules:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">.<span class="sy0">/</span>symfony propel-init-admin frontend drug Drug
.<span class="sy0">/</span>symfony propel-init-admin frontend fluid Fluid</pre></div></div>


<p>But I don&#8217;t want users to delete these values and leave orphaned rows in the related tables, or delete all related Therapy objects, so I&#8217;ll remove the &#8216;delete&#8217; ability in each new module&#8217;s config/generator.yml, for example, in <var>apps/frontend/modules/drug/config/generator.yml</var>,</p>


<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">generator:
  class:              sfPropelAdminGenerator
  param:
    model_class:      Drug
    theme:            default
    list:
      display:
        - =name
      object_actions:
         _edit:          ~
    edit:
      display:
        - name
      actions:
        _save:
          params:  confirm=This will affect all existing log records that use this drug, OK?
        _list:  -</pre></div></div>


<p>OK, now to add it to the Therapy object&#8217;s admin module.  I&#8217;m going to need it in three places:</p>

<ol>
    <li>The list view</li>
    <li>The edit form</li>
    <li>The filter list on the list view</li>
</ol>

<h4>List view</h4>

<p>In the list view, I unfortunately can&#8217;t just tell it to display the &#8220;drug&#8221; or &#8220;therapy_drug&#8221; column, because the Admin generator will print the results as &#8220;Array&#8221;.  So I make a <a href="http://www.symfony-project.org/book/1_1/07-Inside-the-View-Layer#Partials">partial</a> to display the list of related objects.  I&#8217;m going to use the same partial for list, edit and filter views using the $type variable <a href="http://www.symfony-project.org/book/1_1/14-Generators#Partial Fields">the admin generator provides</a> to tell them apart.</p>

<p>I define my partial in <var>apps/frontend/modules/therapy/templates/_drugs.php</var></p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">&lt;!--  begin _drugs partial for type '<span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$type</span> <span class="sy1">?&gt;</span>' --&gt;
<span class="kw2">&lt;?php</span> <span class="kw1">switch</span> <span class="br0">&#40;</span><span class="re0">$type</span><span class="br0">&#41;</span><span class="sy0">:</span>  <span class="sy1">?&gt;</span>
<span class="kw2">&lt;?php</span> <span class="kw1">case</span> <span class="st_h">'list'</span><span class="sy0">:</span> 
&nbsp;
<a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <a href="http://www.php.net/implode"><span class="kw3">implode</span></a><span class="br0">&#40;</span><span class="st_h">', '</span><span class="sy0">,</span> <span class="re0">$therapy</span><span class="sy0">-&gt;</span><span class="me1">getDrugs</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="sy1">?&gt;</span>
<span class="kw2">&lt;?php</span> <span class="kw1">break</span><span class="sy0">;</span> <span class="kw1">case</span> <span class="st_h">'edit'</span><span class="sy0">:</span>
&nbsp;
   <span class="co1">// this is handled by the admin generator</span>
&nbsp;
  <span class="sy1">?&gt;</span>
<span class="kw2">&lt;?php</span> <span class="kw1">break</span><span class="sy0">;</span> <span class="kw1">case</span> <span class="st_h">'filter'</span><span class="sy0">:</span>
   <span class="co1">// coming in a minute</span>
 <span class="sy1">?&gt;</span>
<span class="kw2">&lt;?php</span> <span class="kw1">break</span><span class="sy0">;</span> <span class="kw1">endswitch</span><span class="sy0">;</span>  <span class="sy1">?&gt;</span>
&lt;!--  end _drugs partial --&gt;</pre></div></div>


<div>(and do the same for a <var>_fluids.php</var> partial)</div>

<p>Now I just have to add the partials to the list of fields that display in list view, in</p>


<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">    list:
      fields:
        # ...
        - _drugs
        - _fluids</pre></div></div>


<p>And hooray!  My list of <code>Therapy </code>objects now displays their associated <code>Drug </code>and <code>Fluid </code>objects: </p>

<p><a href="http://n8v.enteuxis.org/wp-content/uploads/2008/10/list-view-works.png"><img class="alignnone size-full wp-image-100" title="list-view-works" src="http://n8v.enteuxis.org/wp-content/uploads/2008/10/list-view-works.png" alt="list-view-works" width="153" height="73" /></a>
 </p>

<h4>Edit view</h4>

<p>The edit view doesn&#8217;t really need the partial at this point, we can get a list of checkboxes in the edit form just by hacking the correct stuff into <var>apps/frontend/modules/therapy/config/generator.yml</var>:</p>


<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">  edit:
    display:
# ...
          - drug
          - fluid
&nbsp;
    fields:
# ...
        drug:
          name:  Drug(s)
          type:  admin_check_list
          params:  through_class=TherapyDrug
        fluid:
          name:  Fluid(s)
          type:  admin_check_list
          params:  through_class=TherapyFluid</pre></div></div>


<p>I had to make a little tweak to the <code>.sf_admin_checklist li</code> style in <var>web/css/main.css</var>, but now I have a nice set of working checkboxen!</p>

<p><a href="http://n8v.enteuxis.org/wp-content/uploads/2008/10/edit-view-works.png"><img src="http://n8v.enteuxis.org/wp-content/uploads/2008/10/edit-view-works.png" alt="edit-view-works" title="edit-view-works" width="243" height="183" class="alignnone size-full wp-image-101" /></a></p>

<h4>Filter view</h4>

<p>This will take two stages.  First I put this sort of thing in my <var>_drugs.php</var> and <var>_fluids.php</var> partials:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">&lt;?php</span> <span class="kw1">break</span><span class="sy0">;</span> <span class="kw1">case</span> <span class="st_h">'filter'</span><span class="sy0">:</span> 
&nbsp;
<span class="re0">$drugs</span> <span class="sy0">=</span> DrugPeer<span class="sy0">::</span><span class="me2">doSelect</span><span class="br0">&#40;</span><span class="kw2">new</span> Criteria<span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// get the list of all the possible drugs</span>
<a href="http://www.php.net/echo"><span class="kw3">echo</span></a> select_tag<span class="br0">&#40;</span><span class="st_h">'filters[drug]'</span><span class="sy0">,</span> 
  		  objects_for_select<span class="br0">&#40;</span>
				   <span class="re0">$drugs</span><span class="sy0">,</span> <span class="st_h">'getId'</span><span class="sy0">,</span> <span class="st_h">'getName'</span><span class="sy0">,</span> 
				   <a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span><span class="re0">$filters</span><span class="br0">&#91;</span><span class="st_h">'drug'</span><span class="br0">&#93;</span><span class="br0">&#41;</span> ? 
				     <span class="re0">$filters</span><span class="br0">&#91;</span><span class="st_h">'drug'</span><span class="br0">&#93;</span> <span class="sy0">:</span> <span class="st_h">''</span><span class="sy0">,</span>
				   <span class="st_h">'include_blank=true'</span><span class="br0">&#41;</span> 
		<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
 <span class="sy1">?&gt;</span></pre></div></div>


<p>and tell the Admin Generator to use the partials, back in <var>generator.yml</var>:</p>


<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">    list:
      # ...
      filters:
        # ...
        - _drugs
        - _fluids</pre></div></div>


<p>Now I have a nice widget in my filters box, but it doesn&#8217;t do anything quite yet:</p>

<p><a href="http://n8v.enteuxis.org/wp-content/uploads/2008/10/filter-view-works.png"><img src="http://n8v.enteuxis.org/wp-content/uploads/2008/10/filter-view-works.png" alt="filter-view-works" title="filter-view-works" width="258" height="141" class="alignnone size-full wp-image-102" /></a></p>

<p>To get it working I&#8217;ll need to help out the filter action, by extending the addFiltersCriteria action generated by the admin generator.  I will edit my copy in <var>apps/frontend/modules/therapy/actions/actions.class.php</var>:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">  protected <span class="kw2">function</span> addFiltersCriteria<span class="br0">&#40;</span><span class="re0">$c</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
&nbsp;
    <span class="kw1">if</span> <span class="br0">&#40;</span><a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">filters</span><span class="br0">&#91;</span><span class="st_h">'drug'</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">filters</span><span class="br0">&#91;</span><span class="st_h">'drug'</span><span class="br0">&#93;</span> <span class="sy0">!=</span> <span class="st_h">''</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
      <span class="re0">$c</span><span class="sy0">-&gt;</span><span class="me1">addJoin</span><span class="br0">&#40;</span> TherapyPeer<span class="sy0">::</span><span class="me2">ID</span><span class="sy0">,</span> TherapyDrugPeer<span class="sy0">::</span><span class="me2">THERAPY_ID</span><span class="sy0">,</span> Criteria<span class="sy0">::</span><span class="me2">LEFT_JOIN</span><span class="br0">&#41;</span><span class="sy0">;</span>
      <span class="re0">$c</span><span class="sy0">-&gt;</span><span class="me1">add</span><span class="br0">&#40;</span>TherapyDrugPeer<span class="sy0">::</span><span class="me2">DRUG_ID</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">filters</span><span class="br0">&#91;</span><span class="st_h">'drug'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw1">if</span> <span class="br0">&#40;</span><a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">filters</span><span class="br0">&#91;</span><span class="st_h">'fluid'</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">filters</span><span class="br0">&#91;</span><span class="st_h">'fluid'</span><span class="br0">&#93;</span> <span class="sy0">!=</span> <span class="st_h">''</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
      <span class="re0">$c</span><span class="sy0">-&gt;</span><span class="me1">addJoin</span><span class="br0">&#40;</span> TherapyPeer<span class="sy0">::</span><span class="me2">ID</span><span class="sy0">,</span> TherapyFluidPeer<span class="sy0">::</span><span class="me2">THERAPY_ID</span><span class="sy0">,</span> Criteria<span class="sy0">::</span><span class="me2">LEFT_JOIN</span><span class="br0">&#41;</span><span class="sy0">;</span>
      <span class="re0">$c</span><span class="sy0">-&gt;</span><span class="me1">add</span><span class="br0">&#40;</span>TherapyFluidPeer<span class="sy0">::</span><span class="me2">FLUID_ID</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">filters</span><span class="br0">&#91;</span><span class="st_h">'fluid'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw1">return</span> parent<span class="sy0">::</span><span class="me2">addFiltersCriteria</span><span class="br0">&#40;</span><span class="re0">$c</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span></pre></div></div>


<p>Now the action will add additional constraining filter criteria before displaying the list of Therapy objects, if the filters have been set.  That will let the user search for only records with a particular combination of values, for example.</p>

<p>Whew, that got a little bit involved but I&#8217;m sure it will be easier next time.</p>

<p>The big breakthrough for me learning how to work with the admin generator was when I realized that it generates all its files in the cache directory, so you can look in the cache at how it&#8217;s doing everything, and override as necessary with partials and actions when you run past what you can do with <var>generator.yml</var>.</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2008/10/adding-many-to-many-tables-to-an-existing-symfony-project/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Adding Subversion keywords to an entire Symfony project</title>
		<link>http://n8v.enteuxis.org/2008/10/adding-subversion-keywords-to-an-entire-symfony-project/</link>
		<comments>http://n8v.enteuxis.org/2008/10/adding-subversion-keywords-to-an-entire-symfony-project/#comments</comments>
		<pubDate>Tue, 07 Oct 2008 19:07:14 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=90</guid>
		<description><![CDATA[For some reason, even though I&#8217;ve set default properties in my .subversion/config, it doesn&#8217;t always apply to new files, so I end up doing this once in a while:


svn propset svn:keywords 'Id Rev URL HeadUrl' \
`find apps/ config/ doc/ lib/ web data/ test/ \
-name '*.php' -or -name '*.yml' -or -name '*.css' -or -name '*.sql'`


This tells [...]]]></description>
			<content:encoded><![CDATA[<p>For some reason, even though I&#8217;ve set default properties in my <var>.subversion/config</var>, it doesn&#8217;t always apply to new files, so I end up doing this once in a while:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">svn</span> propset <span class="kw2">svn</span>:keywords <span class="st_h">'Id Rev URL HeadUrl'</span> \
<span class="sy0">`</span><span class="kw2">find</span> apps<span class="sy0">/</span> config<span class="sy0">/</span> doc<span class="sy0">/</span> lib<span class="sy0">/</span> web data<span class="sy0">/</span> <span class="kw3">test</span><span class="sy0">/</span> \
<span class="re5">-name</span> <span class="st_h">'*.php'</span> <span class="re5">-or</span> <span class="re5">-name</span> <span class="st_h">'*.yml'</span> <span class="re5">-or</span> <span class="re5">-name</span> <span class="st_h">'*.css'</span> <span class="re5">-or</span> <span class="re5">-name</span> <span class="st_h">'*.sql'</span><span class="sy0">`</span></pre></div></div>


<p>This tells Subversion to go into those types of files and update <a href="http://svnbook.red-bean.com/en/1.4/svn.advanced.props.special.keywords.html">the <code>$Id$</code> and other keyword tags</a>.</p>

<p>(Note, I&#8217;ve been fooled before by not noticing the keywords are CASE-SENSITIVE.  If you set them to &#8216;id rev url headURL&#8217; they will NOT work!)</p>

<p>It works with <a href="http://cygwin.com">Cygwin</a>, if you&#8217;re stuck in Windowsland like I am for local development.</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2008/10/adding-subversion-keywords-to-an-entire-symfony-project/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Upgrading sfGuardPlugin for symfony 1.1</title>
		<link>http://n8v.enteuxis.org/2008/08/upgrading-sfguardplugin-for-symfony-11/</link>
		<comments>http://n8v.enteuxis.org/2008/08/upgrading-sfguardplugin-for-symfony-11/#comments</comments>
		<pubDate>Tue, 19 Aug 2008 21:27:20 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=44</guid>
		<description><![CDATA[Last week I upgraded my first symfony 1.0 project to symfony 1.1 following the
UPGRADE file that comes with symfony 1.1

The first part of the upgrade went pretty smoothly, but my project broke due to the sfGuardPlugin.  There weren&#8217;t any details about plugins in the UPGRADE doc, and removing and reinstalling it didn&#8217;t work for [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I upgraded my first symfony 1.0 project to <a href="http://www.symfony-project.org/blog/2008/06/30/the-wait-is-over-symfony-1-1-released">symfony 1.1</a> following the
<a href="http://trac.symfony-project.com/browser/branches/1.1/UPGRADE">UPGRADE</a> file that comes with symfony 1.1</p>

<p>The first part of the upgrade went pretty smoothly, but my project broke due to the sfGuardPlugin.  There weren&#8217;t any details about plugins in the UPGRADE doc, and removing and reinstalling it didn&#8217;t work for me.</p>

<p>However, this week, with <a href="http://www.symfony-project.org/forum/index.php/m/58542/#msg_num_6">the help of some friendly symfony forum users</a>, this procedure finally worked for me:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">svn</span> <span class="kw2">rm</span> plugins<span class="sy0">/</span>sfGuardPlugin
<span class="kw2">svn</span> ci plugins<span class="sy0">/</span>sfGuardPlugin <span class="re5">-m</span> <span class="st_h">'removed old version of sfGuardPlugin'</span>
<span class="kw2">rm</span> <span class="re5">-rf</span> plugins<span class="sy0">/</span>sfGuardPlugin plugins<span class="sy0">/</span>.channels plugins<span class="sy0">/</span>.depdb plugins<span class="sy0">/</span>.depdblock plugins<span class="sy0">/</span>.filemap plugins<span class="sy0">/</span>.lock plugins<span class="sy0">/</span>.registry<span class="sy0">/</span>
<span class="kw2">rm</span> <span class="re5">-rf</span> cache<span class="sy0">/</span>.pear
.<span class="sy0">/</span>symfony plugin:<span class="kw2">install</span> sfGuardPlugin
<span class="kw2">svn</span> add plugins<span class="sy0">/</span>sfGuardPlugin<span class="sy0">/</span></pre></div></div>


<p>my successful plugin installation looked like this:
<pre>
$  <kbd>./symfony plugin:install sfGuardPlugin</kbd>
&gt;&gt; plugin    installing plugin "sfGuardPlugin"
&gt;&gt; sfPearFrontendPlugin Attempting to discover channel "pear.symfony-project.com"...
&gt;&gt; sfPearFrontendPlugin downloading channel.xml ...
&gt;&gt; sfPearFrontendPlugin Starting to download channel.xml (663 bytes)
&gt;&gt; sfPearFrontendPlugin .
&gt;&gt; sfPearFrontendPlugin ...done: 663 bytes
&gt;&gt; sfPearFrontendPlugin Auto-discovered channel "pear.symfony-project.com", alias
&gt;&gt; sfPearFrontendPlugin "symfony", adding to registry
&gt;&gt; sfPearFrontendPlugin Attempting to discover channel
&gt;&gt; sfPearFrontendPlugin "plugins.symfony-project.org"...
&gt;&gt; sfPearFrontendPlugin downloading channel.xml ...
&gt;&gt; sfPearFrontendPlugin Starting to download channel.xml (639 bytes)
&gt;&gt; sfPearFrontendPlugin ...done: 639 bytes
&gt;&gt; sfPearFrontendPlugin Auto-discovered channel "plugins.symfony-project.org", alias
&gt;&gt; sfPearFrontendPlugin "symfony-plugins", adding to registry
&gt;&gt; sfPearFrontendPlugin downloading sfGuardPlugin-2.2.0.tgz ...
&gt;&gt; sfPearFrontendPlugin Starting to download sfGuardPlugin-2.2.0.tgz (18,589 bytes)
&gt;&gt; sfPearFrontendPlugin ...done: 18,589 bytes
&gt;&gt; sfPearFrontendPlugin Failed to download symfony/symfony (version &gt;= 1.1.0, version
&gt;&gt; sfPearFrontendPlugin &lt;= 1.2.0, excluded versions: 1.2.0), latest release is version
&gt;&gt; sfPearFrontendPlugin 1.1.1, stability "stable", use
&gt;&gt; sfPearFrontendPlugin "channel://pear.symfony-project.com/symfony-1.1.1" to install
&gt;&gt; sfSymfonyPluginManager Installation successful for plugin "sfGuardPlugin"
</pre></p>

<p>Then I did the first couple of steps from the install again to get it working:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ symfony propel:build-model
$ symfony propel:build-sql
$ symfony <span class="kw2">cc</span></pre></div></div>


<p>But grrr&#8230; my customized authentication and signin forms are hosing it up.  Time to learn more about the new release I guess.</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2008/08/upgrading-sfguardplugin-for-symfony-11/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The intranets!  Let them in!  Let them play!</title>
		<link>http://n8v.enteuxis.org/2008/08/ldap-authn-authz-for-symfony/</link>
		<comments>http://n8v.enteuxis.org/2008/08/ldap-authn-authz-for-symfony/#comments</comments>
		<pubDate>Tue, 05 Aug 2008 18:49:04 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Giving back]]></category>
		<category><![CDATA[AD]]></category>
		<category><![CDATA[intranet]]></category>
		<category><![CDATA[LDAP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=32</guid>
		<description><![CDATA[I just released bhLDAPAuthPlugin to the world with permission from my employer.  I&#8217;ve been using symfony (&#8220;PHP on Rails&#8221;) for about a year at work for a few intranet projects, and over and over I have needed to use our enterprise-wide Microsoft Active Directory® for user authentication and authorization. The plugin might work with non-Microsoft [...]]]></description>
			<content:encoded><![CDATA[<p>I just released <a href="http://www.symfony-project.org/plugins/bhLDAPAuthPlugin">bhLDAPAuthPlugin</a> to the world with permission from my employer.  I&#8217;ve been using <a href="http://www.symfony-project.org/">symfony</a> (&#8220;PHP on Rails&#8221;) for about a year at work for a few intranet projects, and over and over I have needed to use our enterprise-wide Microsoft Active Directory® for user authentication and authorization. The plugin might work with non-Microsoft LDAP servers too, but I don&#8217;t have any of them to play with.</p>

<p>Maybe this will help other developers cook up Intranet apps that rock using symfony.</p>

<p>I have been able to rapidly develop some things that users really like with symfony, so I appreciate this chance to give back to the project.  Also, I&#8217;m the only one in my organization doing this sort of thing, so I hope I&#8217;ll be able to get some good feedback and contributions from others.</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2008/08/ldap-authn-authz-for-symfony/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
