在 PHP 的扩展类中使用父变量

发布于 2024-07-10 15:46:54 字数 497 浏览 8 评论 0原文

我有两门课,主课和扩展课。 我需要在扩展类中使用主变量。

<?php
class Main {
  public $vars = array();
}

$main = new Main;

$main->vars['key'] = 'value';

class Extended extends Main { }

$other = new Extended;

var_dump($other->vars);

?>

我能做谁呢?

无效的例子:

<?php
class Extended extends Main {
  function __construct ($main) {
    foreach ($main as $k => $v) {
      $this->$k = $v;
    }
  }
}
?>

我需要一些更透明和高效的解决方案:)

I have 2 classes, main and extended. I need to use main vars in extended class.

<?php
class Main {
  public $vars = array();
}

$main = new Main;

$main->vars['key'] = 'value';

class Extended extends Main { }

$other = new Extended;

var_dump($other->vars);

?>

Who I can do it?

No valid for example:

<?php
class Extended extends Main {
  function __construct ($main) {
    foreach ($main as $k => $v) {
      $this->$k = $v;
    }
  }
}
?>

I need some solution more transparent and efficient :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

吃素的狼 2024-07-17 15:46:55

使用简单的构造函数就可以轻松实现

<?php

class One {

    public static $string = "HELLO";

}

class Two extends One {

    function __construct()
    {
        parent::$string = "WORLD";
        $this->string = parent::$string;
    }

}

$class = new Two;
echo $class->string; // WORLD

?>

It would be easily possible with a simple constructor

<?php

class One {

    public static $string = "HELLO";

}

class Two extends One {

    function __construct()
    {
        parent::$string = "WORLD";
        $this->string = parent::$string;
    }

}

$class = new Two;
echo $class->string; // WORLD

?>
天涯沦落人 2024-07-17 15:46:55

编辑:通过控制反转 (IoC) 和依赖注入 (DI) 可以更好地解决这个问题。 如果您使用自己的框架或没有依赖注入容器的框架,请尝试League/Container

下面的答案作为愚蠢答案的历史。


我认为正确的方法。

<?php
class Config {
    protected $_vars = array();

    protected static $_instance;

    private function __construct() {}

    public static function getInstance()
    {
        if (!isset(self::$_instance)) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    public function &__get($name) {
        return $this->_vars[$name];
    }

    public function __set ($name, $value) {
        $this->_vars[$name] = $value;
    }
}

$config = Config::getInstance();
$config->db = array('localhost', 'root', '');
$config->templates = array(
    'main' => 'main',
    'news' => 'news_list'
);

class DB {
    public $db;

    public function __construct($db)
    {
        $this->db = $db;
    }

    public function connect()
    {
        mysql_connect($this->db[0], $this->db[1], $this->db[2]);
    }
}

$config = Config::getInstance();
$db = new DB($config->db);
$db->connect();

class Templates {
    public $templates;

    public function __construct($templates)
    {
        $this->templates = $templates;
    }

    public function load ($where) {
        return $this->templates[$where];
    }
}

$config = Config::getInstance();
$templates = new Templates($config->templates);
echo $templates->load('main') . "\n";

EDIT: This can be solved much better with Inversion of Control (IoC) and Dependency Injection (DI). If you use your own framework or one without Dependency Injection Container try League/Container

Answer below left as history of foolish answers.


The correct way I figure.

<?php
class Config {
    protected $_vars = array();

    protected static $_instance;

    private function __construct() {}

    public static function getInstance()
    {
        if (!isset(self::$_instance)) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    public function &__get($name) {
        return $this->_vars[$name];
    }

    public function __set ($name, $value) {
        $this->_vars[$name] = $value;
    }
}

$config = Config::getInstance();
$config->db = array('localhost', 'root', '');
$config->templates = array(
    'main' => 'main',
    'news' => 'news_list'
);

class DB {
    public $db;

    public function __construct($db)
    {
        $this->db = $db;
    }

    public function connect()
    {
        mysql_connect($this->db[0], $this->db[1], $this->db[2]);
    }
}

$config = Config::getInstance();
$db = new DB($config->db);
$db->connect();

class Templates {
    public $templates;

    public function __construct($templates)
    {
        $this->templates = $templates;
    }

    public function load ($where) {
        return $this->templates[$where];
    }
}

$config = Config::getInstance();
$templates = new Templates($config->templates);
echo $templates->load('main') . "\n";
神回复 2024-07-17 15:46:55

我意识到这已经太老了,但以防万一其他人需要线索......

您是否考虑过使用静态变量?

PHP OOP 设计模式使得父类中静态声明的变量在子类中也保持相同。

例如...

<?php
class A {
    public static $test = 'a';

