如何获取在PHP中作为参数传递的变量名?

时间:2014-12-01 15:57:25

标签: php templates scope

我有一个接受2个参数的视图方法,其中一个是该视图的数据。我将它设置为$data作为方法参数。

我按照以下方式使用该课程:

view->make('testview', $movies);

在这种情况下,$movies是一个对象,但它可能只是文本。

class View {

    public function make($view, $data) {
        require_once("../app/views/$view" . ".php");
        var_dump($data);
    }

}

问题是,我不想在我的所有观看中使用$data->whatever(),因为这没有语义含义并且难以审核。我希望我的视图数据与我传递给它的变量具有相同的名称。在这种情况下,我将变量$movies传递给它,因此我希望能够在我的视图中使用$movies->whatever()

本质上,我希望传递给方法的变量保持相同的变量名,并且在函数中可以使用。

我该怎么做?

5 个答案:

答案 0 :(得分:3)

您无法在通话中获取变量的名称。你能做的就像模板引擎在这种情况下所做的一样:不只是分配一个变量,而是将它分配给某个东西。

所以你会,例如

$view = new View();
$view->assign('movies', $movies);
$view->make('testview');
<{1>}在assign函数中,您同时拥有内容和名称,因此您可以使用该名称创建变量。这可能是一个更好的解决方案,但这可以让你开始:

function assign($name, $data)
{
    $$name = $data;
    //now you have a $movies in your template
}

这不是一个非常稳固的解决方案,尤其是您需要该视图的方式。为了实现这一目标,您可能需要添加许多函数,并且这些函数在更默认的模板框架中实现,例如, smarty。看看这是否适合你,听起来你想创造类似的东西。

答案 1 :(得分:2)

如果它只是您想要跟踪的名称,您可以保留原始的$ data参数名称,但默认使用数组。您可以为$ data参数传递函数array('movies'=>$movies)(或array('gerbils'=>$gerbils),如果需要)。这将允许您在不实现一堆额外函数的情况下跟踪原始变量名称,但您必须使用$data['movies']语法来访问它。这样做的好处是可以减少对可能需要查看代码的未来开发人员的混淆。

答案 2 :(得分:1)

虽然您可以动态获取the function's argument names,但我认为无法获取传递的变量名称。或者,你可以在函数中传递一个关联数组的参数和extract

$param = array(
    'view' => 'testview',
    'movies' => $movies
);
view->make($param);

然后,您可以在make函数中提取参数。

class View {

    public function make($arg) {
        extract($arg);
        // now you get
        // $view
        // $movies
        require_once("../app/views/$view" . ".php");
        var_dump($movies);
    }
}

尽管如此,我不确定你为什么要在被调用函数中使用$movies或其他东西,因为我想你想要它是动态的和自动化的。

答案 3 :(得分:0)

您可以做的是在extract()方法中传递一个数组make()。因此,传递的数组的内容将作为当前符号表中的变量提供。

<?php

// Controller or something

$movies = [
    ['name' => 'Fight Club' => 'rating' => 'great'],
    ['name' => 'The Avengers', 'rating' => 'great'],
    ['name' => 'Iron Man 2',   'rating' => 'sucks'],
];

view->make('testview', compact('movies'));

// View Class

class View {

    public function make($view, $data) {
        extract($data);

        //Usage in Viewfile: $movies[0]['name']
        require_once("../app/views/$view" . ".php");
    }

}

当然传递的数组的内容无关紧要,因此您可以轻松传递对象或其他内容。

答案 4 :(得分:0)

作为替代方案:如果您正在为所有数据类型使用对象,并且您希望在方法调用中只处理一个参数,那么可以根据收到的对象类型指定变量的名称。

class View {

    public function make($object) {

        //if it's an object - use the type of object to define the variable
        if(is_object($object)) {

            switch(get_class($object)) {

                case 'Movie':
                    $movie = $object;
                    break;

                case 'CD'
                    $cd = $object;
                    break;

                // ... and so on

                default:
                    $data = $object;
                    break;
            }
        }

        //otherwise go with a default of $data
        else {
            $data = $object;
        }
    }

}

我个人认为需要在每个视图文件中使用isset()验证变量,以防万一错误类型的对象被传入 - 我担心它会最终需要在所有视图文件中进行远远超过必要的验证。


更进一步

或者你的类都可以扩展一个公共(抽象)类,它可以容纳类型 - 在所有子类的构造函数中设置该类型,并根据它确定变量名(set)例如,protected $type;构造函数中的父$this->type = 'movie'; Movie

这会给你这样的东西(注意:${$object->getType()} = $object;)哪个有效,但我不确定它的完整性:

class View {

    public function make($object) {

        //if it's an object - use the type of object to define the variable
        //  so for the `Movie` object where the type is 'movie' this will
        //  create a variable called $movie containing the Movie object
        if(is_object($object) && method_exists($object, 'getType')) {

            ${$object->getType()} = $object;
            require_once "/path/to/{$object->getType()}.php";
        }
    }
}

/**
 * base abstract 'thing'
 */
abstract class Thing {

    protected $type;

    public function getType() {
        return $this->type;
    }

}

/**
 * a Movie 'thing'
 */
class Movie extends Thing {

    public function __construct() {
        $this->type = 'movie';
    }

}

//processing stuff
$oView = new View();
$oView->make( new Movie() );