【问题标题】:PHP OOP inheritancePHP OOP 继承
【发布时间】:2015-02-10 03:49:15
【问题描述】:

我有 2 个类:用户和路由器

在我的脚本中,首先实例化 User 类来设置用户数据,然后实例化 Router 类来设置页面数据。

$user = new User();
$router = new Router();

在Router 的一个方法中,我需要调用$user->getSuperPrivileges()。该函数查询数据库并在 $user 对象中设置额外的参数,然后返回它们。

我可以将 $user 作为 Router($user) 的参数传递,并将其保存为构造函数中的属性,但我相信这只会创建真实对象的克隆。问题在于 $this->user->getSuperPrivileges() 设置的值只能由克隆访问,而不能在全局脚本中由真实对象访问。换句话说,我需要在真实对象中再次调用 getSuperPrivileges() 方法来重新设置这些属性,这会适得其反。

实现我想要的最佳方式是什么(从 $router 内部访问真实对象 $user 及其方法,而无需创建作为传递的克隆一个函数参数)?

【问题讨论】:

  • 仅在路由器中使用 $user - 这意味着您将始终通过 $router->user 调用 $user
  • but I believe this would only create a clone of the real object 不,那不会。到处都是同一个对象
  • 只是想补充一点,路由器需要了解用户的信息听起来很可疑。听起来这个逻辑可能需要在另一个类中,这取决于你在做什么。

标签: php oop


【解决方案1】:

正如@hek2mgl 所指出的,在 php5 中,每个对象变量都是一个引用。无论如何,__construct 魔法方法在此之前根本不起作用,因此我们可以假设 OP 示例无论如何都应该起作用。

http://3v4l.org/6dKL0

鉴于上面的例子,以下几行真的毫无意义。


您是否尝试过将 $user 对象作为引用传递?

class Router{
  function __contruct(&$user){
    $this->user=$user;
  }
}

new Router($user);

在那种情况下,单身呢?

function user(&$userO){
  static $user;
  if(!is_array($user)) $user=array();
  if(is_object($userO)) $user[$userO->uid]=$userO;
  if(is_string($userO)) return $user[$userO];
}
class Router{
  function __construct($user){
    $this->uid=$user->uid;
  }
  function __get($k){if($k=='user') return user($this->uid);}
}

为了解释更多,用户函数存储用户对象,以静态数组中的唯一标识符为键,__get 魔术方法允许您拦截对路由器对象上用户属性的调用并静态返回从单例函数中保存的对象。

【讨论】:

  • 这就是我现在正在做的事情,但它创建了 $user 对象的克隆,当我从 $this->user->getSuperPrivileges() 调用 getSuperPrivileges() 时,它只将新属性设置为克隆对象,而不是真实对象。因此,当我之后尝试从真实对象访问这些属性时,会出现错误并需要再次调用该方法...
  • 通过引用传递对象有什么好处?
  • 理论上通过引用传递它允许您编辑对象本身,而不仅仅是它的克隆
  • @joey 提供的链接实际上是一个真正的单例示例,我选择包装函数来处理它,因为我经常需要在一次加载中加载多个对象(用户),它允许我维护单独的对象。我可能弄错了,但根据我的经验,类中的某些静态设置实际上使其对于类和该类的每个实例化而不是在特定对象上是静态的。
  • @Trey PHP5 中的每个对象变量都是一个引用——而不是一个克隆。检查这个例子:3v4l.org/K8Rci
【解决方案2】:

您可以创建 $user 对象并使用构造函数注入将其注入 $router 对象。但你正在做的应该没问题。您应该能够将该对象用于路由器类中所需的任何内容。特别是如果数据库维护特权状态。

如果您必须只使用该类的一个实例,请查看单例模式部分:http://www.phptherightway.com/pages/Design-Patterns.html,您可以了解如何实现这一点。

【讨论】:

    【解决方案3】:

    我会尝试应用Dependency Injection 模式。关键是方法应该传递所有它们需要操作的东西。

    意味着你的路由器中对用户进行操作的方法应该传递给该用户。

    class Router {
      method privilegiateUser(User $user) { 
        // notice the typehint
        // php will enforce that your method receives a User
        $user->getSuperPrivileges();
      }
    }
    

    我不赞成将User 传递给您的Router__construct(),如果它只使用一次而不是在每个脚本运行时使用。这样想:

    UserRouter 的属性,与 NameUser 的属性一样吗?

    【讨论】:

      猜你喜欢
      • 2013-02-11
      • 2014-09-12
      • 1970-01-01
      • 1970-01-01
      • 2013-02-19
      • 2016-06-25
      • 2018-05-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多