【问题标题】:How to get a variable name that's been passed as an argument in PHP?如何获取在 PHP 中作为参数传递的变量名?
【发布时间】:2015-01-29 16:21:30
【问题描述】:

我有一个接受 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()

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

我该怎么做?

【问题讨论】:

  • 使用公共函数make($view, $movies)?
  • 你能详细说明一下吗?正如@Erik 所说,只需将$data 重命名为$movies 似乎就是这样。
  • ... 除了它可能不是$movies 在某些视图中它可能是$badgers,因此视图文件中的变量变量名......我自己并没有真正明白这一点,这只会让生活变得困难。只需在所有视图文件中使用$data 并完成它,至少您知道在所有情况下将调用什么变量并且不用担心语义。如果变量名称的语义让您感到困扰,只需在视图顶部重新映射它:$movies = $data;丑陋但它会起作用。
  • 就是这样。当我为它提供除 $movies 之外的其他变量时,我希望它具有可重用性。我宁愿让变量是动态的。这并没有让生活变得更难,因为我必须从变量开始。

标签: php templates scope


【解决方案1】:

您无法在调用中获取变量的名称。在这种情况下,您可以做的类似于模板引擎所做的:不只是分配一个变量,而是将其分配给某个东西。

例如,你会这样做

$view = new View();
$view->assign('movies', $movies);
$view->make('testview');

assign 函数中,您拥有内容和名称,因此您可以使用该名称创建一个变量。可能有比这个更好的解决方法,但这可以让你开始:

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

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

【讨论】:

  • 谢谢,这就是我要找的。我只是想自动化它以自动获取我传递给它的变量名。为 assign 方法使用 2 个参数似乎有点多。只是想知道是否有一种方法可以从您直接传递的变量中设置名称。
  • @Stephan-v 不是真的 - 它可能在您的脚本中称为 $movies 但一旦将其传递给对象方法,您使用的参数名称是 $data ... @ 987654328@ 不存在于该对象方法的范围内。
  • 请注意,您可以通过使用 compactextract 来隐藏此行为,正如其他一些答案所示,但这在我看来几乎没有什么不同。 assign 方式让您明确说明您使用的视图以及视图可以显示的变量。它具有从一个功能中剥离不同功能的额外优势。您有一个视图函数和一个数据函数,而不是一个组合函数。这应该会导致更清晰的设计恕我直言
  • 我已经玩了一点,它工作正常,但我如何将动态变量从 assign() 方法传递给 view() 方法?否则视图无权访问它?这意味着我必须在我的类中使用动态属性并在我的视图方法中使用 $this 来引用它?
  • 您可以创建一个类,在其中隐藏键/值类型的构造(例如普通数组)中的所有变量,并添加一个使用指定键调用数组的魔术 getter?见php.net/manual/en/language.oop5.overloading.php#object.get这些是我所说的,当你使用像 smarty 这样的框架库时,你会“免费”获得这些东西
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    您可以做的是在您的make() 方法中传递一个数组和extract()。所以传入的数组的内容将在当前符号表中作为变量可用。

    <?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】:

      虽然可以动态获取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 或其他内容,因为我猜您希望它是动态的和自动化的。

      【讨论】:

      • 我只是以 $movies 为例,我当然可以用任何东西代替。我想我还没有完全清楚。
      • @Stephan-v 是的,$movies 就是一个例子。如果函数make 对任何东西都是动态的,为什么要在函数中使用那些特定的变量名,对吧?
      【解决方案5】:

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

      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() 验证变量,以防传入对象的错误类型 - 我担心它会结束在所有视图文件中都需要进行比必要更多的验证。


      更进一步

      或者,您的类都可以扩展一个通用(抽象)类,该类可以保存 type - 在所有子类的构造函数中设置该类型并根据该类型确定变量名称(设置例如,父级的protected $type;$this-&gt;type = 'movie';Movie 构造函数中)。

      这会给你这样的东西(注:${$object-&gt;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() );
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-25
        • 1970-01-01
        • 2011-01-17
        • 1970-01-01
        • 1970-01-01
        • 2022-06-14
        相关资源
        最近更新 更多