Re: calling parent class method from the outside
| From: | admin | Date: | Tue, 03 Jul 2007 05:50:04 +0000 |
| Subject: | Re: calling parent class method from the outside | ||
| References: | 1 2 3 4 5 | Groups: | php.general |
| Request: | Send a blank email to php-general+get-258075@lists.php.net to get a copy of this message | ||
Jochem Maas wrote:
admin wrote:It was late in the night over where I live when I replied :-) But now I see that although your trick answers the subj perfectly, back then I didn't make it clear that the real intention was to get rid of code duplication in doSetColumn(). On closer inspection your trick would force me to scatter identical copies of __call() in every model class too, so I've gained nothing. [snip]Jochem Maas wrote:sure it might be a neat little hack - __call() can be used for alsorts of wonderful madnessanother solution for the OP might be (although I think it goes against all design principles): class A { function foo() {Barring the s/parent/get_parent_class/ the idea is really really cute, thanks. Beautiful. Heck, maybe I'll even hack the code to do it like that... after some grace period.echo "achoo\n";} } class B extends A { function foo() {echo "cough\n";} function __call($meth, $args) {$func = array(parent, strtolower(str_replace("parent","", $meth))); if (is_callable($func)) return call_user_func_array($func, $args);} } $b = new B; $b->foo(); $b->parentFoo();
and having read what you wrote about Propel/Symphony I still don't get what the problem is that your trying to solve ... although I suspectIn Symfony/Propel you're on your own when things get to the point where you have to put the submitted data into DB. The main idea is that for columns that can be NULL the form submits empty values as empty string '', but I'd rather make that NULL. You would argue that simply leaving out the relevant update from the SQL clause would do the trick, but a second, more important issue prevents skipping NULL and is the basis for the former: for everything to work smoothly and transparently Symfony/Propel _insists_ on pre-hydrating the object right before the update, a requirement I cannot personally stand. So I've tried working around the requirement by populating the model myself with form data using setNew(false) and setXXX() calls. The real doSetColumn(): # these mutators help to skip pre-hydrating the object just to do an update # treats NULL and empty string the same # this also means empty input string will be converted to SQL NULL private function doSetColumn($colname, $value, $col_mutator, $mod_trigger_value = '') {
if ($value == '')
$value = null;
if (call_user_func(array(__CLASS__ . 'Peer', 'getTableMap'))->getColumn($colname)->isNotNull()) {
if (is_null($value))
throw new Exception("$col_mutator: $colname may not be NULL");
} else {
if (is_null($value) && !$this->isColumnModified($colname))
# XXX: as we don't know the current value in DB
# we need to force it to be set to NULL
parent::$col_mutator($mod_trigger_value);
}
parent::$col_mutator($value);
}
Hope you get the idea.
This undocumented (?) feature is fairly nice. Unfortunately there's no $this outside the class.P.S.: I thought calling array('classname', 'method') only worked for static methods? It turns out there's an implied $this being passed around?the 'callback' type has a number of forms: 'myFunc' array('className', 'myMeth') array(self, 'myMeth') array(parent, 'myMeth') array($object, 'myMeth') self and parent adhere to the same 'context' rules when used in call_user_func*() as when you use them directly - whether $this is present within the scope of the called method is essentially down to whether the method being called is defined as static or not. AFAIK call_user_func*() respects PPP modifiers and works transparently with regard to access to the relevant object variable ($this)