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

时间:2011-12-07 11:37:39

标签: php

我想知道是否有人可以帮助我理解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变量。

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

如果我要将$ r变量传递给函数,我会想出没有问题,但是因为它们是全局声明的,我想知道为什么没有这样做就看不到它们,因为它们的范围可能是全局的?

感谢。

编辑 - 完整代码。

<?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 *变量不再在此处再次使用,因此可以方便地在会话中使用。

6 个答案:

答案 0 :(得分:1)

那不是OOP - 在OOP中你要声明一个类,使r1,r2和r3成为它的属性,然后它们将在类的每个方法中可用。查看有关课程here的小教程。

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

修改

这是一个示例代码,如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();

答案 1 :(得分:0)

如果将它们声明为全局(创建本地Global),则可以在函数内访问

reference to the global个变量。但是,globals are bad

如果变量定义发生在“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移到使用变量的行之前,因为这与全局变量共享一个大问题:变量看似神奇地存在,并没有指示如何或在何处,制作只需阅读函数就很难理解函数(以及代码的其余部分)。这是coupling的一种形式。

通过包含文件来执行代码有时可能是一个有用的技巧,但它也经常会导致问题(正如这个问题所示)。通常,包含文件应该只定义事物。对于OO方法,请执行所包含文件正在执行的任何任务,并确定代码尝试实现的整体任务。然后,将每个任务分配给具有(单个)职责的类,以实现每个整体工作。在这种情况下,特定任务是将请求分解为路由,并且整个作业将请求分派给控制器。然后应该有一个调度程序类,它使用一种解析路由的方法将请求分派给适当的控制器。该方法(可能是私有的或受保护的,并从构造函数中调用)可以将路由存储在实例变量中以实现时间效率。

class RouteDispatcher {
    protected $route;

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

    function dispatch() {
        ...
    }

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

    ...
}

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

在一般情况下,良好的设计可能比这更棘手,因为您在创建具有single responsibility的类时作为设计者的目标是减少更改它们的需要。如果一个类只有一个责任,那么只有当该职责的要求发生变化时才需要更改该类。

答案 2 :(得分:0)

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

$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
}

答案 3 :(得分:0)

在函数内添加此功能。

全球$ r1,$ r2,$ r3;

这告诉函数使用全局范围内的变量。

答案 4 :(得分:0)

使用$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'];
    }
}

或在声明变量global

的函数内部
function bar() {
    global $baz;
    echo $baz
}

答案 5 :(得分:0)

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

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

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