The first bit of code was a challenge to see if anyone could answer the question: What is the rational behind static methods being unable to use inherited members or methods.
- Code: Select all
<?php
class base
{
public $color = 'Blue';
public function get_color()
{
return $this->color;
}
}
class child extends base
{
public $color = 'Green';
}
// Static classes
class static_base
{
public static $color = 'Red';
public static function get_color()
{
return self::$color;
}
}
class static_child extends static_base
{
public static $color = 'Purple';
}
$base = new base();
echo $base->get_color(); // Prints Blue
echo "\n<br />\n";
$child = new child();
echo $child->get_color(); // Prints Green
echo "\n<br />\n";
echo static_child::get_color(); // Prints Red -- why?
// Using the same logic as the dynamic class, shouldn't this code print Purple?
echo "\n<br />\n";
?>
Answer to the above:
Spoiler:
Is there a workaround? There really are no 'Good' workarounds without duplicating code.
There are three workarounds that I'm aware of, but not great solutions except #1.
- Use a dynamic class instead of a static class.
- Set a member variable in the constructor. This makes the value available within the object as well as from the outside, though it is not static. Obviously not a great solution.
- The third way is to pass an extra class name parameter into the static method calls telling the method which class it should 'act as.' Again, not a great solution.
The second part of the lesson was how to do overloading in PHP. Most programmers are aware of the typical method of doing member overloading using the magic methods: __get, __set and __isset. But this is not possible with a static method. That is not to worry though, because there is still a way to do this with static classes, here is an example where we create a simple API to get a list of posts based on post time.
Enjoy!
- Code: Select all
<?php
class base
{
public static $object_data = array();
public static $classname = __CLASS__;
public static function get($arg)
{
if (!isset(self::$object_data[$arg]))
{
$args = func_get_args();
call_user_func_array(__CLASS__ . '::' . 'set', $args);
}
return self::$object_data[$arg];
}
public static function set($arg)
{
$args = func_get_args();
if (!method_exists(self::$classname, 'get_' . $arg))
{
self::$object_data[$arg] = $args[1];
}
else
{
$args = array_shift($args);
self::$object_data[$arg] = call_user_func_array(self::$classname . '::' . 'get_' . $arg, $args);
}
}
}
// Lets give an example based on something you might do with a phpBB type project
class posts extends base
{
public static function set_class()
{
parent::$classname = __CLASS__;
}
public static function get_posts()
{
global $db;
$limit = self::get('limit', 100);
$start = self::get('start', 0);
$sql = $db->sql_build_query('SELECT', self::base_sql());
$result = $db->sql_query_limit($sql, $limit, $start);
while ($row = $db->sql_fetchrow($result))
{
$post_data[$row['post_id']] = $row;
}
return $post_data;
}
// Build sql query...
public static function base_sql()
{
$start_time = self::get('start_time', time());
$end_time = self::get('end_time', time());
$order_by = self::get('order_by', 'p.post_time');
$sort_order = self::get('sort_order', 'DESC');
// typically, we would not use sql_ary for a single-table query
// but when building a query, this allows us to modify the parameters 'later' making it extensible
$sql_ary = array(
'SELECT' => 'p.*',
'FROM' => array(POSTS_TABLE => 'p'),
'WHERE' => 'p.post_time BETWEEN ' . (int) $start_time . ' AND ' . (int) $end_time,
'ORDER_BY' => $order_by . ' ' . $sort_order, // if this is user input, we would need to sanitize it
);
return $sql_ary;
}
}
$date = getdate();
posts::set_class();
// Get posts within the last 7 days
posts::set('start_time', mktime(0, 0, 0, $date['mon'], $date['mday'] - 7, $date['year']));
posts::set('end_time', $date[0]);
// Show only 10 posts
posts::set('limit', 10);
$posts_ary = posts::get('posts');
foreach ($posts_ary as $post_id => $row)
{
$template->assign_block_vars('posts', array(
// Post data...
));
}







.
Proud member of the phpBB support team
STG Support team member
STG Moderator team member

.
. So I've rewritten the base class in a way that you can have more classes extend it.