Sorting Arrays By Length in PHP

However, in the order given, the color names near the beginning of the array were shorter than the ones near the end of the array; for example, “green” came before “darkgreen.” As a result, after replacement occurred, “darkgreen” became “dark#4b4b4b” (by replacing only the “green” part with a hex equivalent, instead of the entire “darkgreen” part) instead of the darkgreen hex equivalent. Obviously this was unacceptable, so the easiest way to fix the problem was to sort the array in such a way that the shorter names occurred last. Fortunately, PHP allows you to create custom algorithms for sorting arrays, and that’s just what I’ve done.

  1. function sortByLength($a,$b){
  2. if($a == $b) return 0;
  3. return (strlen($a) > strlen($b) ? -1 : 1);
  4. }

Simple, yes, but effective.

Update: This code (written when I was more of a PHP novice) is erroneous. The following function is ideal. As mentioned in the comments, call this function using the PHP usort() (or similar callback) function.

  1. function sortByLength($a,$b){
  2. return (strlen($a) - strlen($b));
  3. }

March 24th, 2006 | 3 Remarks

Using PHP to maintain a specific filesize

The script started off with some simple configuration…

  1. <?php
  2. $file = 'data/data_tracker.txt';
  3. $maxlen = 300000; // bytes/chars before file truncation begins
  4. $input = '<p style="padding:0; line-height:130%;"><strong>'
  5. .'IP: '.getenv('REMOTE_ADDR'). "</strong><br />\n"
  6. .' <span style="font-size:85%;">DT: '.date("M jS, Y - g:i a"). "<br />\n"
  7. .' PG: '.getenv('REQUEST_URI'). "<br /></span></p>\n\n";
  8. ?>

The settings are pretty clear: $file is the location of the tracking file to be written to, $maxlen is the maximum filesize (in bytes) that $file can reach, and $input is what will be prepended to the file. Let’s move on.

  1. <?php
  2.  
  3. if(@$handle = fopen($file, 'r')){
  4. $data = @fread($handle, filesize($file));
  5. fclose($handle);
  6. }
  7.  
  8. while(strlen($data) > $maxlen){
  9. $temp = explode("\n\n", $data);
  10. unset($temp[count($temp)-1]);
  11. $data = implode("\n\n", $temp);
  12. }
  13.  
  14. if(@$handle = fopen($file, 'w')){
  15. fwrite($handle, $input.$data);
  16. fclose($handle);
  17. unset($file, $maxlen, $input, $data, $temp, $handle);
  18. }
  19.  
  20. ?>

The first thing we do is open and read the file. The contents of $file are loaded into the $data variable.

Next is the best part of the script. We run a while loop, checking the strlen() of the $data variable, and making sure that it is greater than the $maxlen. As long as it is, we can delete chunks of data at a time. We don’t want to remove each letter until it is at exactly $maxlen in bytes, but we want to remove the oldest chunks of data until the amount of bytes is less than or equal to $maxlen. Generally, the file size will be kept less than $maxlen, depending on the size of each chunk.

The last part just writes the new data, following truncation (if necessary), and prepends $input.

Anyway, I found this routine helpful and figured I’d share it with anyone who may be interested in accomplishing something similar. Download the entire code: tracker_3.txt.

December 11th, 2005 | 2 Remarks

Show Plugins in Your Sidebar

Now, to make this thing show up in my sidebar instead of in the footer, we don’t need a great deal of modification. Step one is to go to modify the plugin in your Plugins → Plugin Editor panel. When you select the Show Plugins plugin, the source will come up in a textarea and you can make changes to the plugin’s code. Simple enough, so what’ve we got? At the very bottom, you’ll notice this:


// Use object to avoid namespace collisions
$show_plugins = new Show_Plugins();
// We want to modify the meta section
add_action('wp_footer', array(&$show_plugins, 'wp_footer'));
// There is no action hook for "start of processing",
// so we use this implicitly.
$show_plugins->start();

