سؤال

لدي 2 فصول، رئيسي وممتد. أحتاج إلى استخدام Vars الرئيسية في الفئة الممتدة.

<?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;
    }
  }
}
?>

أحتاج إلى بعض الحل أكثر شفافية وفعالة :)

هل كانت مفيدة؟

المحلول

تعديل: يمكن حل هذا أفضل بكثير مع قلب السيطرة (IOC) و حقن التبعية (دي). إذا كنت تستخدم الإطار الخاص بك أو واحد دون حاوية حقن التبعية يحاول الدوري / الحاويات

الإجابة أدناه اليسار كتاريخ من الإجابات الحمقاء.


الطريقة الصحيحة أنا الشكل.

<?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";

نصائح أخرى

سيكون من الممكن بسهولة مع منشئ بسيط

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

?>

أدرك أن هذا قديم فائق، ولكن في حالة أي شخص آخر يحتاج إلى فكرة ...

هل فكرت باستخدام المتغيرات الثابتة؟

نمط تصميم OOP PHP هو مثل المتغيرات المعلنة القانونية في الأبوين الطبقة تبقى هي نفسها في طفل الطبقة أيضا.

علي سبيل المثال...

<?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 - أنا متأكد من أنه نفس الشيء بالنسبة للإصدارات الأخرى أيضا) سوف يمنحك النتيجة التالية:

اختبار هو:

من ما يمكن أن أجمع في المرجع السابق، فأنت تبحث عن وسيلة ل متغيرات الطبقة الأصل البقاء - حتى في الفصول الممتدة. هذا يحل هذه المشكلة.

لاستدعاء المتغيرات علانية خارج نطاق الفصل (أي حيث تكتب عادة $ obj-> vars)، سوف تحتاج إلى إنشاء وظيفة في الفئة الأصل التي تشير self::$variable_name بحيث يمكن أن يرمي هذا المتغير مرة أخرى إلى الرمز الذي يستخدم إما هذه الفئة، أو أي فئة أخرى تمددها.

على سبيل المثال، شيء مثل:

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

يمكنك أيضا إنشاء طريقة سحرية من شأنها رمي متغير الذات: $ ديناميكيا بناء على ما تسأل مثيله - أي طريقة أو متغير. يمكنك أن ترأس التعليمات البرمجية لرمي الذات: ما يعادل المتغير الذاتي على أي حال.

اقرأ http://php.net/manual/en/language.oop5.magic.php. لمزيد من المعلومات حول الطرق السحرية المختلفة التي تتيح لك القيام بهذا النوع من الأشياء.

كان المرجع قد خفف قليلا لذلك لم أكن متأكدا مما إذا كان هذا هو بالضبط ما تريد، لكنني لم أر أي شخص آخر هنا مرجع المتغيرات الثابتة لذلك اعتقدت أنني تتناغم - آمل أن يساعد ذلك!

أعتقد أنك بحاجة إلى أن تكون أكثر وضوحا حول ما تريد. تخيل أن لديك عدة حالات من كل من رئيسي وممتد. يجب أن يشير جميعا إلى نفس البيانات، بحيث إذا قمت بتغيير البيانات في أي منهم، فإنهم يتأثرون جميعا؟

إذا كان الأمر كذلك، فإن نهج واحد هو استخدام متغير ثابت، وهو مرتبط بالصف بدلا من المثيل الفردي. آخر هو إنشاء كائن منفصل (فئة مختلفة) لتخزين البيانات الخاصة بك، وتمريرها إلى الفصول الرئيسية والموسعة عند إنشائها. يمكن أن يكون كل متجر إشارة إليه، على سبيل المثال:

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);

إذا لم يكن الأمر كذلك، فأنت تريد نسخ من البيانات، بدلا من الإشارات إلى نفس البيانات. في هذه الحالة، مثالتك الثانية أقرب، على الرغم من أنني لن أفعل فقط نسخ جميع الأعضاء.

OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOH.

انت تريد هذا:

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");
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top