<?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>A.J. Brown&#039;s Blog &#187; Autoload</title> <atom:link href="http://ajbrown.org/blog/tags/autoload/feed" rel="self" type="application/rss+xml" /><link>http://ajbrown.org/blog</link> <description>Coding adventures and technology musing for the masses</description> <lastBuildDate>Fri, 26 Mar 2010 17:57:50 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.0.1</generator> <item><title>An Auto Loader Using PHP Tokenizer</title><link>http://ajbrown.org/blog/2008/12/02/an-auto-loader-using-php-tokenizer.html</link> <comments>http://ajbrown.org/blog/2008/12/02/an-auto-loader-using-php-tokenizer.html#comments</comments> <pubDate>Wed, 03 Dec 2008 05:07:08 +0000</pubDate> <dc:creator>A.J. Brown</dc:creator> <category><![CDATA[PHP]]></category> <category><![CDATA[Autoload]]></category><guid isPermaLink="false">http://ajbrown.org/blog/?p=14</guid> <description><![CDATA[Although adding some overhead to your application, using an autoloader instead of directly requiring files will increase the flexibility of your application. With an autoloader, you can move files around in your project as you please, without breaking dependent code. It's also much more convenient for the developer, who no longer needs to know the exact location (or version) of a needed file.Using an autoloader instead of directly requiring files will help keep your code decoupled. This is especially useful for writing unit-testable code by allowing you to mock dependent objects, and prevent unnecessary code from being run.]]></description> <content:encoded><![CDATA[<h3 id="toc-what-is-an-auto-loader">What is an Auto Loader?</h3><p>In PHP, an auto loader is a set of code that's responsible for "loading" a class that is needed for some piece of code (if it has not already been loaded).  Typically it uses some formula or pre-determined list to figure out what file needs to be included in order for the class to be defined.  In most applications the filename is determined by examining the class name.</p><h3 id="toc-why-auto-load-instead-of-using-includes">Why Auto Load instead of using includes?</h3><p>Although adding some overhead to your application, using an autoloader instead of directly requiring files will increase the flexibility of your application.  With an autoloader, you can move files around in your project as you please, without breaking dependent code.  It's also much more convenient for the developer, who no longer needs to know the exact location (or version) of a needed file.</p><p>Using an autoloader instead of directly requiring files will help keep your code decoupled.  This is especially useful for writing unit-testable code by allowing you to mock dependent objects, and prevent unnecessary code from being run.</p><h3 id="toc-our-class-file-mapping-package">Our Class File Mapping Package</h3><p>The class file map factory is responsible for scanning the files of a specified directory, indexing the classes and interfaces contained within those files, and generating a <code>ClassFileMap</code> object to represent the index.  Each <code>ClassFileMap</code> is then used by a <code>ClassFileMapAutloader</code> to lookup the needed class.</p><p>To load the files we want to index, we're using SPL's<cite><a href="http://www.php.net/~helly/php/ext/spl/classRecursiveDirectoryIterator.html" rev="vote-for">RecursiveDirectoryIterator</a> and</cite><cite><a href="http://www.php.net/~helly/php/ext/spl/classRecursiveIteratorIterator.html" rev="vote-for">RecursiveIteratorIterator</a></cite>.  Explaining those classes is outside the scope of this article.</p><p>The auto loader I wrote uses the<cite><a href="http://us.php.net/manual/en/ref.tokenizer.php">tokenizer</a></cite>'s<cite><a href="http://us.php.net/manual/en/function.token-get-all.php">token_get_all</a></cite>, which returns an array of tokens within a given source string.  Tokens describe the relevance of a sequence of characters in PHP source, such as `whitespace`, `class`, `function`, `bracket`, etc.  Once our file has been tokenized, we just look for all `class` and `interface` tokens, and look at the next non-whitespace token to select the class name.</p><h3 id="toc-class-file-map-factory">Class File Map Factory</h3><div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Class to handle generating the class file map, and loading of classes
 *
 * @author A.J. Brown
 * @package com.hypermuttlabs
 * @subpackage packaging
 */</span>
