4

I am developing a PHP mini-framework, one of whose methods builds an HTML table from an array of objects:

class HTMLTableField {
    private $hdr;
    private $alg;
    private $fun;

    function __construct($descr, $align, $apply) {
        # fun must be an anonymous function
        $this->hdr = '<th>' . htmlentities($descr) . "</th>\n";     
        $this->alg = "<td style=\"text-align: {$align}\">";
        $this->fun = $apply;
    }

    function getHeader() {
        return $this->hdr;
    }

    function getCell($row) {
        # This line fails
        return "{$this->alg}{$this->fun($row)}</td>";
    }
}

function gen_html_table($rows, $fields) {
    # $fields must be an array of HTMLTableField objects
    echo "<table>\n<thead>\n<tr>\n";
    foreach ($fields as $field)
        echo $field->getHeader();
    echo "</tr>\n</thead>\n<tbody>\n";
    foreach ($rows as $row) {
        echo "<tr>\n";
        foreach ($fields as $field)
            echo $field->getCell($row);
        echo "</tr>\n";
    }
    echo "</tbody>\n</table>\n";
}

However, when the flow of control of gen_html_table reaches

echo $field->getCell($row);

I get an error: "Call to undefined method HTMLTableField::fun()." But fun is supposed to be an anonymous method!

isekaijin
  • 19,076
  • 18
  • 85
  • 153

6 Answers6

2

There is even shorter and in my opinion more elegant solution:

function getCell($row) {
    return "{$this->alg}{$this->fun->__invoke($row)}</td>";
}
edorian
  • 38,542
  • 15
  • 125
  • 143
1

Never mind. I found an ugly, but ultimately working solution:

$func = $this->fun;
return "{$this->alg}{$func($row)}</td>";
isekaijin
  • 19,076
  • 18
  • 85
  • 153
1

I'm not sure what you are try to accomplish but are you not better off using Magic Methods http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.methods?

Matt Lowden
  • 2,586
  • 17
  • 19
1

One way to do this is:

call_user_func($this->fun, $row)

I suppose it's a matter of style, but a lot of time using call_user_func() or call_user_func_array() is considered cleaner than $func() syntax, and in some cases (such as this one), necessary. It also makes it easier to spot dynamic calls right away.

mfonda
  • 7,873
  • 1
  • 26
  • 30
  • Yeah, but I wish `$($this->fun)($row)` were possible. – isekaijin Jan 14 '11 at 00:21
  • @Eduardo `call_user_func[_array]` is the PHP way. – mfonda Jan 14 '11 at 00:23
  • I'm a C++ programmer who happens to be using PHP out of necessity. A FORTRAN programmer can write FORTRAN programs in any language. A C++ programmer hates all other languages, because he cannot write C++ programs in them. – isekaijin Jan 14 '11 at 00:25
1

you can't use an anynomious function via the class property.

function getCell($row) {
    # This line works
    $fun = $this->fun;
    return $this->alg . $fun($row) . "</td>";
}

makes your script running :), tested on php 5.3.1

Samuel Herzog
  • 3,561
  • 1
  • 22
  • 21
0

I think you need

$this->$fun($row)

rather than

$this->fun($row)

The former calls the function pointer stored in the member variable $fun, while the latter calls the member function fun(), which as pointed out does not exist.

JSBձոգչ
  • 40,684
  • 18
  • 101
  • 169