tags:

views:

216

answers:

4

Hi all,

I have a, I think fairly easy, question, but I can't figure out what I'm doing wrong. I have a function which i call with PHP's function eval. I'm expecting an, selfbuilt, ArrayList to get as a result. But instead when I use gettype I see the result is NULL. Even though I'm using return in the eval-ed function.

As far as I'm aware I'm playing it by the documentation, but somehow it's not working. Any suggestions?

Code fragment

<?php
                $widgetList = new ArrayList();

                for($i = 0; $i < $selectedTemplate->Regions->count(); $i++)
                {
                    $region = $selectedTemplate->Regions->item($i);

                    if($region->Widget->selectiveContent == 1)
                    {
                        $widgetList->add($region->Widget);
                    }
                }

                if($widgetList->count() > 0)
                {
            ?>
            <tr>
                <td colspan="2">
                    <strong>Widget instellingen</strong>
                    <hr size="1" width="100%" color="#333"/>
                </td>
            </tr>
            <?php
                    for($i = 0; $i < $widgetList->count(); $i++)
                    {
            ?>
            <tr>
                <td class="w150">
                    <?= $widgetList->item($i)->title ?>
                </td>
                <td>
                    <select name="widget_<?= $widgetList->item($i)->id ?>" class="full">
                    <?php
                        $itemList = eval($widgetList->item($i)->functionCall);
                        for($j = 0; $j < $itemList->count(); $j++)
                        {
                            $selected = null;
                            if($_POST["widget_".$widgetList->item($i)->id] == $itemList->item($j)->id)
                            {
                                $selected = " selected=\"selected\"";
                            }
                    ?>
                        <option value="<?= $itemList->item($j)->id ?>"<?= $selected ?>><?= $itemList->item($j)->title ?></option>
                    <?php
                        }
                    ?>
                    </select>
                </td>
            </tr>
            <?php
                    }
                }
            ?>

Eval-ed code

public function getNavigationByLanguageId(Integer $parent, ArrayList $objectList, Integer $language)
    {
        $query  = DataAccess::getAdapter()->query("
                    SELECT      *
                    FROM        `navigation`
                    WHERE       `parent_id`     = ".$parent->value."
                    AND         `language_id`   = ".$language->value."
                    AND         `website_id`    = ". $_SESSION["currentSite"]["id"]."
                    ORDER BY    `sort_order`");

        while($result = DataAccess::getAdapter()->fetchAssoc($query))
        {
            $link = new Model_Navigation();

            $link->id           = $result["id"];
            $link->language     = $result["language_id"];
            $link->parent       = $result["parent_id"];
            $link->Page         = Model_Page::getPageById(new Integer($result["page_id"]));
            $link->title        = $result["title"];
            $link->externalUrl  = $result["external_url"];
            $link->sortOrder    = $result["sort_order"];

            $objectList->add($link);
            Model_Navigation::getNavigationByLanguageId(new Integer($result["id"]), $objectList, $language);
        }

        return $objectList;
    }

The function being eval-ed is: Model_Navigation::getNavigationByLanguageId(new Integer(0), new ArrayList(), new Integer(7));

Some more explaination about the code I'm using this funcitonality in my new CMS. A user is able to design a template and place widgets in defined regions, pretty much like the portlet functionality jQuery is providing. Widgets are installed for a website by me, I have built in an option to provide a functioncall to retrieve a list of objects when a widget is flagged as 'Selective Content'.

What I'm trying to achieve here is using eval to return ArrayLists from the value of $widget->functionCall.

I hope it's clear for you, and thanks in advance for the effort you make!

Thanks in advance, Ben

+1  A: 

Eval is evil (and in most cases hackish). I would suggest posting your code and we can perhaps do away with that portion of the code for you.

cballou
A: 

If you run the code outside the eval function and it's OK then you probably need to check the eval() function documentation.

Make sure the string to be "evaluated" is "not wrong"/formatted properly.

andreas
+1  A: 

If you run

function foo() {
  bar();
}
function bar() {
  return 1;
}
$x=foo();
var_dump($x);

the output will be `NULL'. Although bar() returns a value foo() does not. The return value of bar() is "lost". Same if you use eval()

function bar() {
  return 1;
}
$x=eval('bar();');
var_dump($x);
$x=eval('return bar();');
var_dump($x);

prints

NULL
int(1)
VolkerK
Hi VolkerK, also, thanks for you answer! It did the trick, but I can only flag one answer as accepted. +1!
Ben Fransen
+2  A: 

On this line, what is the content of $widgetList->item($i)->functionCall ? $itemList = eval($widgetList->item($i)->functionCall);

For eval to return anything, $widgetList->item($i)->functionCall MUST begin with the token return

e.g., if

$widgetList->item($i)->functionCall == 'return myFunc();';

then you're fine

But if

$widgetList->item($i)->functionCall == 'myFunc();';

Then that's why eval() isn't returning anything. Also, keep an eye out for any errors generated while executing eval() -- if you code fails to parse, or throws any sort of error, that may also explain why eval() isn't returning anything.

You should be able to do away with the call to eval entirely, though -- at worst, use call_user_func()

Edit: For your example:

eval('return Model_Navigation::getNavigationByLanguageId(new Integer(0), new ArrayList(), new Integer(7));');

This could be written as:

call_user_func(array('Model_Navigation', 'getNavigationByLanguageId'), new Integer(0), new ArrayList(), new Integer(7));

This is probably preferable, as it avoids compilation overhead, is less likely to break, etc.

Frank Farmer
Hi Frank! The code containing in functionCall, in this particular case, is `Model_Navigation::getNavigationByLanguageId(new Integer(0), new ArrayList(), new Integer(7));`. Adding `return` in the eval function solved the case! Thanks! +1
Ben Fransen