The problem, obviously, is that it’s running this plugin in the footer. We don’t need any of the above code, so delete it. The start() function is empty, as you may have noticed, so we won’t be needing that, either. Delete it, too. Now we’re left with two functions, wp_footer() and get_plugin_data(). Rename wp_footer() to start() to avoid any possible compatibility issues (though I doubt it would be a problem, since this function is run within a class and is therefore a private function as opposed to a public one).

Now let’s make some changes to the start() function (which we renamed from wp_footer()). The end of the function is where an echo statement is, indicating HTML output. However, we want an unordered list… Right? (If not, skip this part.) Take a look at the following code.


echo("<div class=\"show-plugins\">" .
__("Plugins: ") .
join(', ', $plugins) . "</div>");

Change the above to something more elegant, like what I’ve done below. (Note that I’m referring to the output rather than the actual PHP code when I suggest that the solution is more elegant.)


echo(' <ul class="show-plugins">'."\n".' <li>'.
join('</li>'."\n".' <li>', $plugins).
' </ul>'."\n");

You’re done modifying the plugin! Save that bugger, and go to the Presentation → Theme Editor panel. Make sure you’re modifying the correct theme (the one your site’s using, or more than one if you have a theme-switcher) and locate the file you use for your sidebar to edit it (in the default theme, Kubrick, I believe the file is named “sidebar.php”). Decide where you want this list to appear, and place the following code in that place.


<?php
$show_plugins = new Show_Plugins();
$show_plugins->start();
?>

All the above does is creates a new Show_Plugins class and calls the start() function to output the HTML we want. You can use any kind of list in any kind of format. I did exactly what I showed in this blog entry (in the sidebar, I added an H3 that says “Wordpress Plugins”), so it should work for any Wordpress blog running WP 1.5 or greater. Hope this helps some of you folks out there!

June 18th, 2005 | Remark

Preprocessing PHP Includes

The problem, you see, is that I want to include a content file (for example, “content.php”). This file has an array of various texts and randomly outputs one of them. Here’s an example:


$ary = array("test asdf asdf and aasdfadsfa ", " asdf as ak and asdfa sldk a", " asidfu aoi j and a;lskjz.");
echo $ary[rand(0,count($ary)-1)];

Now, we can use include ("content.php"); in our PHP to include that random output on another PHP page, right? What if we wanted to change the word “and” to blue in the text that is output? We could do this in content.php, but if we have many various files like content.php, this would become a tedious process very quickly. Instead, we need to process the output of content.php before including it. So, let’s make a custom include function:

function inc($file){
if(@$handle = fopen($file,'r')){
$data = fread($handle, filesize($file));
fclose($handle);
} else {
return 'Error: Could not open file.';
}
return preg_replace("/\b(and)\b/i", '<span style="color: #00f;">$1</span>', $data);
}

What’s the problem with this? Well, when we read the file in this way, it doesn’t process the PHP in the included file. Uh oh! What do we do? If you’re using PHP5, there’s a really, really quick solution:

function inc($file){
$data = (include $file);
return preg_replace("/\b(and)\b/i", '<span style="color: #00f;">$1</span>', $data);
}

This doesn’t work for PHP4, though, so we have to use this:

function inc($file){
$temp = explode('/', $_SERVER["REQUEST_URI"]);
$temp = $temp[count($temp)-1];
$data = implode('',file('http://'.$_SERVER["SERVER_NAME"].str_replace($temp, 'content.php', $_SERVER["REQUEST_URI"])));
return preg_replace("/\b(and)\b/i", '<span style="color: #00f;">$1</span>', $data);
}

What we’re doing with all this mess is basically getting the full HTTP-address of the file that is being included, and then opening that file as if it were remote (even though it’s on the same server). This makes PHP include the file without outputting it so that we can process it in our own way, and then returns that value. By returning the value (instead of echoing it), we can also run it through other functions. That is, we can say echo str_replace("#00f", "#f00", inc("content.php")); if we want to use red instead of blue.

May 27th, 2005 | 2 Remarks