abstract <span style="color: #000000; font-weight: bold;">class</span> ClassFileMapFactory
<span style="color: #009900;">&#123;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * Generates a class file map instance for the specified class path
  *
  * @param string $sClassPath the path to analyze
  * @param string $sName      the name for this class file map
  * @return ClassFileMap
  */</span>
 <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> generate<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sClassPath</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sName</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span> <span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$aClassMap</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span>_getClassFileMapArray<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sClassPath</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$oClassfileMap</span> <span style="color: #339933;">=</span>  <span style="color: #000000; font-weight: bold;">new</span> ClassFileMap<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sName</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$oClassfileMap</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setClassPath</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$aClassMap</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #000088;">$oClassfileMap</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * Generates a class file map for the specified directory
  *
  * @return array
  */</span>
 <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000000; font-weight: bold;">function</span> _getClassFileMapArray<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sDirectory</span><span style="color: #339933;">,</span> <span style="color: #000088;">$bRecursive</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span> <span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #990000;">is_dir</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sDirectory</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
   throw <span style="color: #000000; font-weight: bold;">new</span> AppException<span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'The specified location is not a directory'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #990000;">is_readable</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sDirectory</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
   throw <span style="color: #000000; font-weight: bold;">new</span> AppException<span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'The path `'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$sDirectory</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'` is not readable'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000088;">$sPath</span> <span style="color: #339933;">=</span> <span style="color: #990000;">realpath</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sDirectory</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000088;">$oFiles</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> RecursiveIteratorIterator<span style="color: #009900;">&#40;</span>
   <span style="color: #000000; font-weight: bold;">new</span> RecursiveDirectoryIterator<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sPath</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
   <span style="color: #000088;">$bRecursive</span> ? RecursiveIteratorIterator<span style="color: #339933;">::</span><span style="color: #004000;">SELF_FIRST</span> <span style="color: #339933;">:</span> <span style="color: #009900; font-weight: bold;">null</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000088;">$sHiddenFiles</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'/\/\.\w+/'</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">//------------------------------------------</span>
  <span style="color: #666666; font-style: italic;">// Load the list of files in the directory</span>
  <span style="color: #666666; font-style: italic;">//------------------------------------------</span>
  <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$oFiles</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$sName</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$aFile</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
   <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sHiddenFiles</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sName</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span><span style="color: #000088;">$aFile</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isDir</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
   <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$oFile</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$aFile</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">openFile</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$sContents</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #000088;">$oFile</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">eof</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
     <span style="color: #000088;">$sContents</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$oFile</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fgets</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//----------------------------------------</span>
    <span style="color: #666666; font-style: italic;">// Tokenize the source and grab the classes</span>
    <span style="color: #666666; font-style: italic;">// and interfaces</span>
    <span style="color: #666666; font-style: italic;">//----------------------------------------</span>
    <span style="color: #000088;">$aTokens</span> <span style="color: #339933;">=</span> <span style="color: #990000;">token_get_all</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sContents</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$iNumtokens</span> <span style="color: #339933;">=</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$aTokens</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$iNumtokens</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
&nbsp;
     <span style="color: #b1b100;">switch</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$aTokens</span><span style="color: #009900;">&#91;</span> <span style="color: #000088;">$i</span> <span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span> <span style="color: #cc66cc;">0</span> <span style="color: #009900;">&#93;</span>  <span style="color: #009900;">&#41;</span>
     <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">case</span> T_CLASS<span style="color: #339933;">:</span>
      <span style="color: #b1b100;">case</span> T_INTERFACE<span style="color: #339933;">:</span>
       <span style="color: #000088;">$i</span> <span style="color: #339933;">+=</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//skip the whitespace token</span>
       <span style="color: #000088;">$aDeclarations</span><span style="color: #009900;">&#91;</span> <span style="color: #000088;">$aTokens</span><span style="color: #009900;">&#91;</span> <span style="color: #000088;">$i</span> <span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$sName</span><span style="color: #339933;">;</span>
       <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
     <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
   <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">return</span> <span style="color: #000088;">$aDeclarations</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div><p>You'll notice we're using a regex to check the directory name of our files before processing them.  This prevents hidden folders (such as .svn) from being processed, which will both reduce overhead, and prevent diff and history files from being scanned.</p><h3 id="toc-class-file-map-autoloader">Class File Map Autoloader</h3><p>The <code>ClassFileMapAutoloader</code> is used by PHP to locate classes which have not yet been defined.  It must be added to the autoload stack using<cite><a href="http://us.php.net/manual/en/function.spl-autoload-register.php">spl_autoload_register</a></cite> by calling it's <code>registerAutload()</code> method.  Once registered, it will use all attached <code>ClassFileMaps</code> to lookup class names and require their files.</p> </pre><div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Autoloads classes using class file maps
 *
 * @author A.J. Brown
 * @package com.hypermuttlabs
 * @subpackage packaging
 *
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> ClassFileMapAutoloader
<span style="color: #009900;">&#123;</span>
 <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_aClassFileMaps</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * Adds a class file map for use by this autoloader.  ClassFileMaps are grouped
  * by their name if the second parameter is true, resulting in a second
  * class file with the same name overwriting the first.
  *
  * @param ClassFileMap $oClassFileMap
  * @param bool $bUseName use the value of {@link ClassFileMap::getName()}
  *  as the key
  *
  * @return void
  */</span>
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> addClassFileMap<span style="color: #009900;">&#40;</span> ClassFileMap <span style="color: #000088;">$oClassFileMap</span><span style="color: #339933;">,</span> <span style="color: #000088;">$bUseName</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span> <span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$bUseName</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
   <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_aClassFileMaps<span style="color: #009900;">&#91;</span> <span style="color: #000088;">$oClassFileMap</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$oClassFileMap</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #b1b100;">else</span>
  <span style="color: #009900;">&#123;</span>
   <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_aClassFileMaps<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$oClassFileMap</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * Registers this class with the spl autloader stack.
  *
  * @return bool
  */</span>
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> registerAutoload<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #990000;">spl_autoload_register</span><span style="color: #009900;">&#40;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'autoload'</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * Autloads classes, if they can be found in the class file maps associated
  * with this autoloader.
  *
  * @param string $sClass
  * @return string the class name if found, otherwise false
  */</span>
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> autoload<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sClass</span> <span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #990000;">class_exists</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sClass</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> interface_exists<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sClass</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
   <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000088;">$sPath</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_doLookup<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sClass</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sPath</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">null</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
   <span style="color: #b1b100;">require_once</span> <span style="color: #000088;">$sPath</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * Loop through class files maps untill a match is found
  *
  * @param string $sClassName
  * @return string the path of the class, or null if not found
  */</span>
 <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> _doLookup<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sClassName</span> <span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_aClassFileMaps <span style="color: #b1b100;">as</span> <span style="color: #000088;">$oClassFileMap</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
   <span style="color: #000088;">$sPath</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$oClassFileMap</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lookup</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sClassName</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #990000;">is_null</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sPath</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
   <span style="color: #b1b100;">return</span> <span style="color: #000088;">$sPath</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div><h3 id="toc-class-file-map">Class File Map</h3><p>The <code>ClassFileMap</code> represents an index of php files of a specific location, allowing the <code>ClassFileMapAutoloader</code> to determine a filename from a class name.</p><div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Manages a map of class names to their paths
 *
 * @author A.J. Brown
 * @package com.hypermuttlabs
 * @subpackage packaging
 *
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> ClassFileMap
<span style="color: #009900;">&#123;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * @var array
  */</span>
 <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_aClassMap</span><span style="color: #339933;">;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * Stores a name for this class file map.  For user usage.
  * @var string
  */</span>
 <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_sName</span><span style="color: #339933;">;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * Stores the timestamp of this class file map's creation.
  * @var int
  */</span>
 <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_iCreated</span><span style="color: #339933;">;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * Constructor
  *
  * @param string $sName an optional name to give this class file map.
  */</span>
 <span style="color: #000000; font-weight: bold;">function</span> __construct <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sName</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span> <span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_iCreated <span style="color: #339933;">=</span> <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_sName <span style="color: #339933;">=</span> <span style="color: #000088;">$sName</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * Maps the specified class to the specified path. If the first argument
  * is an array, it is expected that the array contains name-value pairs
  * of class names and thier paths.
  *
  * @param string|array  $mClassName the class name to map
  * @param string   $sPath the path to map to
  *
  * @return void
  */</span>
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setClassPath<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$mClassName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sPath</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span> <span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$mClassName</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
   <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$mClassName</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$sClassName</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$sPath</span> <span style="color: #009900;">&#41;</span>
   <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setClassPath</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sClassName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sPath</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #009900;">&#125;</span>
