繁体   English   中英

PHP OOP:可以在函数中看到变量而无需将其作为参数传递吗?

[英]PHP OOP: Can a variable be seen in a function without passing it as a param?

我想知道是否有人可以帮助我了解OO PHP的这一特定方面,因为它现在使我陷入了困境。

我已经在文件顶部指定了一个var,就像这样

$route = explode('/', $_SERVER["REQUEST_URI"]);
// Shorthand
$r1=$route[0]; $r2=$route[1]; $r3=$route[2];

然后,我试图在上面的代码下方编写的函数中使用$ r1等。

function edit($id)
   {
            $_SESSION['path'] = $r1 . "/" . $r2 . "/" . $r3;
            require 'app/controller/edit.php';
            new Controller($id);
   }

$ r1,$ r2,$ r3 var出于某种原因在此函数内看不到。

Notice: Undefined variable: r1 in C:\wamp\www\options.ex\public_html\app\options.php on line 77

如果我将$ r vars传递给函数,我会认为不会有问题,但是由于它们是全局声明的,所以我想知道为什么不这样做就看不见它们,因为它们的范围可能是全局的?

谢谢。

编辑-完整代码。

<?php

require_once 'load.php';


// Clean and prepare query string
$route = explode('/', $_SERVER["REQUEST_URI"]);
    // Trim outer exmpty parameters caused by leading/trailing slash
    if($route[count($route)-1]=='') unset($route[count($route)-1]);
    if($route[0]=='') unset($route[0]);
    $route = array_values($route);
    // If any parameters are undefined, set them to ''
    if(!isset($route[0])) { $route[0]=''; $route[1]=''; $route[2]='';  }
    elseif(!isset($route[1])) { $route[1]=''; $route[2]='';  }
    elseif(!isset($route[2])) { $route[2]='';  }
// Shorthand
$r1=$route[0]; $r2=$route[1]; $r3=$route[2];

// Choose route, else default to dash
if($r1=='dashboard' && $r2=='' && $r3=='')          dashboard();
elseif($r1=='staff' && $r2=='add' && $r3=='')       add_staff();
elseif($r1=='staff' && $r2=='edit' && $r3!='')      edit_staff($r3);

else header("location: http://local.options.ex/dashboard");



// Dashboard: Main entry point after login.
function dashboard()
   {
            require 'app/controller/dashboard/dashboard.php';
            new Controller();

   }

// Staff related interfaces ----------------------------------------------------
function add_staff()
   {
            require 'app/controller/staff/add_staff.php';
            new Controller();
   }

// ----------------------------------------
function edit_staff($staff_id)
   {
            $_SESSION['path'] = $r1 . "/" . $r2 . "/" . $r3;
            require 'app/controller/staff/edit_staff.php';
            new Controller($staff_id);
   }

// ----------------------------------------

只是为了清理起见,这里不再使用$ r *变量,因此可以方便地在会话中使用存储。

那不是OOP-在OOP中,您将声明一个类,将r1,r2和r3设置为其属性,然后它们将在该类的每个方法中可用。 在这里查看有关类的一些教程。

使用全局变量是一个坏主意。

编辑

这是一个示例代码,如Sohnee所问:

Class Route {
    var $r1;
    var $r2;
    var $r3;

    function __construct($url)
    {
        $route = explode('/', $url);
        // Shorthand
        $this->r1=$route[0]; $this->r2=$route[1]; $this->r3=$route[2];
    }

    function test()
    {
            $path = $this->r1 . "/" . $this->r2 . "/" . $this->r3;
            echo $path;
    }

}

$a = new Route('http://stackoverflow.com/questions/');
$a->test();

如果将全局变量声明为全局变量(这会创建对global的本地引用 ),则可以在函数内访问全局变量。 但是, 全局变量是不好的

如果变量定义发生在“ app / controller / edit.php”中,那么问题就出在警告告诉您:尚未定义变量。 您只能在一行上使用它们,但是直到下一行才包含定义它们的文件,因此尚未定义它们。 就像函数是一样的:

function edit($id) {
    $_SESSION['path'] = $r1 . "/" . $r2 . "/" . $r3;
    $route = explode('/', $_SERVER["REQUEST_URI"]);
    // Shorthand
    $r1=$route[0]; $r2=$route[1]; $r3=$route[2];
    ...
}

我建议不要采用明显的修正方法:将require移到使用变量的行之前,因为这与全局变量存在一个大问题:变量似乎魔术般地存在,而没有指示如何或在何处进行,使其更难只需阅读函数即可了解该函数(以及代码的其余部分)。 这是耦合的一种形式。

通过包含文件来执行代码有时可能是一个有用的技巧,但它通常还会导致问题(如该问题所示)。 通常,包含文件应仅定义事物。 对于OO方法,请执行包含的文件正在执行的所有任务,并找出代码总体上要尝试完成的工作。 然后,将每个任务分配给负责完成每个总体工作的(单个)职责的班级。 在这种情况下,特定的任务是将请求分解为一条路由,而整个任务是将请求分派给控制器。 然后应该有一个调度程序类,该类通过解析路由的方法将请求调度到适当的控制器。 该方法(可以是私有的,也可以是受保护的,并可以从构造方法调用的方法)可以将路由存储在实例变量中,以节省时间。

class RouteDispatcher {
    protected $route;

    function __construct() {
        $this->_parseRoute();
        ...
    }

    function dispatch() {
        ...
    }

    protected function _parseRoute() {
        $this->route = explode('/', $_SERVER['REQUEST_URI']);
    }

    ...
}

入口点(首先被调用来处理每个请求的脚本)将实例化RequestDispatcher ,设置任何适当的属性或调用任何必要的方法,然后调用RequestDispatcher::dispatch ,这将创建适当的控制器并将控制权RequestDispatcher::dispatch给其请求处理程序。

在一般情况下,一个好的设计可能比这更棘手,因为作为设计师,创建具有单一职责的类的目标是减少对它们进行更改的需求。 如果班级只有一个职责,则只有在该班级的要求发生变化时才需要更改班级。

为了在函数内使用全局变量,您必须通过以下方式进行操作

$route = explode('/', $_SERVER["REQUEST_URI"]);
// Shorthand
$r1=$route[0]; $r2=$route[1]; $r3=$route[2];
// ...  
function edit($id)
{
    global $r1, $r2, $r3;  // after this the variables are available in function scope

}

另一种选择是使用全局数组$ GLOBALS。 使用此数组,可以从任何如下范围访问全局变量:

if ($GLOBALS["r1"] == "some value")
{ 
    // do something
}

将其添加到函数内部。

全局$ r1,$ r2,$ r3;

这告诉函数使用全局作用域中的变量。

全局变量可以在使用$GLOBALS的方法中看到

$GLOBALS — References all variables available in global scope

http://php.net/manual/en/reserved.variables.globals.php

<?php

$baz = 'foo';

clas Bar {

    public function __construct() {
        echo $GLOBALS['baz'];
    }
}

或在函数内声明全局变量

function bar() {
    global $baz;
    echo $baz
}

如果$ r1,$ r2和$ r3在任何类或函数定义之外定义,则可以使用global关键字来访问它们,或直接从$ GLOBALS数组中调用它们。 例如:

function edit($id){
  global $r1, $r2, $r3; //Rest of the function below this

要么

$_SESSION['path'] = $GLOBALS['r1'].'/' //... etc.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM