<?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"
	>

<channel>
	<title>Rudd-O.com &#187; PHP</title>
	<atom:link href="http://rudd-o.com/archives/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://rudd-o.com</link>
	<description>We only do fun stuff.</description>
	<pubDate>Thu, 02 Oct 2008 13:18:52 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6</generator>
	<language>en</language>
			<item>
		<title>Just invented a technique for a true home page in WordPress blogs</title>
		<link>http://rudd-o.com/archives/2006/11/11/just-invented-a-technique-for-a-true-home-page-in-wordpress-blogs/</link>
		<comments>http://rudd-o.com/archives/2006/11/11/just-invented-a-technique-for-a-true-home-page-in-wordpress-blogs/#comments</comments>
		<pubDate>Sat, 11 Nov 2006 20:22:44 +0000</pubDate>
		<dc:creator>Rudd-O</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Turbocharged]]></category>

		<guid isPermaLink="false">http://rudd-o.com/archives/2006/11/11/just-invented-a-technique-for-a-true-home-page-in-wordpress-blogs/</guid>
		<description><![CDATA[It lets you put any of your blog pages as a static home page, while maintaining a separate blog posts page.  It’s ideal for turning WordPress into a CMS.

Read it on my Turbocharged blog: Building a true home page into your WordPress blog
]]></description>
			<content:encoded><![CDATA[<p>It lets you put any of your blog pages as a static home page, while maintaining a separate blog posts page.  It’s ideal for turning <a href="http://turbochargedcms.com/2006/11/building-a-true-home-page-into-your-wordpress-blog/">WordPress into a CMS</a>.</p>

<p>Read it on my Turbocharged blog: <a href="http://turbochargedcms.com/2006/11/building-a-true-home-page-into-your-wordpress-blog/">Building a true home page into your WordPress blog</a></p>
]]></content:encoded>
			<wfw:commentRss>http://rudd-o.com/archives/2006/11/11/just-invented-a-technique-for-a-true-home-page-in-wordpress-blogs/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Benchmarking WordPress plugins</title>
		<link>http://rudd-o.com/archives/2006/06/09/benchmarking-wordpress-plugins/</link>
		<comments>http://rudd-o.com/archives/2006/06/09/benchmarking-wordpress-plugins/#comments</comments>
		<pubDate>Fri, 09 Jun 2006 10:52:17 +0000</pubDate>
		<dc:creator>Rudd-O</dc:creator>
		
		<category><![CDATA[Mi weblog]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Software bacán]]></category>

		<guid isPermaLink="false">http://rudd-o.com/archives/2006/06/09/benchmarking-wordpress-plugins/</guid>
		<description><![CDATA[

While doing routine tuning and checking of my weblog, I discovered a rather nasty slowdown with WordPress page generation.  Taking the “scientific” route, I deactivated nearly all non-essential plugins in my Supercharged weblog (more than 40) and proceeded to activate them one by one, interspersing activations with ApacheBench tests.

A short plug: This post is [...]]]></description>
			<content:encoded><![CDATA[<div class="floatright"><a href="http://rudd-o.com/wp-content/uploads/images/plugin-performance.png" title="Comparative accumulative plugin performance in KB/s" target="_self" rel="lightbox"><img class="thumbnail" src="http://rudd-o.com/wp-content/uploads/images/thumb_plugin-performance.png" alt="Comparative accumulative plugin performance in KB/s" width="150" height="106"/></a></div>

<p>While doing routine tuning and checking of my weblog, I discovered a rather nasty slowdown with WordPress page generation.  Taking the “scientific” route, I deactivated nearly all non-essential plugins in my <a href="http://rudd-o.com/projects/supercharged/">Supercharged</a> weblog (more than 40) and proceeded to activate them one by one, interspersing activations with ApacheBench tests.</p>

<p><em>A short plug: This post is brought to you by <a href="http://rudd-o.com/projects/supercharged/" title="Turbocharged">Supercharged</a>.  If you want to get these plugins in one package, consider <a href="http://rudd-o.com/projects/supercharged/" title="Turbocharged">getting Supercharged for your blog</a>.</em></p>

<p>Really quick conclusions:</p>

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

<ul>
<li>WordPress (with the baseline plugins installed) is slow.  On my server (not exactly the fastest thing in the planet, but dedicated to Web and database serving, and not bound by swapping or memory limits), it can’t pipe more than 1.5 front page views per second.  I don’t think the load from ApacheBench accounts for more than 10% of the CPU usage.</li>
<li>Do not install My Tube under any circumstances.  Further investigation is pending.</li>
<li>These plugins add negligible amounts of overhead.  None of the plugins (except for My Tube) added detectable performance losses.</li>
<li>bsuite seems to introduce a small slowdown.</li>
</ul>

<p>The chart above shows the (rather unscientific, but effective) results of my short benchmark, in a nice bar chart (the taller, the better).  This table represents the average KB/s for page generation after activating each plugin.  Note that plugins were never deactivated after beig activated (except for My Tube, which I kicked out of the circuit).  Thus, in a perfectly repeatable test scenario, you should see a ladder in the bar chart.  Since you don’t see one, I can conclude that stacking my 40 plugins introduces negligible page generation performance overhead.</p>

<p>Caveats:</p>

<ul>
<li>I started with a plugin baseline of Akismet, Fold Page List, Fold Category List, PHP Markdown Extra, Redirectify, Software shop for WordPress, del.icio.us widget, Sidebar Widgets, WordPress allow dashes, WordPress AutoLink, Permalink redirect.  There’s simply no way I can afford to turn these off in my live site.</li>
<li>I hit my site with 100 requests using <code>ab -n 1000 http://rudd-o.com/</code> executing on the Web host.  Whenever I saw dramatic performance drops, I checked to see whether the load average was high, then waited for all other running processes to finish, and then re-tested</li>
<li>As you can see, I only tested front page views.</li>
<li>The base WordPress installation is a vanilla 2.0.3 + bug fixes setup.  No caching options were modified or set.</li>
<li>This is not a scientific test.  Standard deviation is not reported.  Since I was only looking major performance drops, minor differences (+/- 0.1 requests per second) can be accounted for the fact that tests were performed on the live site.  Yes, that includes apparent “performance boosts” with some plugins active.</li>
<li>Plugins that add template tags or widgets were added to the template/widget configuration for accurate representation.</li>
<li>This benchmark does not measure page responsiveness or ancillary object loading times (JavaScript, images)</li>
</ul>

<p>Here is the collected data:</p>

<p>baseline: Akismet, Fold Page List, Fold Category List, PHP Markdown Extra, Redirectify, Software shop for WordPress, del.icio.us widget, Sidebar Widgets, WordPress allow dashes, WordPress AutoLink, Permalink redirect:<br />
Requests per second:    1.56 [#/sec] (mean)<br />
Time per request:       642.467 [ms] (mean)<br />
Transfer rate:          50.06 [Kbytes/sec] received</p>

<p>add: Canary Comment<br />
Requests per second:    1.54 [#/sec] (mean)<br />
Time per request:       649.238 [ms] (mean)<br />
Transfer rate:          52.48 [Kbytes/sec] received</p>

<p>add Cache-Flush<br />
Requests per second:    1.58 [#/sec] (mean)<br />
Time per request:       634.240 [ms] (mean)<br />
Transfer rate:          53.72 [Kbytes/sec] received</p>

<p>add Creative Commons Configurator<br />
Requests per second:    1.54 [#/sec] (mean)<br />
Time per request:       648.789 [ms] (mean)<br />
Transfer rate:          54.52 [Kbytes/sec] received</p>

<p>add: Digg This<br />
Requests per second:    1.47 [#/sec] (mean)<br />
Time per request:       678.475 [ms] (mean)<br />
Transfer rate:          52.13 [Kbytes/sec] received</p>

<p>add: Days Since Birth and Gravatars<br />
Requests per second:    1.49 [#/sec] (mean)<br />
Time per request:       669.963 [ms] (mean)<br />
Transfer rate:          52.82 [Kbytes/sec] received</p>

<p>add: Inline ajax more<br />
Requests per second:    1.67 [#/sec] (mean)<br />
Time per request:       597.525 [ms] (mean)<br />
Transfer rate:          61.60 [Kbytes/sec] received</p>

<p>add: In Series<br />
Requests per second:    1.41 [#/sec] (mean)<br />
Time per request:       707.612 [ms] (mean)<br />
Transfer rate:          52.02 [Kbytes/sec] received</p>

<p>add: iG:CoComment<br />
Requests per second:    1.61 [#/sec] (mean)<br />
Time per request:       621.901 [ms] (mean)<br />
Transfer rate:          59.19 [Kbytes/sec] received</p>

<p>add: Bread Crumb Trail Generator<br />
Requests per second:    1.60 [#/sec] (mean)<br />
Time per request:       623.195 [ms] (mean)<br />
Transfer rate:          59.47 [Kbytes/sec] received</p>

<p>add: LMB^Box FilePress<br />
Requests per second:    1.55 [#/sec] (mean)<br />
Time per request:       646.917 [ms] (mean)<br />
Transfer rate:          57.29 [Kbytes/sec] received</p>

<p>add: LMB^Box Comment Quicktags<br />
Requests per second:    1.73 [#/sec] (mean)<br />
Time per request:       577.145 [ms] (mean)<br />
Transfer rate:          64.21 [Kbytes/sec] received</p>

<p>add: My Tube<br />
Requests per second:    0.49 [#/sec] (mean)<br />
Time per request:       2025.577 [ms] (mean)<br />
Transfer rate:          18.39 [Kbytes/sec] received
(at this point, I’m disabling My Tube)</p>

<p>remove: My Tube<br />
Requests per second:    1.71 [#/sec] (mean)<br />
Time per request:       585.946 [ms] (mean)<br />
Transfer rate:          63.25 [Kbytes/sec] received</p>

<p>add: Optimal Title<br />
Requests per second:    1.49 [#/sec] (mean)<br />
Time per request:       671.295 [ms] (mean)<br />
Transfer rate:          55.21 [Kbytes/sec] received</p>

<p>add: Related Posts<br />
Requests per second:    1.73 [#/sec] (mean)<br />
Time per request:       577.798 [ms] (mean)<br />
Transfer rate:          64.14 [Kbytes/sec] received</p>

<p>add: Taragana’s Del.icio.us mp3 Player Plugin<br />
Requests per second:    1.55 [#/sec] (mean)<br />
Time per request:       646.751 [ms] (mean)<br />
Transfer rate:          57.41 [Kbytes/sec] received</p>

<p>add: FancyTooltips<br />
Requests per second:    1.51 [#/sec] (mean)<br />
Time per request:       660.859 [ms] (mean)<br />
Transfer rate:          56.59 [Kbytes/sec] received</p>

<p>add: Recent Comments (my edition adds a ‘Recent comments with excerpts’ widget)<br />
Requests per second:    1.51 [#/sec] (mean)<br />
Time per request:       664.122 [ms] (mean)<br />
Transfer rate:          58.38 [Kbytes/sec] received</p>

<p>add: Sociable<br />
Requests per second:    1.53 [#/sec] (mean)<br />
Time per request:       652.300 [ms] (mean)<br />
Transfer rate:          59.62 [Kbytes/sec] received</p>

<p>add: Subscribe me<br />
Requests per second:    1.52 [#/sec] (mean)<br />
Time per request:       659.224 [ms] (mean)<br />
Transfer rate:          61.01 [Kbytes/sec] received</p>

<p>add: Search Meter<br />
Requests per second:    1.49 [#/sec] (mean)<br />
Time per request:       670.161 [ms] (mean)<br />
Transfer rate:          60.02 [Kbytes/sec] received</p>

<p>add: Search Reloaded<br />
Requests per second:    1.43 [#/sec] (mean)<br />
Time per request:       699.615 [ms] (mean)<br />
Transfer rate:          57.49 [Kbytes/sec] received</p>

<p>add: Text Link Ads<br />
Requests per second:    1.43 [#/sec] (mean)<br />
Time per request:       699.958 [ms] (mean)<br />
Transfer rate:          57.46 [Kbytes/sec] received</p>

<p>add: WP Lightbox 2<br />
Requests per second:    1.41 [#/sec] (mean)<br />
Time per request:       706.736 [ms] (mean)<br />
Transfer rate:          57.67 [Kbytes/sec] received</p>

<p>add: Write Post Find and Rudd-O’s Wordspew<br />
Requests per second:    1.44 [#/sec] (mean)<br />
Time per request:       695.128 [ms] (mean)<br />
Transfer rate:          59.01 [Kbytes/sec] received</p>

<p>add: BlogSpy for WordPress<br />
Requests per second:    1.45 [#/sec] (mean)<br />
Time per request:       688.703 [ms] (mean)<br />
Transfer rate:          59.66 [Kbytes/sec] received</p>

<p>add: XFish Meta<br />
Requests per second:    1.40 [#/sec] (mean)<br />
Time per request:       714.832 [ms] (mean)<br />
Transfer rate:          57.57 [Kbytes/sec] received</p>

<p>add: WP-SlimStat<br />
Requests per second:    1.41 [#/sec] (mean)<br />
Time per request:       708.787 [ms] (mean)<br />
Transfer rate:          58.06 [Kbytes/sec] received</p>

<p>add: AutoMeta<br />
Requests per second:    1.38 [#/sec] (mean)<br />
Time per request:       725.395 [ms] (mean)<br />
Transfer rate:          56.73 [Kbytes/sec] received</p>

<p>add: bsuite (my edition has some bug fixes by me)<br />
Requests per second:    1.21 [#/sec] (mean)<br />
Time per request:       827.565 [ms] (mean)<br />
Transfer rate:          49.72 [Kbytes/sec] received</p>
]]></content:encoded>
			<wfw:commentRss>http://rudd-o.com/archives/2006/06/09/benchmarking-wordpress-plugins/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Quickie: Cómo entrar en BlogSpy con WordPress</title>
		<link>http://rudd-o.com/archives/2006/05/29/quickie-como-entrar-en-blogspy-con-wordpress/</link>
		<comments>http://rudd-o.com/archives/2006/05/29/quickie-como-entrar-en-blogspy-con-wordpress/#comments</comments>
		<pubDate>Tue, 30 May 2006 03:05:51 +0000</pubDate>
		<dc:creator>Rudd-O</dc:creator>
		
		<category><![CDATA[Free software]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Software bacán]]></category>

		<guid isPermaLink="false">http://rudd-o.com/archives/2006/05/29/quickie-como-entrar-en-blogspy-con-wordpress/</guid>
		<description><![CDATA[Si usas WordPress, sabrás que normalmente para entrar en BlogSpy necesitas editar tu plantilla… o no, con este pequeño plugin que desarrollé hace 5 minutos:



&lt;?php

/*
Plugin Name: BlogSpy for WordPress
Version: 0.0.1
Plugin URI: http://rudd-o.com/
Description: Automates inclusion in the BlogSpy network
Author: Manuel Amador (Rudd-O)
Author URI: http://rudd-o.com/
*/

/* Code licensed under the GNU GPL v2 */

function blogspy_footer() {
   [...]]]></description>
			<content:encoded><![CDATA[<p>Si usas WordPress, sabrás que normalmente para entrar en <a href="http://spy.foxcorp.org">BlogSpy</a> necesitas editar tu plantilla&#8230; o no, con este pequeño plugin que desarrollé hace 5 minutos:</p>

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

<p><pre>&lt;?php</pre></p>

<p>/*
Plugin Name: BlogSpy for WordPress
Version: 0.0.1
Plugin URI: http://rudd-o.com/
Description: Automates inclusion in the BlogSpy network
Author: Manuel Amador (Rudd-O)
Author URI: http://rudd-o.com/
*/</p>

<p>/* Code licensed under the GNU GPL v2 */</p>

<p>function blogspy_footer() {
        print '&lt;script src="http://spy.foxcorp.org/spy.js" type="text/javascript"&gt;&lt;/script&gt;';
}</p>

<p>add_action("wp_footer","blogspy_footer");</p>

<p>?&gt;</p>

<p>Graba este código en un archivo llamado <code>blogspy.php</code> y colócalo en tu directorio <code>wp-content/plugins</code> en tu Web host de WordPress.  Actívalo a través de la pantalla de administración de plugins de WordPress, and that&#8217;s it!  Ya estás en BlogSpy.</p>

<p>En algún momento lo haré un plugin propiamente dicho, disponible para descargar.  Por lo pronto, que te aproveche.</p>
]]></content:encoded>
			<wfw:commentRss>http://rudd-o.com/archives/2006/05/29/quickie-como-entrar-en-blogspy-con-wordpress/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Revisiting multiple inheritance in PHP</title>
		<link>http://rudd-o.com/archives/2006/03/18/revisiting-multiple-inheritance-in-php/</link>
		<comments>http://rudd-o.com/archives/2006/03/18/revisiting-multiple-inheritance-in-php/#comments</comments>
		<pubDate>Sat, 18 Mar 2006 14:42:53 +0000</pubDate>
		<dc:creator>Rudd-O</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Software bacán]]></category>

		<guid isPermaLink="false">http://rudd-o.com/archives/2006/03/18/revisiting-multiple-inheritance-in-php/</guid>
		<description><![CDATA[As it turns out, version 0.7 of the runkit extension for PHP has problems when copying methods from a class into another.  Of course, this punts my original multiple inheritance simulation technique.  The bug in detail: copying of methods from “parent” classes into the “child” class succeeds, but later on, when attempting to [...]]]></description>
			<content:encoded><![CDATA[<p>As it turns out, version 0.7 of the <code>runkit</code> extension for PHP has problems when copying methods from a class into another.  Of course, this punts <a href="post:simulating-multiple-inheritance-in-php-5-via-the-runkit-extension">my original multiple inheritance simulation technique</a>.  The bug in detail: copying of methods from &#8220;parent&#8221; classes into the &#8220;child&#8221; class succeeds, but later on, when attempting to use a method, PHP requests ludicrous amounts of memory to the OS, which causes PHP to fail.</p>

<p>In lieu of that problem, I decided to explore alternatives.  The final, usable alternative seems to be:</p>

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

<p><pre>function inherits_from($destClassName,$srcClassNameList) {
    foreach ($srcClassNameList as $s) {
        runkit_class_adopt($destClassName,$s);
    }
}</pre></p>

<p>And this version does work without the memory exhaustion problem.  In short:</p>

<p><pre>&lt;?php</pre></p>

<p>class A {
    ...A's methods here...
}</p>

<p>class B {
    ...B's methods here...
}</p>

<p>class C {
    ...C's methods here...
}</p>

<p>class MultipleInheritedClass {
    ...this class' methods here...
} <strong>inherits_from(
        'MultipleInheritedClass',
        array('A','B','C')
        );</strong>
?&gt;</p>

<p>The <code>inherits_from</code> construct does the magic.  All you need to type there is:</p>

<ul>
<li>The name of the &#8220;child&#8221; class</li>
<li>An array containing the names of the &#8220;parent&#8221; classes</li>
</ul>

<p>Of course, this technique works only in PHP 5, with the <code>runkit</code> extension.</p>

<p>Despite the cutting-edge requirements, I&#8217;ve just shown there&#8217;s a practical way to build multiple inheritance in PHP.  Mixin classes, aggregate classes, they&#8217;re a few keystrokes away.  Long live PHP!</p>

<p>Oh, by the way, did I mention that <a href="post:php-runkit-rpms">I built convenient RPM packages of <code>runkit</code></a>?</p>
]]></content:encoded>
			<wfw:commentRss>http://rudd-o.com/archives/2006/03/18/revisiting-multiple-inheritance-in-php/feed/</wfw:commentRss>
		</item>
		<item>
		<title>RPM packages of the runkit extension for PHP</title>
		<link>http://rudd-o.com/archives/2006/03/18/php-runkit-rpms/</link>
		<comments>http://rudd-o.com/archives/2006/03/18/php-runkit-rpms/#comments</comments>
		<pubDate>Sat, 18 Mar 2006 14:42:05 +0000</pubDate>
		<dc:creator>Rudd-O</dc:creator>
		
		<category><![CDATA[Free software]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Software bacán]]></category>

		<guid isPermaLink="false">http://rudd-o.com/archives/2006/03/18/php-runkit-rpms/</guid>
		<description><![CDATA[Yes, sir!  Due to my increased involvement in PHP coding, I’ve had to try the runkit extension.  Since I absolutely refuse to install any software from source without preparing a package for my system (in this case, RPM-based Fedora Core), I took the time to prepare the RPM packages for runkit.



They should work [...]]]></description>
			<content:encoded><![CDATA[<p>Yes, sir!  Due to my increased involvement in PHP coding, I’ve had to try the <code>runkit</code> extension.  Since I absolutely refuse to install any software from source without preparing a package for my system (in this case, RPM-based Fedora Core), I took the time to prepare the RPM packages for <code>runkit</code>.</p>

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

<p>They should work on any Fedora Core 5 system (it may just work on a Fedora Core 4 system with PHP 5.1, but other than that, you’ll have to edit the spec file).</p>

<p><a href="http://rudd-o.com/wp-content/uploads/projects/files/php-runkit/">Download the PHP <code>runkit</code> RPMs (source and i386 packages)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://rudd-o.com/archives/2006/03/18/php-runkit-rpms/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Simulating multiple inheritance in PHP 5 via the runkit extension</title>
		<link>http://rudd-o.com/archives/2006/03/14/simulating-multiple-inheritance-in-php-5-via-the-runkit-extension/</link>
		<comments>http://rudd-o.com/archives/2006/03/14/simulating-multiple-inheritance-in-php-5-via-the-runkit-extension/#comments</comments>
		<pubDate>Tue, 14 Mar 2006 22:47:50 +0000</pubDate>
		<dc:creator>Rudd-O</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Software bacán]]></category>

		<guid isPermaLink="false">http://rudd-o.com/archives/2006/03/14/simulating-multiple-inheritance-in-php-5-via-the-runkit-extension/</guid>
		<description><![CDATA[Update: there’s a serious bug with this approach and `runkit` 0.7.  For an updated approach, try Revisiting multiple inheritance in PHP.  Oh, there are RPM packages for runkit here.

Here’s some code that will help you simulate multiple inheritance in PHP 5 with maximum portability.  This requires the runkit extension for PHP, regrettably. [...]]]></description>
			<content:encoded><![CDATA[<p><ins datetime="2006-03-18T14:47:11+00:00">Update: there&#8217;s a serious bug with this approach and `runkit` 0.7.  For an updated approach, try <a href="post:revisiting-multiple-inheritance-in-php">Revisiting multiple inheritance in PHP</a>.  Oh, there are <a href="post:php-runkit-rpms">RPM packages for <code>runkit</code> here</a>.</ins></p>

<p>Here&#8217;s some code that will help you simulate multiple inheritance in PHP 5 with maximum portability.  This requires the <a href="http://php.net/manual/en/ref.runkit.php"><code>runkit</code></a> extension for PHP, regrettably.  Hope <code>runkit</code> gets rolled into baseline PHP 5.</p>

<p>This code also emulates the <a href="http://www.php.net/manual/en/function.aggregate-methods.php"><code>aggregate_methods</code></a> function from the <a href="http://www.php.net/manual/en/ref.objaggregation.php">Object aggregation functions</a> in PHP 4.</p>

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

<p>Say you have:</p>

<p><pre>&lt;?php
class Foo {
   function example() {
       return "foo!\n";
   }
}</pre></p>

<p>class Bar {
   // initially, no methods
}</p>

<p>// copy the example() method from the Foo class to the Bar class, as baz()
runkit_method_copy('Bar', 'baz', 'Foo', 'example');</p>

<p>// output copied function
echo Bar::baz();
?&gt;</p>

<p>We can generalize the <code>runkit_method_copy</code> to work with all classes:</p>

<p><pre>&lt;?php</pre></p>

<p>function aggregate_methods($destClassName,$srcClassName) {
    $methods = get_class_methods($srcClassName);
    foreach ($methods as $m) {
        runkit_method_copy($destClassName,$m,$srcClassName,$m);
    }
}</p>

<p>function inherits_from($destClassName,$srcClassNameList) {
        foreach ($srcClassNameList as $s) {
                aggregate_methods($destClassName,$s);
        }
}</p>

<p>?&gt;</p>

<p>Now, the function call will work for all classes without modification (honorable exception made of classes whose method namespaces clash).  This little bit of magic lets you &#8216;inherit&#8217; from multiple classes, taking full advantage of methods defined in other classes (such as classes written explicitly to work as mix-ins).  Most of the introspection machinery won&#8217;t exactly work, but those are the breaks.</p>

<p>In practical terms:</p>

<p><pre>&lt;?php</pre></p>

<p>class A {
    ...A' methods here...
}</p>

<p>class B {
    ...B' methods here...
}</p>

<p>class C {
    ...C's methods here...
}</p>

<p>class MultipleInheritedClass {
    ...this class' methods here...
} inherits_from('MultipleInheritedClass',array('A','B','C'));</p>

<p>?&gt;</p>

<p>So there you go: <strong>there is multiple inheritance available in PHP</strong>!</p>
]]></content:encoded>
			<wfw:commentRss>http://rudd-o.com/archives/2006/03/14/simulating-multiple-inheritance-in-php-5-via-the-runkit-extension/feed/</wfw:commentRss>
		</item>
		<item>
		<title>5 minutes to finding issues in production PHP Web applications</title>
		<link>http://rudd-o.com/archives/2006/03/10/5-minutes-to-finding-issues-in-production-php-web-applications/</link>
		<comments>http://rudd-o.com/archives/2006/03/10/5-minutes-to-finding-issues-in-production-php-web-applications/#comments</comments>
		<pubDate>Fri, 10 Mar 2006 22:41:19 +0000</pubDate>
		<dc:creator>Rudd-O</dc:creator>
		
		<category><![CDATA[Free software]]></category>

		<category><![CDATA[Linux]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Server management]]></category>

		<guid isPermaLink="false">http://rudd-o.com/archives/2006/03/10/5-minutes-to-finding-issues-in-production-php-web-applications/</guid>
		<description><![CDATA[Detecting and correcting problems with applications at early stages is an important role of the server manager.  Unfortunately, not all errors are detected at the testing stages.  Even more unfortunate is the fact that most errors go undetected because they are usually triggered when a certain set of criteria is met.



Since all you [...]]]></description>
			<content:encoded><![CDATA[<p>Detecting and correcting problems with applications at early stages is an important role of the server manager.  Unfortunately, not all errors are detected at the testing stages.  Even more unfortunate is the fact that most errors go undetected because they are usually triggered when a certain set of criteria is met.</p>

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

<p>Since all you have is 5 minutes (which is one of the tenets of this Server management series, and quite possibly the only simple truth in your case), in this installment, we&#8217;ll unlock the secret of server log foraging.</p>

<h2>All you need is <code>grep</code>.</h2>

<p>I don&#8217;t know what the Beatles would say about this heading, but, indeed, <code>grep</code> is all you need.</p>

<p>This guide is laid out in two distinct sections:</p>

<ul>
<li>Configuring PHP to report errors</li>
<li>Actually mulling over the server logs</li>
</ul>

<p>I&#8217;m assuming you&#8217;re using Apache on Linux, of course.  I will also assume you have access to your server logs and write permission to the PHP configuration file (usually <code>/etc/php.ini</code>).</p>

<h2>Configuring PHP to report errors</h2>

<p>Okay, fire up your trusty editor of choice (I use <code>nano</code>, and that&#8217;s only because I&#8217;m accustomed to <code>pico</code> &mdash; no longer shipped with any Free Software distro &mdash; and please let&#8217;s not get into an editor flamefest here) while being <code>root</code>.  Open <code>/etc/php.ini</code> and look for the following configuration keys:</p>

<p><pre>display_errors = On</pre></p>

<p>Set it to <code>Off</code>.  Production PHP applications should not reveal any bugs to the outside world.  For the true hacker, the log files will say all that&#8217;s needed.  And, for that, change the following configuration key:</p>

<p><pre>error_reporting = E_ALL</pre></p>

<p>Set it to <code>E_ALL</code>, because you&#8217;re interested in warnings, notices and errors.  Finally, look for the following configuration key:</p>

<p><pre>log_errors = Off</pre></p>

<p>and set it to <code>On</code>.  Save the file, and restart Apache (<a href="post:tuning-an-apache-server-in-5-minutes">here&#8217;s how</a>).</p>

<p>Let the application run for a couple of minutes (or hours, depending on your visitor volume).</p>

<h2><code>grep</code>ping the logs</h2>

<p>Now it&#8217;s time to start working on those logs.  Locate your Apache error log file (usually at <code>/var/log/httpd/error_log</code>.  Then use the following command to find all PHP-related error messages:</p>

<p><pre>grep PHP /var/log/httpd/error_log</pre></p>

<p>That may spit out a hefty amount of messages, so you&#8217;ll probably want to redirect it into a file:</p>

<p><pre>grep PHP /var/log/httpd/error_log &gt; /root/phperrors</pre></p>

<p>The greater-than symbol directs the output of <code>grep</code> into the file <code>/root/phperrors</code>.</p>

<p>Inspect the newly created file with your favorite editor and look for messages.  Does any of them say <code>PHP Fatal Error</code> or <code>PHP Error</code>?  If so, you&#8217;ve got a real problem between hands.  Warnings are also a cause for concern, because they usually mean an error occurred in your application, but the application just kept going like nothing happened.  Notices aren&#8217;t so much a concern, but they should be dealt with individually, because they usually point to common programming mistakes that must be fixed.</p>

<p>The PHP log messages provide you with another useful tidbit of information: they say the file and line number of the error, notice or warning:</p>

<p><code>PHP Warning:  strtotime() [client 157.100.84.91] PHP Warning:  strtotime(): Called with an empty time parameter. in /home/rudd-o/public_html/links.php on line 53, referer: http://rudd-o.com/index.php</code></p>

<p>That information is very useful to find the source of the problem.</p>

<h2>Conclusions</h2>

<p>Whether you have to fix errors yourself, or there&#8217;s a dedicated team behind the Web applications you&#8217;re overseeing, any PHP-related messages usually pinpoint to issues that need to be paid attention to.</p>

<p>It&#8217;s also a good idea to automate this procedure into a shell or <code>CGI</code> script for the developers of the applications you oversee.  That way, they&#8217;ll have a way to get early notice of any issues, and you won&#8217;t need to be involved in the process.  Here&#8217;s an example shell script that would send those messages to someone at your company, to be run through <code>cron</code>:</p>

<p><pre>#!/bin/bash</pre></p>

<p>grep PHP /var/log/httpd/error_log | \
    mail -s 'PHP messages' someone@yourcompany.com
</p>

<p>Finally, this procedure should also be standard on testing and staging servers.  Finding a problem early on the development stage is invaluable.  You really don&#8217;t know how many customers you may lose to bugs that slip into production.</p>

<p>And that&#8217;s it for today!  Remember, keep your Web applications bug-free, and they&#8217;ll give lots of value in return.  Happy hacking!</p>
]]></content:encoded>
			<wfw:commentRss>http://rudd-o.com/archives/2006/03/10/5-minutes-to-finding-issues-in-production-php-web-applications/feed/</wfw:commentRss>
		</item>
		<item>
		<title>PHP code to get exchange rates between currencies</title>
		<link>http://rudd-o.com/archives/2005/06/23/php-code-to-get-exchange-rates-between-currencies/</link>
		<comments>http://rudd-o.com/archives/2005/06/23/php-code-to-get-exchange-rates-between-currencies/#comments</comments>
		<pubDate>Thu, 23 Jun 2005 12:53:57 +0000</pubDate>
		<dc:creator>Rudd-O</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Software bacán]]></category>

		<guid isPermaLink="false">http://www.amautacorp.com/staff/Rudd-O/?p=568</guid>
		<description><![CDATA[Given the DOMit! PHP DOM parser and an XML feed taken from the Federal Reserve Bank of New York, the following code will let you get exchange rates between two currency symbols (e.g. USD to EUR).



Please beware that my blogging software adds a backslash for every quote mark. You should promptly remove these before attempting [...]]]></description>
			<content:encoded><![CDATA[<p>Given the DOMit! PHP DOM parser and <a href="http://ny.frb.org/markets/fxrates/noon.cfm">an XML feed taken from the Federal Reserve Bank of New York</a>, the following code will let you get exchange rates between two currency symbols (e.g. USD to EUR).</p>

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

<p>Please beware that my blogging software adds a backslash for every quote mark. You should promptly remove these before attempting to use this code.</p>

<p><pre>require_once("xml_domit_parser.php");</pre></p>

<p>function get_currency_exchange_array($location) {</p>

<p>global $_get_currencies_cache;
if ($_get_currencies_cache) { return $_get_currencies_cache; }
$data = file_get_contents($location);
$doc = new DOMIT_Document();
$doc-&gt;parseXML($data, true);</p>

<p>//crear un array vacio $moneda;
$moneda = array();
//traerme todos los frbny:series en una lista $list
$list = $doc-&gt;getElementsByTagName("frbny:Series");</p>

<p>//para cada elemento de $list:
foreach ($list-&gt;arNodeList as $element) {
    $UNIT = $element-&gt;getAttribute("UNIT");
    if (!$UNIT) continue;</p>

<pre><code>$frbny_CURR = $element-&amp;gt;getElementsByTagName("frbny:CURR");
if (!$frbny_CURR) continue;
$frbny_CURR = $frbny_CURR-&amp;gt;arNodeList;
if (!$frbny_CURR) continue;
$frbny_CURR = $frbny_CURR[0];
if (!$frbny_CURR) continue;
$frbny_CURR = $frbny_CURR-&amp;gt;firstChild;
if (!$frbny_CURR) continue;
$frbny_CURR = $frbny_CURR-&amp;gt;nodeValue;
if (!$frbny_CURR) continue;

$frbny_OBS_VALUE = $element-&amp;gt;getElementsByTagName("frbny:OBS_VALUE");
if (!$frbny_OBS_VALUE) continue;
$frbny_OBS_VALUE = $frbny_OBS_VALUE-&amp;gt;arNodeList;
if (!$frbny_OBS_VALUE) continue;
$frbny_OBS_VALUE = $frbny_OBS_VALUE[0];
if (!$frbny_OBS_VALUE) continue;
$frbny_OBS_VALUE = $frbny_OBS_VALUE-&amp;gt;firstChild;
if (!$frbny_OBS_VALUE) continue;
$frbny_OBS_VALUE = $frbny_OBS_VALUE-&amp;gt;nodeValue;
if (!$frbny_OBS_VALUE) continue;

// si el array $moneda no contiene un elemento (array) de nombre UNIT, crearlo como array vacio
if (!array_key_exists($UNIT,$moneda)) $moneda[$UNIT] = array();
// ahora si, le metemos el valúe al array
$moneda[$UNIT][$frbny_CURR] = floatval( $frbny_OBS_VALUE );
</code></pre>

<p>}</p>

<p>$_get_currencies_cache = $moneda;
return $moneda;</p>

<p>}</p>

<p>function exchange_rate($file,$from_descriptor,$to_descriptor,$donotrecurse=false) {</p>

<h1>returns null if no exchange rate found</h1>

<p>$moneda = get_currency_exchange_array($file);</p>

<p>if (array_key_exists($from_descriptor,$moneda) &nbsp;&nbsp; array_key_exists($to_descriptor,$moneda[$from_descriptor])) {
     return $moneda[$from_descriptor][$to_descriptor];
}
elseif ($donotrecurse == false) {
     $value = exchange_rate($file,$to_descriptor,$from_descriptor,true);
     if (!$value) return;
     return 1.0/$value;
}</p>

<p>return;</p>

<p>}</p>

<p>Be nice to the Federal Reserve server, and do not fetch their XML feed each time you want to obtain exchange rates.</p>
]]></content:encoded>
			<wfw:commentRss>http://rudd-o.com/archives/2005/06/23/php-code-to-get-exchange-rates-between-currencies/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