&nbsp;
   <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_aClassMap<span style="color: #009900;">&#91;</span> <span style="color: #000088;">$mClassName</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$sPath</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * Retreives the name of this class
  *
  * @return string
  */</span>
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getName<span style="color: #009900;">&#40;</span>  <span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_sName<span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * Determine if a class is mapped
  *
  * @param string $sClassName
  * @return boolean true if the class is mapped
  */</span>
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> isMapped<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sClassName</span> <span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_aClassMap<span style="color: #009900;">&#91;</span> <span style="color: #000088;">$sClassName</span> <span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * Returns the path of the file if mapped, otherwise null
  *
  * @param  string  $sClassName the class to lookup
  * @return  string the full path to the file containing the class
  */</span>
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> lookup<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sClassName</span> <span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isMapped</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sClassName</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_aClassMap<span style="color: #009900;">&#91;</span> <span style="color: #000088;">$sClassName</span> <span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * Returns an array of classes which exist within a given file path
  *
  * @param unknown_type $sFileName
  * @return unknown
  */</span>
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getClassesInFile<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$sFileName</span> <span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_aClassMap<span style="color: #339933;">,</span> <span style="color: #000088;">$sFileName</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
 <span style="color: #009933; font-style: italic;">/**
  * Retreives the entire class-file map as an array with class names as keys
  * and their paths as values
  *
  */</span>
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getClassMap<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_aClassMap
 <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div><h3 id="toc-usage-example">Usage Example</h3><div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//build a class file map for our applications classes</span>
<span style="color: #000088;">$oAppClassFileMap</span> <span style="color: #339933;">=</span> ClassFileMapFactory<span style="color: #339933;">::</span><span style="color: #004000;">generate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/path/to/class/files'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//instanciate a new auto loader</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_oAutoLoader <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ClassFileMapAutoloader<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//add the class file map to the autoloader</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_oAutoLoader<span style="color: #339933;">-&gt;</span><span style="color: #004000;">addClassFileMap</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$oAppClassFileMap</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//register the autoloader</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_oAutoLoader<span style="color: #339933;">-&gt;</span><span style="color: #004000;">registerAutoload</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>And that's all there is to it.  Once this code has been executed in your application, no further requires will be needed.  We do add a slight overhead to the application, but the increased flexibility and modularity is well worth it, especially for larger applications.</p><p>Feel free to use the autoloader in this article in your own projects.</p> ]]></content:encoded> <wfw:commentRss>http://ajbrown.org/blog/2008/12/02/an-auto-loader-using-php-tokenizer.html/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>
