PHP对象扩展$this->some\u Object->method
我试图制作一个脚本,其中不同的类(例如数据库、实用程序、配置)都用于形成一个中心主类。我已经尝试过扩展一系列: 主->实用程序->数据库->配置 但是,我如何设置不同的部分,以便它们可以这样命名:PHP对象扩展$this->some\u Object->method,php,inheritance,oop,object,Php,Inheritance,Oop,Object,我试图制作一个脚本,其中不同的类(例如数据库、实用程序、配置)都用于形成一个中心主类。我已经尝试过扩展一系列: 主->实用程序->数据库->配置 但是,我如何设置不同的部分,以便它们可以这样命名: <?php $this->db->select("WAFFLES"); echo($this->config->app_path); ?> 您需要在主类中将每个新对象声明为变量,如: class Main{ private $db
<?php
$this->db->select("WAFFLES");
echo($this->config->app_path);
?>
您需要在主类中将每个新对象声明为变量,如:
class Main{
private $db = NULL;
private $config = NULL;
$this->db = new Database;
$this->config = new Config;
}
等等
虽然我不是一个专业的程序员,但我会考虑一个更好的方法。这种对象处理可能导致主类膨胀,在最坏的情况下,您可能会面临一些性能问题。以下是示例原型:
include 'db.php'; // include db class
include 'config.php'; // include config class
class main{
public $db = NULL;
public $config = NULL;
function __construct() {
$this->db = new db;
$this->config = new config;
}
}
您可以创建一个执行基本初始化的全局类
class Base {
$var1, var2;
public function __construct() {
$this->var1 = new DB();
$this->var2 = new Config();
....
}
}
然后类可以扩展基类并访问数据
class Foo extends Base {
public function bar() {
$this->var1->someOpertaion();
}
}
创建一个包含代码执行过程中可能需要的所有内容的实例的复合对象完全是浪费资源。您希望仅在需要时创建实例。实现这一点的一种方法是向类中添加一个magic __get方法:
public function __get($name) {
// if self::$instances (or main) contains instance of $name, return instance
// else if class_exists $name, create, store and return instance
// else throw exception
}
但即便如此,您也有可能正在创建一个新的访问器,并且魔术方法比常规访问器要慢一些。如果需要以这种方式创建实例,请查看或实现 1使用自动加载或加载类
2使用神奇的方法,在获取未知属性时调用函数。以下示例演示如何仅在使用uuu get和dynamicali初始化对象时使用它们
//use __autoload to load db and config class when they are called.
class db{
function lol(){
echo 'Hello from db->lol() <br />';
}
}
class config{
function lol(){
echo 'Hello from config->lol() <br />';
}
}
//Manager class to use with classes where you want to access other object trough $this
class Manager{
private $_instances=array();
function __get($name){
//if instance does not exists, create one
if (!isset($this->_instances[$name])){
$this->_instances[$name]=new $name();
}
//return instance
return $this->_instances[$name];
}
}
class Some extends Manager{
function f1(){
$this->db->lol();
$this->config->lol();
}
}
$some=new Some();
$some->f1(); //echoes 'Hello from db->lol()' and 'Hello from config->lol()'
以下是受Gordon评论启发的解决方案:
它使用GlobalClassFactory类仅定义全局类的一个实例
class db{
function lol(){
echo 'Hello from db->lol() <br />';
}
}
class config{
function lol(){
echo 'Hello from config->lol() <br />';
}
}
class GlobalClassFactory{
private static $_classes=array();
public static function getInstance($name){
if (!isset(self::$_classes[$name])){
self::$_classes[$name]=new $name();
}
return self::$_classes[$name];
}
}
class Base{
function __get($name){
return GlobalClassFactory::getInstance($name);
}
}
class Some extends Base{
function f1(){
$this->db->lol();
$this->config->lol();
}
}
$some=new Some();
$some->f1();
从通用基类生成子类几乎总是一个坏主意。你正在建立一种关系,说一些人是经理,而实际上不是。此外,如果您将实例存储为对象实例,任何类扩展管理器都将仅为自身创建单独的实例,而在db和config的情况下,这是不可能需要的。单例可以缓解这种情况,但由于单例不能用new实例化,因此_get中的代码将不再工作。不管怎样,单例通常是个坏主意。戈登,你是对的,所以我创建了一个解决方案,其中每个全局类只创建一个实例。但是为什么单身是个坏主意呢?你刚刚交换了一个问题:你现在如何创建非单身呢?此外,您仍在创建is-a关系,现在还通过将基类硬编码到_get方法中,将基类与工厂耦合,从而有效地将基类简化为神奇的getter。我的意思是,它确实有效,但在我看来,它的设计很糟糕。尽量避免全局性的东西。单例是个坏主意,因为它们更难测试,并且在全局范围内添加紧密耦合和依赖性。这会降低应用程序的可维护性。
class db{
function lol(){
echo 'Hello from db->lol() <br />';
}
}
class config{
function lol(){
echo 'Hello from config->lol() <br />';
}
}
class GlobalClassFactory{
private static $_classes=array();
public static function getInstance($name){
if (!isset(self::$_classes[$name])){
self::$_classes[$name]=new $name();
}
return self::$_classes[$name];
}
}
class Base{
function __get($name){
return GlobalClassFactory::getInstance($name);
}
}
class Some extends Base{
function f1(){
$this->db->lol();
$this->config->lol();
}
}
$some=new Some();
$some->f1();