Jochem Maas wrote:
admin wrote:
Jochem Maas wrote:
another solution for the OP might be (although I think it goes against
all
design principles):

class A {
  function foo() {
    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();

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.

sure it might be a neat little hack - __call() can be used for alsorts
of wonderful madness

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]

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 suspect

In 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.


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)


This undocumented (?) feature is fairly nice. Unfortunately there's no $this outside the class.

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to