Ok so, here is an interesting post about PHP! I am currently building a website with a famous framework in PHP, and I noticed that the CRUD methods (create/read/update/delete) for the models looked a lot alike between all my models. No surprise here.
However, it wasn't that easy to make it generic -- meaning that the field names and table names still change every time, and passing an array of field names at every call didn't seem that elegant... That plus the fact that I wanted these methods to be called from the public interface of my models. What to do?
I figured out a little trick I really like, and that I'm going to share with you today. This trick probably has a design pattern named after it, and it's a little twisted so hang on! For those who don't have time to read, here is the beast:
<?php
// Our base class
class A
{
const _foo = 'foo_A';
protected static $_bar = array( 'bar_A' );
// Define static accessors using 'get_called_class'
public static function foo()
{
$c = get_called_class();
return $c::_foo;
}
public static function &bar()
{
$c = get_called_class();
return $c::$_bar;
}
// Define methods using 'inherited' statics/constants
public function print_foo()
{
echo self::foo() . PHP_EOL;
}
public function print_bar()
{
print_r(self::bar());
echo PHP_EOL;
}
}
// Let's make some magic
class B extends A
{
const _foo = 'foo_B';
protected static $_bar = array( 'bar_B' );
}
// Try it out!
$a = new A();
$b = new B();
$a->print_foo(); // foo_A
$a->print_bar(); // bar_A
$b->print_foo(); // foo_B
$b->print_bar(); // bar_B :)
You can see here that I'm defining "static accessors" to some constants/static variables defined in my base class. These constants/statics are not only overridden by children, but are also bound to them; that's why I use the get_called_class in these accessors. Now all there is to do is to write some methods using these accessors instead of instance properties. Override these constants/statics in children classes, and VoilĂ ! You get template-like methods in PHP that fit any situation where methods should be "parameterized" in addition to receiving public inputs :)