<?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>Rommel Santor&#039;s Clog &#187; PHP</title>
	<atom:link href="https://rommelsantor.com/clog/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>https://rommelsantor.com/clog</link>
	<description>my exploits and misadventures in programming</description>
	<lastBuildDate>Thu, 04 Feb 2016 12:56:01 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.0.38</generator>
	<item>
		<title>30 Second Delay with PHP and Memcache Sessions</title>
		<link>https://rommelsantor.com/clog/2016/02/02/30-second-delay-php-memcache-sessions/</link>
		<comments>https://rommelsantor.com/clog/2016/02/02/30-second-delay-php-memcache-sessions/#comments</comments>
		<pubDate>Wed, 03 Feb 2016 07:08:02 +0000</pubDate>
		<dc:creator><![CDATA[rommel]]></dc:creator>
				<category><![CDATA[Bugs]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://rommelsantor.com/clog/?p=459</guid>
		<description><![CDATA[We upgraded the servers at NeatoShop.com and Neatorama.com a couple of weeks ago, and in the past week we started noticing and receiving reports that on &#8220;some&#8221; page loads there was a 30-second delay where the page seemed to hang before finally returning any content. The common things we could put a finger on were [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>We upgraded the servers at NeatoShop.com and Neatorama.com a couple of weeks ago, and in the past week we started noticing and receiving reports that on &#8220;some&#8221; page loads there was a 30-second delay where the page seemed to hang before finally returning any content.</p>
<p>The common things we could put a finger on were 1) it would seem to happen with a raw/initial page load (e.g., in a brand new incognito window), 2) it would not hang up anymore after that first page load, and 3) it seemed to happen only if we loaded neatoshop.com which was then redirected to www.neatoshop.com.</p>
<p>It took a ton of code profiling and countless attempts to reproduce the problem (because it didn&#8217;t happen for me on <i>every</i> new incognito page load), but I finally traced the delay down to <code>session_start()</code>. This didn&#8217;t really make sense to me because we&#8217;ve used php5-memcache (obviously with Memcached) for handling sessions with redundancy across our 7 web servers, and nothing regarding sessions nor Memcached changed on our end any time recently. So what could the problem be?</p>
<p><span id="more-459"></span>
<div style="float: left; margin: 0 10px 10px 0;"><script type="text/javascript">// <![CDATA[
google_ad_client = "ca-pub-7639656561235411";
/* Square (250x250) */
google_ad_slot = "8522038794";
google_ad_width = 250;
google_ad_height = 250;
// ]]&gt;</script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">// <![CDATA[

// ]]&gt;</script></div>
</p>
<p>It started to seem like a pointless shot in the dark to keep googling for clues, but something that stuck out in my mind were reports of session <i>files</i> getting locked if there were two simultaneous requests from the same user. This didn&#8217;t seem to apply since we&#8217;re dealing with Memcached sessions and not file-based sessions, but then I noticed the new <code>memcache.lock_timeout</code> option in php5-memcache v3.0.4 which has a default value of 15 seconds.</p>
<p>Hmm&#8230; 15 seconds with a lock on two simultaneous requests seems like it could result in a 30 second delay&#8230; ya think? There&#8217;s one way to find out.</p>
<p>I tried changing the memcache.lock_timeout value to 2 seconds then trying to repro the problem. Once it seemed like I got the hang-up to occur, I held my breath and the page hung for 4 seconds before loading. Then I changed the value to 1 second and tried again, and as I&#8217;d hoped, the loading time was 2 seconds!</p>
<p>Finally, I&#8217;ve reduced the value to 0 seconds and there seems to no longer be any delay. I&#8217;m not certain of any side effects or unintended consequences of setting the value to zero, but whatever they are, they are insignificant as compared to every customer on an e-commerce site occasionally being subjected to a 30-second delay. I just thought I should share this tale of woe, as I couldn&#8217;t really find any good info on it, and I&#8217;m assuming there must be others facing the same issue.</p>
<p><b>Update!</b></p>
<p>After reducing the value to zero, I started getting reports of slow load times again, which indicates a value of zero is not valid because it causes the default of 15 seconds to be used. So we&#8217;re stuck using a 1-second lock_timeout, which is the only acceptable solution, but a 2-second delay is much better than 30 seconds!</p>
]]></content:encoded>
			<wfw:commentRss>https://rommelsantor.com/clog/2016/02/02/30-second-delay-php-memcache-sessions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Generate UUID in PHP</title>
		<link>https://rommelsantor.com/clog/2012/02/23/generate-uuid-in-php/</link>
		<comments>https://rommelsantor.com/clog/2012/02/23/generate-uuid-in-php/#comments</comments>
		<pubDate>Thu, 23 Feb 2012 17:47:02 +0000</pubDate>
		<dc:creator><![CDATA[rommel]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[uuid]]></category>

		<guid isPermaLink="false">http://rommelsantor.com/clog/?p=313</guid>
		<description><![CDATA[I posted this last year to PHP.net and thought I&#8217;d just share it here as well. It&#8217;s a short write-up and demonstration of a PHP class you can use to generate various versions of a Universally-Unique Identifier, or UUID. The php5-uuid functions could definitely use some documentation to clarify how they should be used, but [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I posted this last year to PHP.net and thought I&#8217;d just share it here as well. It&#8217;s a short write-up and demonstration of a PHP class you can use to generate various versions of a Universally-Unique Identifier, or UUID.</p>
<p>The php5-uuid functions could definitely use some documentation to clarify how they should be used, but here&#8217;s what I&#8217;ve gleaned by examining the OSSP source code (found here: <a href="http://ossp-uuid.sourcearchive.com/documentation/1.5.1-1ubuntu1/php_2uuid_8c-source.html" target="_blank">http://ossp-uuid.sourcearchive.com/documentation/1.5.1-1ubuntu1/php_2uuid_8c-source.html</a>).</p>
<p>The uuid_make() function takes two arguments when generating v1 or v4, but four arguments are required when generating v3 or v5. The first two arguments have been thoroughly demonstrated and are straightforward, so I&#8217;ll skip to the as-yet non-described arguments.</p>
<p><span id="more-313"></span>
<div style="float:left;margin:0 10px 10px 0">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-7639656561235411";
/* Square (250x250) */
google_ad_slot = "8522038794";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
The third argument to uuid_make() is: $namespace<br />
  &#8211; this is a secondary resource created with uuid_create(); it is apparently used to generate an internal UUID, which is used as the namespace of the output UUID</p>
<p>The fourth argument to uuid_make() is: $url<br />
  &#8211; this is the value that is to be hashed (MD5 for v3, SHA-1 for v5); it may be any string or even null</p>
<p>Here&#8217;s a simple class illustrating the proper usage (note that if php5-uuid is not installed on your system, each function call will just return false):</p>
<pre>
class UUID {
  /**
   * Generates version 1: MAC address
   */
  public static function v1() {
    if (!function_exists('uuid_create'))
      return false;

    $context = $uuid = null;
    uuid_create($context);
    uuid_make($context, UUID_MAKE_V1);
    uuid_export($context, UUID_FMT_STR, $uuid);
    return trim($uuid);
  }

  /**
   * Generates version 3 UUID: MD5 hash of URL
   */
  public static function v3($i_url) {
    if (!function_exists('uuid_create'))
      return false;

    if (!strlen($i_url))
      $i_url = self::v1();

    $context = $namespace = $uuid = null;
    uuid_create($context);
    uuid_create($namespace);

    uuid_make($context, UUID_MAKE_V3, $namespace, $i_url);
    uuid_export($context, UUID_FMT_STR, $uuid);
    return trim($uuid);
  }

  /**
   * Generates version 4 UUID: random
   */
  public static function v4() {
    if (!function_exists('uuid_create'))
      return false;

    $context = $uuid = null;
    uuid_create($context);

    uuid_make($context, UUID_MAKE_V4);
    uuid_export($context, UUID_FMT_STR, $uuid);
    return trim($uuid);
  }

  /**
   * Generates version 5 UUID: SHA-1 hash of URL
   */
  public static function v5($i_url) {
    if (!function_exists('uuid_create'))
      return false;

    if (!strlen($i_url))
      $i_url = self::v1();

    $context = $namespace = $uuid = null;
    uuid_create($context);
    uuid_create($namespace);

    uuid_make($context, UUID_MAKE_V5, $namespace, $i_url);
    uuid_export($context, UUID_FMT_STR, $uuid);
    return trim($uuid);
  }
}
</pre>
<p>And here&#8217;s a demonstration:</p>
<pre>
for ($i = 1; $i <= 3; ++$i) {
  echo 'microtime = ' . microtime(true) . '<br/>';
  echo "V1 UUID: " . UUID::v1() . '<br/>';
  echo "V3 UUID of URL='abc': " . UUID::v3('abc') . '<br/>';
  echo "V4 UUID: " . UUID::v4() . '<br/>';
  echo "V5 UUID of URL=null: " . UUID::v5(null) . '<br/>';
  echo '<hr/>';
}
</pre>
<p>And the output:</p>
<p><code>microtime = 1306620716.0457<br />
V1 UUID: 7fddae8e-8977-11e0-bc11-003048c3b1f2<br />
V3 UUID of URL='abc': 522ec739-ca63-3ec5-b082-08ce08ad65e2<br />
V4 UUID: b3851ec7-4871-4527-92b5-ef5616bae1e6<br />
V5 UUID of URL=null: e129f27c-5103-5c5c-844b-cdf0a15e160d<br />
-------------------<br />
microtime = 1306620716.0465<br />
V1 UUID: 7fddb83e-8977-11e0-9e6e-003048c3b1f2<br />
V3 UUID of URL='abc': 522ec739-ca63-3ec5-b082-08ce08ad65e2<br />
V4 UUID: 7e78fe0d-59b8-4637-af7f-e88d221a7d1e<br />
V5 UUID of URL=null: e129f27c-5103-5c5c-844b-cdf0a15e160d<br />
-------------------<br />
microtime = 1306620716.0467<br />
V1 UUID: 7fddbfb4-8977-11e0-a2bc-003048c3b1f2<br />
V3 UUID of URL='abc': 522ec739-ca63-3ec5-b082-08ce08ad65e2<br />
V4 UUID: 12a940c7-0f3f-46a1-bb5f-bdd602e10654<br />
V5 UUID of URL=null: e129f27c-5103-5c5c-844b-cdf0a15e160d</code></p>
<p>As you can see, the calls to v3() always return the same UUID because the same URL parameter, &#8220;abc&#8221;, is always supplied. The same goes for the v5() function which is always supplied a null URL.</p>
<p>The v4() UUIDs are always entirely different because they are (pseudo)random. And the v1() calls are very similar but just slightly different because it&#8217;s based on the computer&#8217;s MAC address and the current time.</p>
<p><script type="text/javascript">//< ![CDATA[
$("pre").attr({name:'code'}).addClass('php:nocontrols:nogutter');
//]]&gt;</script></p>
]]></content:encoded>
			<wfw:commentRss>https://rommelsantor.com/clog/2012/02/23/generate-uuid-in-php/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Text Beautify WordPress Plugin</title>
		<link>https://rommelsantor.com/clog/2012/02/09/text-beautify-wordpress-plugin/</link>
		<comments>https://rommelsantor.com/clog/2012/02/09/text-beautify-wordpress-plugin/#comments</comments>
		<pubDate>Thu, 09 Feb 2012 17:44:57 +0000</pubDate>
		<dc:creator><![CDATA[rommel]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://rommelsantor.com/clog/?p=304</guid>
		<description><![CDATA[I&#8217;ve just submitted my first ever plugin to the WordPress repository. It&#8217;s called Text Beautify and can be found at the following URL: http://wordpress.org/extend/plugins/text-beautify/ The purpose of the plugin is to beautify post titles, post contents, and comments of your WordPress blog. In post contents and comments, the text is made sentence case. In post [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve just submitted my first ever plugin to the WordPress repository. It&#8217;s called Text Beautify and can be found at the following URL:<br />
<a href="http://wordpress.org/extend/plugins/text-beautify/" target="_blank">http://wordpress.org/extend/plugins/text-beautify/</a></p>
<p>The purpose of the plugin is to beautify post titles, post contents, and comments of your WordPress blog. In post contents and comments, the text is made sentence case. In post titles, it is made title case, so all words are capitalized except for a user-defined list of exceptions, such as: of, an, the, etc. It is really targeted at persons with a refined sense of text aesthetics and people who just want their content to look nicer.</p>
<p><span id="more-304"></span>
<div style="float:left;margin:0 10px 10px 0">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-7639656561235411";
/* Square (250x250) */
google_ad_slot = "8522038794";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
The plugin will also disallow the posting of bothersome repetitive characters. For example, consider someone who uses excessive exclamation marks!!!!! Those will be trimmed down to just a single one! You can define the list of characters that should not be repeated.</p>
<p>Another aesthetic improvement it offers is converting quotation marks, apostrophes, and commas into their &#8220;curly&#8221; equivalents. You can enable or disable any one, so if you only want double quotes made curly, it is supported.</p>
<p>There are a couple of string user customizations allowed regarding full strings. First, you can define a list of terms for which the case must be preserved. One of the issues with beautifying a body of text is that it may turn lowercase or uppercase terms that are supposed to be capitalized or lowercase, respectively. Some examples are: iPhone, Los Angeles, PHP. The second type of customization is to replace any string with another. If you, for example, wanted to expand any occurrence of &#8220;Dr.&#8221; to &#8220;Doctor&#8221; or from &#8220;vs&#8221; to &#8220;versus&#8221; that would be possible. (These are pretty mundane examples, but I&#8217;m sure you can imagine lots of possibilities for this feature.)</p>
<p>Anyway, I hope you check it out and find it useful. If so, let me know with a comment below. Thanks!</p>
]]></content:encoded>
			<wfw:commentRss>https://rommelsantor.com/clog/2012/02/09/text-beautify-wordpress-plugin/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>PHP Human File Size Function</title>
		<link>https://rommelsantor.com/clog/2011/11/19/php-human-file-size-function/</link>
		<comments>https://rommelsantor.com/clog/2011/11/19/php-human-file-size-function/#comments</comments>
		<pubDate>Sat, 19 Nov 2011 08:16:59 +0000</pubDate>
		<dc:creator><![CDATA[rommel]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[function]]></category>
		<category><![CDATA[language]]></category>

		<guid isPermaLink="false">http://rommelsantor.com/clog/?p=281</guid>
		<description><![CDATA[Just found myself needing to display bytes in a human readable format. There are countless examples that use a lot of complex techniques to achieve this, but I wanted a simpler solution. This is the method that came to mind. Rather than basing my algorithm on the numeric value, it is based on the length [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Just found myself needing to display bytes in a human readable format. There are countless examples that use a lot of complex techniques to achieve this, but I wanted a simpler solution. This is the method that came to mind. Rather than basing my algorithm on the numeric value, it is based on the length of the bytes.</p>
<p><span id="more-281"></span>
<pre>
function human_filesize($bytes, $decimals = 2) {
  $sz = 'BKMGTP';
  $factor = floor((strlen($bytes) - 1) / 3);
  return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor];
}
</pre>
<p>
<div style="float:left;margin:0 10px 10px 0">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-7639656561235411";
/* Square (250x250) */
google_ad_slot = "8522038794";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<br />
This will return the number with the appropriate initial (B for bytes, K for kilobytes, M for megabytes, etc.) appended and the numeric with the specified number of decimal digits. It&#8217;s obviously pretty straightforward, but I always like coming up with a new way to do things and this is a faster solution than probably most if not all I&#8217;ve come across.</p>
<p><script type="text/javascript">//< ![CDATA[
$("pre").attr({name:'code'}).addClass('php:nocontrols:nogutter');
//]]&gt;</script></p>
]]></content:encoded>
			<wfw:commentRss>https://rommelsantor.com/clog/2011/11/19/php-human-file-size-function/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP Uppercase Sentences</title>
		<link>https://rommelsantor.com/clog/2011/11/14/php-uppercase-sentences/</link>
		<comments>https://rommelsantor.com/clog/2011/11/14/php-uppercase-sentences/#comments</comments>
		<pubDate>Mon, 14 Nov 2011 18:25:44 +0000</pubDate>
		<dc:creator><![CDATA[rommel]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[function]]></category>
		<category><![CDATA[grammar]]></category>
		<category><![CDATA[language]]></category>
		<category><![CDATA[sentence]]></category>
		<category><![CDATA[text]]></category>
		<category><![CDATA[ucfirst]]></category>
		<category><![CDATA[uppercase]]></category>

		<guid isPermaLink="false">http://rommelsantor.com/clog/?p=248</guid>
		<description><![CDATA[I&#8217;ve never really had a need to write code to uppercase only sentences in a string, but I now am dealing with large blocks of text content that is often written all uppercase by the author. So I popped on over to the PHP manual. I was pretty certain no such function existed in the [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve never really had a need to write code to uppercase only sentences in a string, but I now am dealing with large blocks of text content that is often written all uppercase by the author. So I popped on over to the <a href="http://php.net/manual/en/function.ucfirst.php" target="_blank" rel="nofollow">PHP manual</a>. I was pretty certain no such function existed in the language, but thought I&#8217;d check if one was added in a newer version.</p>
<p>Alas, no such function existed, so I wrote one myself<span id="more-248"></span>, but in the process of looking at the manual, I noticed a lot of different, very lengthy implementations of functions to make sentences uppercase. For example, this snippet was posted by <a href="http://www.php.net/manual/en/function.ucfirst.php#86902" target="_blank" rel="nofollow">mattalexxpub</a>:</p>
<pre>
function sentence_case($string) {
    $sentences = preg_split('/([.?!]+)/', $string, -1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);
    $new_string = '';
    foreach ($sentences as $key => $sentence) {
        $new_string .= ($key &#038; 1) == 0?
            ucfirst(strtolower(trim($sentence))) :
            $sentence.' ';
    }
    return trim($new_string);
}

print sentence_case('HMM. WOW! WHAT?');

// Outputs: "Hmm. Wow! What?"
</pre>
<p>And this snippet was posted by <a href="http://www.php.net/manual/en/function.ucfirst.php#76384" target="_blank" rel="nofollow">adefoor</a>:</p>
<pre>
function sentence_cap($impexp, $sentence_split) {
    $textbad=explode($impexp, $sentence_split);
    $newtext = array();
    foreach ($textbad as $sentence) {
        $sentencegood=ucfirst(strtolower($sentence));
        $newtext[] = $sentencegood;
    }
    $textgood = implode($impexp, $newtext);
    return $textgood;
}

$text = "this is a sentence. this is another sentence! this is the fourth sentence? no, this is the fourth sentence.";
$text = sentence_cap(". ",$text);
$text = sentence_cap("! ",$text);
$text = sentence_cap("? ",$text);

echo $text; // This is a sentence. This is another sentence! This is the fourth sentence? No, this is the fourth sentence.
</pre>
<p>The long examples continue. I don&#8217;t know if there are any better examples in the manual because there was too much to read through, but here&#8217;s my solution, which does the sentence uppercasing completely and in a single line of code:</p>
<pre>
function ucsentence($i_str, $i_lowercase = false) {
  $i_lowercase &#038;&#038; ($i_str = strtolower($i_str));
  return preg_replace('/(^|[\.!?]"?\s+)([a-z])/e', '"$1" . ucfirst("$2")', $i_str);
}
</pre>
<p>You can pass any string as an argument and it will properly uppercase the first letter of each sentence, including if punctuation is contained within quotes. If you specify a non-empty second argument, the function will first make the entire input string lowercase. This is useful when the string is all uppercase, but the default is to not touch the rest of the string.</p>
<p>
<div style="float:left;margin:0 10px 10px 0">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-7639656561235411";
/* Square (250x250) */
google_ad_slot = "8522038794";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<br />
It&#8217;s pretty straightforward, but for the less familiar with regular expressions, I&#8217;ll explain. The function uses a regular expression to match either of two cases:
<ol>
<li>the beginning of the string followed by a lowercase alphabetic</li>
<li>a period (.), exclamation (!), or question mark (?) optionally followed by a quotation mark (&#8220;), followed by a lowercase alphabetic</li>
</ol>
<p>If either of those cases is matched, preg_replace will execute the code in its second argument, which prepends the leading character(s), if any, to the uppercase version of alphabetic.</p>
<p>Et voila. Your string is sentence-cased. There are, of course, some caveats. For instance, there are many cases where your string could contain proper nouns, initials, or abbreviations and those such cases might not be handled as you&#8217;d like. Here are a couple examples with undesired output:</p>
<pre>
$str = 'A FOX NAMED MURPHY BROWN JUMPED OVER THE LAZY DOGS.';
echo ucsentence($str, true);// make it lowercase first because it's all upper
// desired output: A fox named Murphy Brown jumped over the lazy dogs.
// actual output: A fox named murphy brown jumped over the lazy dogs.
</pre>
<pre>
$str = 'the bottle contained five oz. of water.';
echo ucsentence($str);
// desired output: The bottle contained five oz. of water.
// actual output: The bottle contained five oz. Of water.
</pre>
<p>There&#8217;s unfortunately nothing much we can do about things like that except building an extensive list of special circumstances where we wouldn&#8217;t want a period to be considered the end of a sentence. I think we&#8217;ll survive with it as-is.</p>
<p><script type="text/javascript">//< ![CDATA[
$("pre").attr({name:'code'}).addClass('php:nocontrols:nogutter');
//]]&gt;</script></p>
]]></content:encoded>
			<wfw:commentRss>https://rommelsantor.com/clog/2011/11/14/php-uppercase-sentences/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PHP 5.3 Class Friendship Support</title>
		<link>https://rommelsantor.com/clog/2011/04/23/php-5-3-class-friendship-support/</link>
		<comments>https://rommelsantor.com/clog/2011/04/23/php-5-3-class-friendship-support/#comments</comments>
		<pubDate>Sun, 24 Apr 2011 00:56:27 +0000</pubDate>
		<dc:creator><![CDATA[rommel]]></dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://rommelsantor.com/clog/?p=186</guid>
		<description><![CDATA[One of the useful features of OOP languages like C++ is class friendship via the friend keyword. What this allows you to do is define a class that permits other explicitly named classes to touch its private parts. For an overly simple example, let&#8217;s say you have a User class that carries its user info [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>One of the useful features of OOP languages like C++ is class friendship via the friend keyword. What this allows you to do is define a class that permits other explicitly named classes to touch its private parts.</p>
<p>For an overly simple example, let&#8217;s say you have a User class that carries its user info privately, but you also have a Logger class for writing error and info message to a log. If you tried the following, you&#8217;d hit errors telling you that the User properties &#8220;id&#8221; and &#8220;nick&#8221; are private:
<pre>class User {
  private $id;
  private $nick;
  // ...
}

class Logger {
  // ...
  public static function write($str) {
    $user = User::get_current_user();
    fwrite(self::$handle, "User: {$user->nick} ({$user->id}): {$str}\n");
  }
}</pre>
<p>In C++ you could add a simple line to class User like:</p>
<pre>friend class Logger;</pre>
<p>This would permit the Logger class to access any of its private or protected properties and methods. Despite there being numerous people who demand that you should redesign your code instead of using class friendship, there are many cases where friendship is not only useful but necessary. This is all good and fine except for the fact that the PHP language does not have support for friend classes, nor do its developers have any intention of adding it (the last I heard from the PHP team is they long ago decided against such functionality).</p>
<p>This led me to develop a workaround, which wouldn&#8217;t have been possible in the past, but with the flexibility of PHP5.3 and late-static binding, it is now possible. So, without further ado, here&#8217;s my implementation of class Friendship.<br />
<span id="more-186"></span></p>
<pre>class Friendship {
  private static function friend_error($i_type, $i_name, $i_sep = '-&gt;') {
    $bt = debug_backtrace();
    $caller = $bt[1];

    $msg = array();
    !empty($caller['file']) &#038;&#038; $msg[] = $caller['file'];
    !empty($caller['line']) &#038;&#038; $msg[] = "(Line {$caller['line']})";
    $msg[] = "attempted to access inaccessible {$i_type}:";
    $msg[] = get_called_class() . "{$i_sep}{$i_name}";
    $msg = implode(' ', $msg);

    trigger_error($msg, E_USER_ERROR);
  }

  private static function backtrace_test($i_callee = null) {
    $db = debug_backtrace();
    $i = 2;
    do {
      $bt = @$db[$i++];

      if (empty($bt['file']))
        $bt = null;
      else if (preg_match('#^(' . __NAMESPACE__ . ')?\\\\?(call_user_func|call_user_func_array)$#i', @$bt['function']))
        $bt = null;
      else if (@$bt['file'] == __FILE__ || __CLASS__ == @$bt['class'])
        $bt = null;
      else if ($i_callee) {
        if (0 == strcasecmp(get_called_class(), @$bt['class']) &#038;&#038;
            0 == strcasecmp($i_callee, @$bt['function']))
        {
          $bt = @$db[$i];
          break;
        }
      }
    } while ($i &lt; count($db) &#038;&#038; empty($bt));

    $class = @$bt['class'];
    $func = @$bt['function'];

    if (is_subclass_of(get_called_class(), $class))
      return true;

    $prep = function($s) {
		$ns = function($i_name) {
		  if (!is_scalar($i_name))
			return $i_name;
		  return strpos($i_name, '\\') !== false ? $i_name : (__NAMESPACE__ . '\\' . $i_name);
		};
		return strtolower($ns($s));
	};

    $friends = array_map($prep, static::get_friend_classes());

    if (strpos($class, '\\') === false)
      $class = '\\' . $class;
    return in_array(strtolower($class), $friends);
  }

  protected static function get_friend_classes() {
    return array();
  }
  
  public function __call($i_name, $i_args) {
    if (!method_exists($this, $i_name)) {
      $bt = debug_backtrace();
      $bt = $bt[1];
      trigger_error($bt['file'] . ' (Line ' . $bt['line'] . ') ' .
        'call to non-existent method ' . get_called_class() . '-&gt;' .
        $i_name . '()', E_USER_WARNING);
      return null;
    }

    !$this-&gt;backtrace_test($i_name) &#038;&#038; self::friend_error('method', $i_name . '()');

    $rm = new \ReflectionMethod($this, $i_name);
    $accessible = $rm-&gt;isPrivate() || $rm-&gt;isProtected();
    $rm-&gt;setAccessible(true);
    $ret = $rm-&gt;invokeArgs($this, $i_args);
    $rm-&gt;setAccessible($accessible);
    return $ret;
  }

  public static function __callStatic($i_name, $i_args) {
    if (!method_exists(get_called_class(), $i_name)) {
      $bt = debug_backtrace();
      $bt = $bt[1];
      trigger_error($bt['file'] . ' (Line ' . $bt['line'] . ') ' .
        'call to non-existent static method ' . get_called_class() . '::' .
        $i_name . '()', E_USER_WARNING);
      return null;
    }

    !self::backtrace_test($i_name) &#038;&#038; self::friend_error('static method', $i_name . '()', '::');

    $rm = new \ReflectionMethod(get_called_class(), $i_name);
    $accessible = $rm-&gt;isPrivate() || $rm-&gt;isProtected();
    $rm-&gt;setAccessible(true);
    $ret = $rm-&gt;invokeArgs(null, $i_args);
    $rm-&gt;setAccessible($accessible);
    return $ret;
  }

  public function __get($i_var) {
    if (!property_exists($this, $i_var)) {
      $bt = debug_backtrace();
      $bt = $bt[1];
      trigger_error($bt['file'] . ' (Line ' . $bt['line'] . ') ' .
        'attempted to access to non-existent property ' . get_called_class() . '-&gt;' .
        $i_var, E_USER_NOTICE);
      return null;
    }

    !self::backtrace_test() &#038;&#038; self::friend_error('property', '$' . $i_var);
    return $this-&gt;$i_var;
  }

  public function __set($i_var, $i_value) {
    if (property_exists($this, $i_var))
      !self::backtrace_test() &#038;&#038; self::friend_error('property', '$' . $i_var);

    $rp = new \ReflectionProperty($this, $i_var);
    $accessible = $rp-&gt;isPrivate() || $rp-&gt;isProtected();
    $rp-&gt;setAccessible(true);
    $rp-&gt;setValue($this, $i_value);
    $rp-&gt;setAccessible($accessible);
    return $i_value;
  }

  public function __isset($i_var) {
    if (!property_exists($this, $i_var))
      return false;

    !self::backtrace_test() &#038;&#038; self::friend_error('property', '$' . $i_var);

    $rp = new \ReflectionProperty($this, $i_var);
    $accessible = $rp-&gt;isPrivate() || $rp-&gt;isProtected();
    $rp-&gt;setAccessible(true);
    $value = $rp-&gt;getValue($this);
    $rp-&gt;setAccessible($accessible);
    return $value !== null;
  }

  public function __unset($i_var) {
    if (property_exists($this, $i_var))
      !self::backtrace_test() &#038;&#038; self::friend_error('property', '$' . $i_var);

    // we are not able to truly unset private properties, so we'll just make them null
    $rp = new \ReflectionProperty($this, $i_var);
    $accessible = $rp-&gt;isPrivate() || $rp-&gt;isProtected();
    $rp-&gt;setAccessible(true);
    $rp-&gt;setValue($this, null);
    unset($this-&gt;$i_var);
    $rp-&gt;setAccessible($accessible);
  }

  //
  // the functions below are for a future version of PHP
  //
  /*
  public static function __getStatic($i_var) {
  }

  public static function __setStatic($i_var, $i_value) {
  }

  public static function __issetStatic($i_var) {
  }

  public static function __unsetStatic($i_var) {
  }
  */
}</pre>
<p>
<div style="float:left;margin:0 10px 10px 0">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-7639656561235411";
/* Square (250x250) */
google_ad_slot = "8522038794";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<br />
Just derive from Friendship and override the get_friend_classes() method. The latter is for global functions, not class methods. I designed it to take into consideration the current namespace and will adjust the specified friends accordingly.</p>
<p>Here&#8217;s an example of how you can use class Friendship:</p>
<pre>class Restricted extends Friendship {
  private $priv_var;
  protected $prot_var;
  public $pub_var;

  protected static function get_friend_classes() {
    return array('Buddy');
  }

  private static function private_static_func() {
    echo __CLASS__ . '::' . __FUNCTION__ . '()&lt;br&gt;';
  }

  private function private_func() {
    echo __CLASS__ . '::' . __FUNCTION__ . '()&lt;br&gt;';
    echo 'I am a ';
    print_r($this);
  }
}

class Buddy {
  public static function touch_privates() {
    Restricted::private_static_func();

    $r = new Restricted();
    $r-&gt;priv_var = 'I changed this private property';
    $r-&gt;prot_var = 'Now a protected one';
    $r-&gt;pub_var = 'Public... not so special';

    $r-&gt;private_func();

    unset($r-&gt;priv_var);
    unset($r-&gt;prot_var);
    unset($r-&gt;pub_var);

    $r-&gt;private_func();

    echo "After unset()'ing, the public property is gone, but private and protected still exist as nulls.&lt;br&gt;";
  }
}

class Stranger {
  public static function deny_privates() {
    // none of these statements will work
    Restricted::private_static_func();

    $r = new Restricted();
    $r-&gt;priv_var = 'I cannot change this private property';
    $r-&gt;prot_var = 'Nor a protected one';
    $r-&gt;private_func();
  }
}

Buddy::touch_privates();
echo '&lt;hr/&gt;';
Stranger::deny_privates();</pre>
<p>The output of the above example is:<br />
<tt><br />
MyNS\Restricted::private_static_func()<br />
MyNS\Restricted::private_func()</p>
<p>I am a MyNS\Restricted Object<br />
(<br />
    [priv_var:MyNS\Restricted:private] =&gt; I changed this private property<br />
    [prot_var:protected] =&gt; Now a protected one<br />
    [pub_var] =&gt; Public... not so special<br />
)</p>
<p>MyNS\Restricted::private_func()</p>
<p>I am a MyNS\Restricted Object<br />
(<br />
    [priv_var:MyNS\Restricted:private] =&gt;<br />
)</p>
<p>After unset()'ing, the public property is gone, but private and protected still exist as nulls.</p>
<p>2011-04-23 17:32:28 -0700 - *E_USER_ERROR*<br />
  /var/www/index.php (Line 52) attempted to access inaccessible static method: MyNS\Restricted::private_static_func()<br />
  /var/www/friendship.php (Line 17)<br />
</tt></p>
<p>Some limitations are:
<ul>
<li>setting/getting static properties is not possible due to PHP&#8217;s lack of __getStatic(), __setStatic(), __issetStatic(), and __unsetStatic() magic methods</li>
<li>private properties cannot be unset(), so they&#8217;re just made null</li>
</ul>
<p><br/>I haven&#8217;t fully tested this in a great variety of examples, but at the very least, it does work as desired in all obvious, simple cases. I&#8217;m not pleased that I had to resort to using a lot of Reflection functionality, but I did just want some way to make any kind of friendship possible in PHP and I believe I&#8217;ve accomplished that. If you notice any issues or have any suggestions for improvement, please do let me know. Thanks for reading!</p>
<p><script type="text/javascript">//< ![CDATA[
/*$("pre").attr({name:'code'}).addClass('php:nocontrols:nogutter');*/
//]]&gt;</script></p>
]]></content:encoded>
			<wfw:commentRss>https://rommelsantor.com/clog/2011/04/23/php-5-3-class-friendship-support/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP 5.3 Dynamic Namespace Resolution</title>
		<link>https://rommelsantor.com/clog/2011/04/10/php-5-3-dynamic-namespace-resolution/</link>
		<comments>https://rommelsantor.com/clog/2011/04/10/php-5-3-dynamic-namespace-resolution/#comments</comments>
		<pubDate>Mon, 11 Apr 2011 05:52:23 +0000</pubDate>
		<dc:creator><![CDATA[rommel]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[namespace]]></category>
		<category><![CDATA[php 5.3]]></category>

		<guid isPermaLink="false">http://rommelsantor.com/clog/?p=176</guid>
		<description><![CDATA[As PHP continues evolving, it just keeps getting better and better. One of the features added in version 5.3 is support for namespaces. If you&#8217;ve started trying to actually use PHP namespaces, you&#8217;ve probably run into some of the more obvious quirks that require you to either retrofit your code or implement a workaround. I [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>As PHP continues evolving, it just keeps getting better and better. One of the features added in version 5.3 is support for <a href="http://www.php.net/manual/en/language.namespaces.rationale.php">namespaces</a>. If you&#8217;ve started trying to actually use PHP namespaces, you&#8217;ve probably run into some of the more obvious quirks that require you to either retrofit your code or implement a workaround. I started with the former before realizing that thanks to the namespace feature itself, a simple set of workarounds could do the job.</p>
<p>Specifically, I&#8217;m referring to the fact that namespace resolution happens at compile time, which means that if you attempt to reference a namespaced class or method as a string, it won&#8217;t be recognized unless that string explicitly includes the namespace name. The most apparent case is when calling <code>class_exists()</code>. For example, let&#8217;s say you define class Settings in namespace OssumCMS:</p>
<pre>namespace OssumCMS;

class Settings {
  const MEMCACHED_ADDR = 'none';
  public static function do_something() {
  }
}</pre>
<p>In your code, you might want to do some things like:</p>
<pre>// ...
if (class_exists('Settings'))
  if (@constant('Settings::MEMCACHED_ADDR') != 'none')
    call_user_func(array('Settings', 'do_something'));</pre>
<p>But that would never work because class Settings is defined within namespace OssumCMS. PHP resolves namespaces at compile time, so when class_exists(), constant(), and call_user_func() are called at run time, they won&#8217;t ever find class Settings because it&#8217;s checking only the global namespace.<span id="more-176"></span> The obvious fix is to include the namespace name before every occurrence of the class name:</p>
<pre>// ...
if (class_exists('OssumCMS\Settings'))
  if (@constant('OssumCMS\Settings::MEMCACHED_ADDR') != 'none')
    call_user_func(array('OssumCMS\Settings', 'do_something'));</pre>
<p>Now PHP will know to check for the class within the namespace in which it&#8217;s actually defined. Small victory, especially when you&#8217;re dealing with thousands of lines of pre-existing code. You definitely don&#8217;t want to find every occurrence of every class and prefix it with the namespace. Another small step in the right direction would be to use a function to automatically prefix a string with the current namespace if needed by using a function:</p>
<pre>namespace OssumCMS;

function ns($i_name) {
  if (!is_scalar($i_name))
    return $i_name;
  return strpos($i_name, '\\') !== false ? $i_name : (__NAMESPACE__ . '\\' . $i_name);
}</pre>
<p>This would allow you to simply wrap all your class name strings in that function call, for example:</p>
<pre>if (class_exists(ns($class_name)))
  do_something();</pre>
<p>
<div style="float:left;margin:0 10px 10px 0">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-7639656561235411";
/* Square (250x250) */
google_ad_slot = "8522038794";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<br />
But that would still require you to traverse all line of all your source code files doing a search/replace. Wouldn&#8217;t it be easier if instead of manipulating your class name references, you could override the built-in PHP functions? In the old days, you wouldn&#8217;t be able to do something like that, but thanks to namespaces, it&#8217;s entirely possible. All we have to do is create our own class_exists(), constant(), and call_user_func() type functions within our own namespace and add to string arguments the namespace prefix whenever necessary, then call the corresponding global functions.</p>
<pre>namespace OssumCMS;

function ns($i_name) {
  if (!is_scalar($i_name))
    return $i_name;
  return strpos($i_name, '\\') !== false ? $i_name : (__NAMESPACE__ . '\\' . $i_name);
}

function un_ns($i_name) {
  if (!is_scalar($i_name))
    return $i_name;
  return preg_replace('#^' . preg_quote(__NAMESPACE__, '#') . '\\#i', '', $i_name);
}

function constant($i_name)        { return @\constant(ns($i_name)); }
function class_exists($i_name)    { return \class_exists(ns($i_name)); }

function call_user_func_array($i_func, $i_args) {
  is_array($i_func)
    ? (!is_object($i_func[0]) &#038;&#038; ($i_func[0] = ns($i_func[0])))
    : (!is_object($i_func) &#038;&#038; !function_exists($i_func) &#038;&#038; ($i_func = ns($i_func)));
  return \call_user_func_array($i_func, $i_args);
}

function call_user_func($i_func) {
  return call_user_func_array($i_func, array_shift($args = func_get_args()));
}</pre>
<p>Given these overrides, our example block of code would be evaluated as follows</p>
<pre>// ...
if (OssumCMS\class_exists(OssumCMS\ns('Settings')))
  if (OssumCMS\constant(OssumCMS\ns('Settings::MEMCACHED_ADDR')) != 'none')
    OssumCMS\call_user_func(array(OssumCMS\ns('Settings'), 'do_something'));</pre>
<p>There are surely other functions that need overriding, but these are the most obvious suspects. This was a useful little hack for me and I hope you find it useful as well.</p>
<p><script type="text/javascript">//< ![CDATA[
$("pre").attr({name:'code'}).addClass('php:nocontrols:nogutter');
//]]&gt;</script></p>
]]></content:encoded>
			<wfw:commentRss>https://rommelsantor.com/clog/2011/04/10/php-5-3-dynamic-namespace-resolution/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PHP Shared Session Encoding Solution</title>
		<link>https://rommelsantor.com/clog/2011/02/06/php-shared-session-encoding-solution/</link>
		<comments>https://rommelsantor.com/clog/2011/02/06/php-shared-session-encoding-solution/#comments</comments>
		<pubDate>Sun, 06 Feb 2011 20:24:40 +0000</pubDate>
		<dc:creator><![CDATA[rommel]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[suhosin session mediawiki]]></category>

		<guid isPermaLink="false">http://rommelsantor.com/clog/?p=140</guid>
		<description><![CDATA[I came up against a really baffling problem the other day. I was tasked with adding a Wiki for VideoSift. Rather than just dumping MediaWiki onto the primary VideoSift web server, we wanted to keep it self-contained for security and load reasons, so we installed into one of our other back-end servers which was being [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I came up against a really baffling problem the other day. I was tasked with adding a <a href="http://wiki.videosift.com">Wiki for VideoSift</a>. Rather than just dumping MediaWiki onto the primary VideoSift web server, we wanted to keep it self-contained for security and load reasons, so we installed into one of our other back-end servers which was being used as a MySQL Slave and not hosting any web content. To start with I just did a quick, basic install of Apache2 and PHP5 (I would prefer and attempted to use Nginx with PHP5-FPM, but MediaWiki complains about implementation bugs in the packaged versions available to me and I don&#8217;t want to recompile from source).</p>
<p><span id="more-140"></span>
<div style="float:left;margin:0 10px 10px 0">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-7639656561235411";
/* Square (250x250) */
google_ad_slot = "8522038794";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
</p>
<p>I have never dealt with MediaWiki previously, so I just went and setup the wiki.videosift.com subdomain to load from the back-end server then downloaded the tarball into the document root and went through the install process. I spent an inordinate amount of time figuring out how it might be possible to synchronize existing VideoSift member accounts and logins seamlessly into the Wiki, (but the details of how I did that are for another story, which I may clog about soon). All of my software changes seemed to make sense and even after in-depth inspection should have been functioning properly, but if anyone went from VideoSift to the Wiki or vice versa, they were instantly automatically being logged out of both.</p>
<p>After spending many clueless hours debugging back and forth, I finally found that the <a href="http://www.php.net/manual/en/book.session.php" target="_blank">sessions</a> designed to be properly shared across the two servers was to blame. The session data on one server would be written to a centralized session depot and the other server should have read that session data, allowing the session to persist across both websites.</p>
<p>I use <a href="http://www.php.net/manual/en/function.session-set-save-handler.php" target="_blank">session_set_save_handler()</a> to manipulate how sessions are managed, so I put in some debug code on both servers to dump the raw session data that was being read and written. To my surprise they were totally different. On the Wiki the session data was a normal session-serialized string of variable data like this:<br />
<tt>&nbsp;&nbsp;test|s:3:"sdf";</tt><br />
but the VideoSift session contained a seemingly random string of characters:<br />
<tt>&nbsp;&nbsp;3GdlPEGr2kYgRFDs-pUSoKomZ4fN7r5BM5oKOCMsWNc</tt></p>
<p>After a lot more digging and googling, I finally came across <a href="http://www.php.net/manual/en/function.session-set-save-handler.php#89564" target="_blank">this comment at php.net</a>. Unbeknownst  to me, as a security measure, the <a href="http://www.hardened-php.net/suhosin/index.html" target="_blank">suhosin module</a> for PHP was using its <a href="http://www.hardened-php.net/suhosin/configuration.html#transparent_encryption_options" target="_blank">Transparent Encryption Options</a> to automatically encrypt all session data as it was being written.</p>
<p>This is a good idea and I&#8217;m glad to leave encryption on, but why was it being encrypted differently on the two servers? Suhosin by default uses a couple of different pieces of information as its session encryption key. One of the enabled session encryption options (see the previous link) is &#8220;suhosin.session.cryptdocroot&#8221; which includes the path to the website&#8217;s document root in its encryption key. Since VideoSift and the Wiki are located in a different folder on each server, this was causing the shared session data written by one server to be unreadable (un-decryptable really) by the other server.</p>
<p>There are a couple of obvious solutions, and since I&#8217;d prefer to maintain whatever shreds of security are already in place, I opted to specify a shared session encryption key on both servers (using suhosin&#8217;s suhosin.session.cryptkey option) and disable the suhosin.session.cryptdocroot option. Et voila, she works.</p>
]]></content:encoded>
			<wfw:commentRss>https://rommelsantor.com/clog/2011/02/06/php-shared-session-encoding-solution/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
