Zend framework 如何使用Zend Framework在域中建立多表继承?

Zend framework 如何使用Zend Framework在域中建立多表继承?,zend-framework,orm,multiple-inheritance,Zend Framework,Orm,Multiple Inheritance,我有一个数据库结构,它有一个Person表,其中包含诸如name、email、company\u id、personType等字段。因为不是所有的人都必须是系统用户,所以我有一个单独的表user,它为系统中的用户定义用户名和密码 我有以下代码来定义Person表的表数据网关: class Model_Table_Person extends Zend_Db_Table_Abstract { protected $_name = 'person'; protected $_prim

我有一个数据库结构,它有一个Person表,其中包含诸如name、email、company\u id、personType等字段。因为不是所有的人都必须是系统用户,所以我有一个单独的表user,它为系统中的用户定义用户名和密码

我有以下代码来定义Person表的表数据网关:

class Model_Table_Person extends Zend_Db_Table_Abstract
{
    protected $_name = 'person';
    protected $_primary = 'person_id';

    protected $_referenceMap = array(
        'Company' =>    array(
            'columns' => 'company_id',
            'refTableClass' => 'Company',
            'refColumns' => 'id'
        ),
        'Store' =>  array(
            'columns' => 'store_id',
            'refTableClass' => 'Store',
            'refColumns' => 'id'
        )
    );

    public function findByPersonType(string $personType)
    {
        $where = $this->getAdapter()->quoteInto('personType = ?', $personType);
        return $this->fetchAll($where);
    }
}
此代码为Person定义域对象:

class Model_Person
{
    protected static $_gateway;

    protected $_person;

    public static function init()
    {
        if(self::$_gateway == null)
        {
            self::$_gateway = new Model_Table_Person();
        }
    }

    public static function get(string $searchString, string $searchType = 'id') 
    {
        self::init();

        switch($searchString)
        {
            case 'id':
                $row = self::$_gateway->find($id)->current();
                break;
        }

        return self::factory($row);
    }

    public static function getCollection(string $searchString, string $searchType = null)
    {
        self::init();

        switch($searchType)
        {
            case 'userType':
                $row = self::$_gateway->findByPersonType($searchString);
                break;
            default:
                $personRowset = self::$_gateway->fetchAll();
                break;
        }

        $personArray = array ();

        foreach ($personRowset as $person)
        {
            $personArray[] = self::factory($person);
        }

        return $personArray;
    }

    public function getCompany()
    {
        return $this->_person->findParentRow('Company');
    }

    public function getStore()
    {
        return $this->_person->findParentRow('Store');
    }

    protected static function factory(Zend_Db_Table_Row $row) 
    {
        $class = 'Model_Person_' . ucfirst($row->personType);
        return new $class($row);
    }

    // protected constructor can only be called from this class, e.g. factory()
    protected function __construct(Zend_Db_Table_Row $personRow)
    {
        $this->_person = $personRow;
    }
}
最后,我为用户提供了另一个表数据网关:

class Model_Table_User extends Zend_Db_Table_Abstract
{
    protected $_name = 'user';
    protected $_primary = 'person_id';

    public function findByUserName()
    {

    }
}
还有一个扩展Model_Person表的基本类,如下所示:

class Model_User extends Model_Person
{       
    public function login()
    {

    }

    public function setPassword()
    {

    }   
}

如何正确地扩展“Model\u User”类(它为除一个以外的所有其他类型的用户提供基本类型)以使用映射到一个表的“Model\u Person”类函数,同时也将实际的“Model\u User”函数映射到第二个表?

这是PHP的一个巨大弱点(在5.3.0之前)--缺乏对政府的支持

也就是说,当一个静态方法(如
get()
调用另一个静态方法(如
init()
)时,它总是使用该类中定义的
init()
方法。如果子类定义了一个替代方法
init()
,并调用
get()
,希望它调用被重写的
init()
,则不会发生这种情况

class A
{
  static $var = null;
  static function init() { self::$var = 1234; }
  static function get() { self::init(); }
}

class B extends A
{
  static function init() { self::$var = 5678; }
}

B::get();
print B::$var . "\n"; 
这将打印“1234”,而您可能希望它打印“5678”。这就好像
A::get()
不知道它是类
B
的一部分。解决方法是必须将
get()
方法的实现复制到子类中,即使它与超类没有什么不同这非常不令人满意

PHP 5.3.0试图解决此问题,但您必须在
get()
中对其进行稍微不同的编码:

PHP5.3.0目前仍处于alpha版本


有几种可能的解决办法:

  • 不要将
    Person
    子类化为
    User
    ,而是将login和password属性添加到
    Person
    类中。如果这些属性为NULL,则它是非用户,函数
    login()
    setPassword()
    应该注意这一点,并抛出异常或返回false或其他内容

  • 每个子类型使用不同的
    get()
    方法:
    getUser()
    getPerson()
    ,等等。每种方法都将初始化各自的表对象


那么,您会以不同的方式设计用户和个人类之间的关系吗?我想尝试这种扩展Model_Person类的方法,然后为User对象实现第二个$_gateway对象,但它似乎没有很好地结合在一起。我想我已经决定需要使用User和Person表的$_referenceMap来定义User表中数据的使用,而不是尝试创建某种多网关继承?这听起来是否正确?是的,我感觉PHP语言目前不支持您正在尝试的操作。毕竟,您可能需要一个工厂类。
function get() {
  static::init();
}