<?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>Jacob Kiers &#187; Annabel</title> <atom:link href="http://jacobkiers.net/category/work/annabel-work/feed/" rel="self" type="application/rss+xml" /><link>http://jacobkiers.net</link> <description>Some things I want to share</description> <lastBuildDate>Fri, 11 Feb 2011 08:53:09 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <item><title>How To Dynamically Instantiate Classes In PHP</title><link>http://jacobkiers.net/2009/03/10/how-to-dynamically-instantiate-classes-in-php/</link> <comments>http://jacobkiers.net/2009/03/10/how-to-dynamically-instantiate-classes-in-php/#comments</comments> <pubDate>Tue, 10 Mar 2009 13:32:03 +0000</pubDate> <dc:creator>Jacob Kiers</dc:creator> <category><![CDATA[Annabel]]></category> <category><![CDATA[Work]]></category> <category><![CDATA[code]]></category> <category><![CDATA[development]]></category> <category><![CDATA[php]]></category><guid isPermaLink="false">http://blog.jacobkiers.net/?p=70</guid> <description><![CDATA[For Annabel, I need to be able to dynamically instantiate classes, based on options in a configuration file (Zend_Config_Ini). However, some of these classes have constructors (some with required options), others don&#8217;t even have a constructor. I first tried to instantiate them with call_user_func_array, like this: This didn&#8217;t work, since some classes don&#8217;t have a [...]]]></description> <content:encoded><![CDATA[<p>For Annabel, I need to be able to dynamically instantiate classes, based on options in a configuration file (Zend_Config_Ini). However, some of these classes have constructors (some with required options), others don&#8217;t even have a constructor. I first tried to instantiate them with <a href="http://www.php.net/call_user_func_array"title="PHP function: call_user_func_array" >call_user_func_array</a>, like this:</p><pre class="brush: php; title: ; notranslate">
$datatype_options = explode(',', $global_config-&gt;customer-&gt;data-&gt;field-&gt;$key-&gt;type);
$datatype_class = array_shift($datatype_options);
$class = call_user_func_array(array($datatype_class, '__construct'), $datatype_options);
</pre><p>This didn&#8217;t work, since some classes don&#8217;t have a constructor and they were not static. Then, I came up with another solution: use a generic static method getInstance() to do it, like this:</p><pre class="brush: php; title: ; notranslate">
class Test {
	public static function getInstance($classname)
	{
		return new $classname();
	}
}

$datatype_options = explode(',', $global_config-&gt;customer-&gt;data-&gt;field-&gt;$key-&gt;type);
$datatype_class = array_shift($datatype_options);
$class = call_user_func_array(array('Test', 'getInstance'), $datatype_options);
</pre><p>This worked, as long as I don&#8217;t need any constructor parameters. But for some classes, I do need them. So I went thinking, and came to the conclusion that I would need the Reflection API to do what I want. Finally, I implemented the following solution, which works perfectly. It could probably be cleaned up a little bit, but it basically works:</p><pre class="brush: php; title: ; notranslate">
class Annabel_Data
{
    /**
     * Creates instances of classes in the Annabel_Data package.
     *
     * To use this, provide arguments in the order you would need them
     * in the instantiated classes, with as the first argument the name
     * of the class to instantiate.
     *
     * @param $arguments An array with arguments
     *
     * @return Annabel_Data_Abstract
     */
    public static function factory($arguments)
    {
        $class_name = array_shift($arguments);
        $class_name = 'Annabel_Data_' . ucfirst($class_name);
        Zend_Loader::loadClass($class_name);
        $reflector = new ReflectionClass($class_name);
        if ($reflector-&gt;isInstantiable()) {
            $constructor = $reflector-&gt;getConstructor();
            if (is_null($constructor)) {
                return $reflector-&gt;newInstance();
            }
            $params = $constructor-&gt;getNumberOfParameters();
            $req_params = $constructor-&gt;getNumberOfRequiredParameters();
            if (count($arguments) &lt; $req_params) {
                throw new Annabel_Data_Exception('Please provide ' . $req_params . ' parameters to instantiate class ' . $class_name);
            }
            if (0 &lt; $params) {
                return $reflector-&gt;newInstanceArgs($arguments);
            } else {
                return $reflector-&gt;newInstance();
            }
        } else {
            throw new Annabel_Data_Exception(&quot;Could not instantiate a class of type '&quot; . $class_name . &quot;'&quot;);
        }
    }
}

