Archive for July, 2009
PHP Magic __get, __set Methods, and Retaining Private and Protected Properties
I have been making an integration with a complex API with hundreds of potential user provided variables, necessitating me use of PHP’s Magic __get and __set methods.
Unfortunately, by using these methods, PHP’s restriction on private and protected properties is bypassed, making all properties public. This is completely unacceptable from my coding perspective.
This class model overrides the magic __get and __set’s ability to alter and access private and protected properties. Public properties are unaffected. This script also allows the class to set and access private and protected properties.
<?php class setter_getter_respect { private $current_page; private $private_properties = array(); public function __construct() { $class = new ReflectionClass(__CLASS__); $this->current_page = $class->getFileName(); $class_properties = get_class_vars(__CLASS__); foreach($class_properties as $class_property_name => $property_value) { $prop = new ReflectionProperty(__CLASS__, $class_property_name); if($prop->isPrivate() || $prop->isProtected()) { $this->private_properties[$prop->getName()] = ($prop->isPrivate()) ? 'private' : 'protected'; } } } public function __set($var, $val) { $requesting_page = debug_backtrace(); if(($requesting_page[0]['file'] != $this->current_page) && (array_key_exists($var,$this->private_properties))) { trigger_error("Cannot access ".$this->private_properties[$var]." property ".__CLASS__."::".$var." in ".$requesting_page[0]['file']."on line ". $requesting_page[0]['line'],E_USER_ERROR); } $this->$var = $val; } public function __get($var) { $requesting_page = debug_backtrace(); if(isset($this->$var)){ if(($requesting_page[0]['file'] != $this->current_page) && (array_key_exists($var,$this->private_properties))) { trigger_error("Cannot access ".$this->private_properties[$var]." property ".__CLASS__."::".$var." in ".$requesting_page[0]['file']."on line ". $requesting_page[0]['line'],E_USER_ERROR); } return $this->$var; } else { throw new Exception("Required property [" . $var . "] has not been set!"); } } } ?> |
Extended classes will not have access to __get or __set protected properties. I will alter this snippet when I find a suitable method of handling extended classes.
I’m hoping that php alters the way it handles private and protected properties through the magic methods but until then, this is a way to semi-preserve private and protected properties.
US States Snippet and SQL Dump
Here’s some US states snippets. Included are php arrays, and a MySQL states dump…
PHP – Script benchmark / bottleneck debugging snippet
Here’s a really simple function that I use for finding bottlenecks in php scripts. You can add any number of steps to the the script using the microtime() function, and this function shows the execution time of each step.
/** * Benchmark a php script * * @param array $time_sample * @return string HTML */ function quick_benchmark($time_sample = array()) { $steps = count($time_sample); $output = ''; for($i=0;$i<$steps;$i++) { if($i<($steps-1)) { $output .= '<p>Time '. ($i+1) .': '. number_format(($time_sample[$i+1] - $time_sample[$i]),6,'.','') .' seconds.</p>'; } } $output .= '<p>Total time: '. number_format(($time_sample[$steps-1] - $time_sample[0]),6,'.','') .' seconds.</p>'; return $output; } |
This is a simple example using sleep() to demonstrate the output.
$time_sample[] = microtime(true); //start sleep(1); $time_sample[] = microtime(true); //time 1 sleep(2); $time_sample[] = microtime(true); //time 2 sleep(3); $time_sample[] = microtime(true); //time 3 sleep(1); $time_sample[] = microtime(true); //time 4 echo quick_benchmark($time_sample); |
The script outputs:
Time 1: 1.001833 seconds.
Time 2: 2.001427 seconds.
Time 3: 3.001124 seconds.
Time 4: 1.001720 seconds.
Total time: 7.006104 seconds.
It’s a good idea to comment each time you record a microtime so that you know which section of script took that amount of time.
PHP – Random string generator snippet
This is a little function that I use all the time to generate random strings. There are 3 options for random strings with this: Alpha, Alpha-numeric, and Alpha-numeric with symbols. This is important because sometimes it’s a good idea not to allow special characters in a php string. However, the special characters are great if you need to create a key or initialization vector for 2 way encryption.
This can be used to generate random passwords or keys or just about anything else that needs a random string. You can also throw this directly into a class and use it as a static method.
/** * Generate a random string * * @param int $length * @param int $mode 1 = Alpha, 2 = Alpha-numeric, 3 = Alpha-numeric with symbols * @param boolian $char_set Set true for Upper and Lower case letters * @return string */ function random_string($length=16,$mode=1,$char_set=false) { $string = ''; $possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; if($char_set) { $possible .= strtolower($possible); } switch($mode) { case 3: $possible .= '`~!@#$%^&*()_-+=|}]{[":;<,>.?/'; case 2: $possible .= '0123456789'; break; } for($i=1;$i<$length;$i++) { $char = substr($possible, mt_rand(0, strlen($possible)-1), 1); $string .= $char; } return $string; } |
Examples:
echo random_string(32); //WQTISVJVMWSEFXEIQISJPCBENFEHQAN |
echo random_string(16,2,true); //cZhVGHJb0PqJIk3 |
echo random_string(16,3); //=,:UT__GN[ST>GH |
25 Point Basic MySQL Setup/Optimization Checklist
Daily I run into new web programmers that are using PHP and MySQL to create their blogs and websites. I created this checklist as a guide for new and experienced to make sure they are covering the basics of a MySQL server setup.
This guide is by no means all inclusive, but should help to cover some of the major gaps in knowledge and commonly overlooked fundamentals that I run into on a daily basis.
The checklist is separated into 5 equal sections: Server Setup, Schema Design, Table Design, Index Optimization, Query Optimization, and a 6th Bonus Tips section.
PHP AES Encryption
Sometime it’s needed to use 2 way encryption for storing data. I’ve been using an AES encryption class for a little over a year now, and it is an excellent way to use FIPS Compliant AES encryption in php. The script comes in a free version (ECB mode only) and a paid version for only $10.
This is a completely standalone class that does not require the mcrypt library, and has php4 and php5 support. Encryption is available in 128, 192, and 256 bit, depending on the cipher length.
Using it is easy as this:
include("AES.class.php"); $my_256_key = 'MpDsw*8cQM&fez*7eBoZB^W*kP652NoW'; $initialization_vector = 'WmR&z28zWn8r*9$R'; $aes = new AES($my_256_key, "CBC", $initialization_vector); $string_to_encrypt = 'SOME STRING OF TEXT, OR EVEN AN ENTIRE FILE'; $encrypted_string = $aes->encrypt($string_to_encrypt); $original_string = $aes->decrypt($encrypted_string); |
The cipher modes that are supported are: Electronic Codebook (ECB), Cipher Block Chaining (CBC), Cipher Feedback (CFB), and Output Feedback (OFB). —Block Cipher Modes »
If you are needing to integrate real encryption into a script, I highly recommend this class. It’s strong enough for storing sensitive data like credit cards (key management is another topic), and has an extremely easy interface.
Keep in mind that encryption is only as secure as the key and the key management that is used. Unlike using hash functions (Md5, SHA1), encryption can be reversed, and will considerably slow down a php script, especially so for encrypting large amounts of data.
Database Storage:
I would recommend base 64 encoding an encrypted string and then storing in a text or blob type field. Output from AES encryption will likely be corrupted by a database’s character encoding if you do not.
PHP Multi-process 1.1.1 (Beta) Released
I just finished the second edition of the php multi-process script. Implementing it is significantly simpler now, and will allow mysql or sqlite implementation for the cache database.
The PHP Multi-process repository is now available at: http://github.com/jestep/PHP-Multi-process/tree/master.
Also, the usage guidelines can be found at: http://www.saynotoflash.com/scripts/php-multi-process/.
If you discover any problems, please log them here: http://github.com/jestep/PHP-Multi-process/issues
Still needing to implement:
Resource checking is a major component that needs to be addressed. If anyone has any suggestions or experience on how to check available resources, and would like to help out, please let me know.
PHP Multi-process dev page
I’ve created a final resting place for the PHP Multi-process script. This page will include all future updates as well as usage and other changes to the script.
Currently, I’m working on the Beta version of the script. From the feedback I’ve received, the script is mostly stable, and needs only minor changes considering its complexity.
The changes I’m currently anticipating for 1.1 beta are:
- Alternate: Mysql or Sqlite Implementation
- Server Resource Checking (RAM and CPU usage)
- Separating the DB, Parent, and Child classes
I’ve also come up with method of creating new scripts from the parent to process, however changes like this would most likely appear in an alternate or fork of the current script.
Again, if you’ve used the PHP Multi-process script and have any changes that you’ve made that have helped or would like to help support this script please let me know.
In case you missed it, here’s the link to PHP Multi-process script: http://www.saynotoflash.com/scripts/php-multi-process/