    public function test() {
        echo 'Test is: '.self::$test;
    }

}
class B extends A {
    public static $test = 'b';
}
$obj = new B;
$obj->test();
?>

运行此代码(在 PHP 5.3 上 - 我确信其他版本也相同)将给出以下结果:

测试是:a

从我在你的OP中收集到的信息来看,你正在寻找一种保留父类变量的方法 - 即使在扩展类中也是如此。 这解决了这个问题。

要在类范围之外公开调用变量(即您通常编写 $obj->vars 的位置),您需要在父类中创建一个引用 的函数self::$variable_name 以便它可以将该变量扔回使用该类或扩展它的任何其他类的代码。

例如,类似:

public function get_variable() {
    return self::$variable;
}

您还可以创建一个神奇的方法,该方法会根据您向实例请求的内容(即方法或变量)动态地返回 self::$ 变量。 在任何情况下,您都可以连接代码以返回 self::$variable 等效项。

阅读 http://php.net/manual/en/language.oop5.magic .php 了解有关允许您执行此类操作的各种魔术方法的更多信息。

OP有点神秘,所以我不确定这是否正是你想要的,但我没有看到这里有其他人引用静态变量,所以我想插话 - 希望它有帮助!

I realize this is super-old, but in case anyone else needs a clue...

Have you considered using static variables?

The PHP OOP design pattern is such that statically declared variables in a parent class remain the same in the child class, too.

For example...

<?php
class A {
    public static $test = 'a';

    public function test() {
        echo 'Test is: '.self::$test;
    }

}
class B extends A {
    public static $test = 'b';
}
$obj = new B;
$obj->test();
?>

Running this code (on PHP 5.3- I'm sure it's the same for other versions, too) will give you the following result:

Test is: a

From what I could gather in your OP, you are looking for a way for the parent class variables to remain - even in extended classes. This solves that problem.

To call the variables publicly outside of the class scope (i.e. where you'd normally write $obj->vars), you'd need to create a function in the parent class that references self::$variable_name so that it can throw that variable back to the code that utilizes either that class, or any other class that extends it.

For example, something like:

public function get_variable() {
    return self::$variable;
}

You could also create a magic method that would dynamically throw back the self::$variable based on what you ask the instance for - i.e. a method or a variable. You could wire the code to throw back the self::$variable equivalent in any case.

Read http://php.net/manual/en/language.oop5.magic.php for more info on the various magic methods that allow you to do this kind of stuff.

The OP was a bit cryptic so I wasn't sure if that's exactly what you wanted, but I didn't see anyone else here reference static variables so thought I'd chime in - hope it helps!

你没皮卡萌 2024-07-17 15:46:55

我认为你需要更清楚自己想要什么。 想象一下您有多个 Main 实例和 Extended 实例。 它们是否都引用相同的数据,以便如果您更改其中任何一个中的数据,它们都会受到影响?

如果是这样,那么一种方法是使用静态变量,该变量与类而不是单个实例相关联。 另一种方法是创建一个单独的对象(不同类的)来存储数据,并在创建主类和扩展类时将其传递给它们。 它们每个都可以存储对它的引用,例如:

class Main {
   public $data;
   function __construct(Data $data) {
     $this->data = $data;
   }
}
class Extended extends Main {}

$ourData = new Data();
$ourData->vars = array(1,2,3);

$main = new Main($ourData);
$other = new Extended($ourData);

如果没有,那么您需要数据的副本,而不是对相同数据的引用。 在这种情况下,您的第二个示例更接近,尽管我不会盲目复制所有成员。

I think you need to be more clear about what you want. Imagine that you had several instances of both Main and Extended. Should they all refer to the same data, so that if you change the data in any one of them, they're all affected?

If so, then one approach is to use a static variable, which is tied to the class rather than the individual instance. Another is to create a separate object (of a different class) to store your data, and pass it to the Main and Extended classes when they're created. They could each store a reference to it, e.g.:

class Main {
   public $data;
   function __construct(Data $data) {
     $this->data = $data;
   }
}
class Extended extends Main {}

$ourData = new Data();
$ourData->vars = array(1,2,3);

$main = new Main($ourData);
$other = new Extended($ourData);

If not, then you want copies of the data, rather than references to the same data. In that case, your second example is closer, although I wouldn't just blindly copy all members.

木緿 2024-07-17 15:46:55

OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOH

您想要以下内容:

class Config
{
    private $m_vars = array();

    function __get($name)
    {
        return $this->m_vars[$name];
    }

    function & __set($name, $value) // << the & is important!
    {
        $this->m_vars[$name] = $value;
    }
}

class Db
{
    funciton __construct(Config $config)
    {
        $this->Connect($config->host, $config->user, $config->pass, $config->db);
    }
}

$config = new Config();
$config->host = "localhost";
...
$db = new Db($config);

:)

编辑:

另外,您可以做到这一点:

class Templator
{
    private $m_config = null;
    function __construct($config)
    {
        $this->m_config = $config;
    }

    function PrintTemplate($name)
    {
        echo file_get_contents($this->m_config->template_path . $name);
    }

}

$config->template_path = "./templates/";
$temp = new Templator($config);
$temp->PrintTemplate("index.html");

oooooooooooooooooooooooooooooooooooooooooooooooooooooh

you want this:

class Config
{
    private $m_vars = array();

    function __get($name)
    {
        return $this->m_vars[$name];
    }

    function & __set($name, $value) // << the & is important!
    {
        $this->m_vars[$name] = $value;
    }
}

class Db
{
    funciton __construct(Config $config)
    {
        $this->Connect($config->host, $config->user, $config->pass, $config->db);
    }
}

$config = new Config();
$config->host = "localhost";
...
$db = new Db($config);

:)

EDIT:

also, you can do this:

class Templator
{
    private $m_config = null;
    function __construct($config)
    {
        $this->m_config = $config;
    }

    function PrintTemplate($name)
    {
        echo file_get_contents($this->m_config->template_path . $name);
    }

}

$config->template_path = "./templates/";
$temp = new Templator($config);
$temp->PrintTemplate("index.html");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文