$datatype_options = explode(',', $global_config-&gt;customer-&gt;data-&gt;field-&gt;$key-&gt;type);
$class = Annabel_Data::factory($datatype_options);
</pre><p>This works perfectly, for each case I need it (and tested it ;)). I should add some more exception checking and things like that, but those are minor details.<br /> Oh, and last but not least, some credits go the commenters over at the <a href="http://www.php.net/manual/en/language.oop5.reflection.php"title="PHP Reflection API" >PHP Reflection API documentation</a>.</p> ]]></content:encoded> <wfw:commentRss>http://jacobkiers.net/2009/03/10/how-to-dynamically-instantiate-classes-in-php/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>40x Speedup With iconv And PHP</title><link>http://jacobkiers.net/2009/03/03/40x-speedup-with-iconv-and-php/</link> <comments>http://jacobkiers.net/2009/03/03/40x-speedup-with-iconv-and-php/#comments</comments> <pubDate>Tue, 03 Mar 2009 13:04:54 +0000</pubDate> <dc:creator>Jacob Kiers</dc:creator> <category><![CDATA[Annabel]]></category> <category><![CDATA[Development]]></category> <category><![CDATA[Personal]]></category> <category><![CDATA[Work]]></category> <category><![CDATA[code]]></category> <category><![CDATA[development]]></category> <category><![CDATA[php]]></category><guid isPermaLink="false">http://blog.jacobkiers.net/?p=64</guid> <description><![CDATA[For our product Annabel (dutch), we have to cleanup the data our customers provide us with. Because this is a fully automated process, we are unable to give feedback and have them fix their input. Therefore, I need a means to clean the data up, so we can process it. Since we don&#8217;t need to [...]]]></description> <content:encoded><![CDATA[<p>For our product <a href="http://www.ac-outbound.nl/"title="Annabel - Alphacomm Outbound Solutions" >Annabel (dutch)</a>, we have to cleanup the data our customers provide us with. Because this is a fully automated process, we are unable to give feedback and have them fix their input. Therefore, I need a means to clean the data up, so we can process it.</p><p>Since we don&#8217;t need to support any unicode stuff, we can stick with just plain ASCII. That&#8217;s a very safe approach, which will reduce the chances of failure greatly. To convert the UTF-8 (Unicode) input into ASCII data, we use <a href="http://www.gnu.org/software/libtool/manual/libc/index.html"title="GNU C Library" >GNU C Library</a> <a href="http://www.gnu.org/software/libtool/manual/libc/Generic-Charset-Conversion.html#Generic-Charset-Conversion"title="GNU C Library Charset Conversion (iconv)" >iconv</a> in combination with PHP.</p><p>The default iconv has two caveats: it stops on an unconvertible string and it prints a question mark when it does not have an equivalent character (or transliterated character) in the destination charset. To overcome this problem, I used to just convert every single character with the PHP <a href="http://php.net/iconv"title="PHP iconv" > iconv</a> function, which gave me a throughput of about 250KiB/sec, using the following code:</p><pre class="brush: php; title: ; notranslate">
/**
*  Replaces special characters with their ASCII equivalents.
*
* This function uses iconv to replace each seperate character with its
* ASCII equivalent, using the ASCII//TRANSLIT option. However, this makes
* the function very slow: max throughput is about 150KiB/sec.
*
* @param string $line
* @return string
*/
protected function _convertSpecialChars($line) {
if (!empty($line)) {
$new_line = &quot;&quot;;

/*
* This potentially could be a very long string, so don't split the line
* in separate tokens, for that would tak way too much memory.
*/
$line_length = strlen($line);
for ($x=0; $x &lt; $line_length; $x++) {
$old_char = substr($line, $x, 1);

/*
* Use iconv to replace the other special characters.
* If iconv can't convert it (and so returns '?'), just skip
* the character, for it probably is something malicious and
* there's probably no need to keep it anyway.
*
* Beware for the edge case if the original character is ? also
*/
$char = iconv('UTF-8', 'ASCII//TRANSLIT', $old_char);
if ( ('?' != $char) &amp;&amp; ('?' != $old_char) ) $new_line .= $char;
}
}

return $new_line;
}
</pre><p>However, I was not satisfied with this, so I looked up the man page of the iconv version of GNU C Library. I supposed PHP was internally using this one, so that seemed a natural action. In that man-page I foud the IGNORE option, which just skips any character which cannot be converted or transliterated. That was exactly what I wanted. So I tried that with the PHP function as well, and it worked. Instead of converting every single character, I can now convert a whole file at once, which gave me a throughput of 11MiB/sec. The caveat, of course, is that I have to use the GNU C Library iconv, with a version the same (or greater than) the current one, to avoid compatibility problems. However, that&#8217;s a price I&#8217;m surely willing to pay. The new code is this (removed proprietary Annabel specific code):</p><pre class="brush: php; title: ; notranslate">
/**
*  Replaces special characters with their ASCII equivalents.
*
* This function uses iconv to replace each seperate character with its
* ASCII equivalent, using the ASCII//TRANSLIT,IGNORE option. Throughput
* is measured at about 11MiB/sec.
*
* WARNING: Using the extra IGNORE option only works with a recent
* GNU libc iconv, so be very picky about which iconv to use! This is an
* undocumented feature, which is not supported by default and is not
* listed in the PHP manual!
*
* @param string $line
* @return string
*/
protected function _convertSpecialChars($line) {
/*
* Check whether we have the right version of iconv
*/
if ( ('glibc' !== ICONV_IMPL) || (true == version_compare(ICONV_VERSION, '2.8.90', '&lt;')) ) {
throw new Exception('Please use the glibc iconv, version 2.8.90 or higher');
}

/*
* Use iconv for speed and glory
* We use the ASCII//TRANSLIT,IGNORE option to replace the string
* with its ASCII transliterated equivalent. If there's no ASCII
* equivalent, the IGNORE option makes sure the character is just
* thrown away, which is exactly what I want.
*
*/
$new_line = iconv('UTF-8', 'ASCII//TRANSLIT,IGNORE', $line);

return $new_line;
}
</pre><p>I guess I don&#8217;t need to comment on this code example ;) If you do have questions, just ask them in the comments, or via <a href="http://twitter.com/jacobkiers"title="Jacob Kiers on Twitter" >@jacobkiers on Twitter.</a></p> ]]></content:encoded> <wfw:commentRss>http://jacobkiers.net/2009/03/03/40x-speedup-with-iconv-and-php/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced
Database Caching 4/16 queries in 0.029 seconds using disk: basic
Object Caching 335/365 objects using disk: basic
Content Delivery Network via N/A

Served from: jacobkiers.net @ 2012-02-06 21:01:50 -->
