jlorente/yii2-activerecord-inheritance

ActiveRecord Inheritance 是一个工具,用于为 Yii2 框架提供类表继承模式。它模拟两个 ActiveRecord 类之间的继承。

1.0.8 2023-11-15 19:04 UTC

This package is auto-updated.

Last update: 2024-09-15 20:53:20 UTC


README

ActiveRecord Inheritance 是一个工具,用于为 Yii2 框架提供类表继承模式。它的动机是模拟两个 ActiveRecord 类之间的继承。

安装

在 bower.json 文件中将包作为依赖项包含。

要安装,可以运行

$ php composer.phar require jlorente/yii2-activerecord-inheritance "*"

或者将以下内容添加到你的 composer.json 文件的 require 部分:

...
    "require": {
        ...
        "jlorente/yii2-activerecord-inheritance": "*"
    }

使用方法

使用示例可能如下:

假设你有以下架构。

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `last_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `created_at` int(11) NOT NULL,
  `updated_at` int(11) NOT NULL,
  PRIMARY KEY (`id`)
);

CREATE TABLE `admin` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `level` INT NOT NULL,
  `banned_users` INT NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  CONSTRAINT `FK_Admin_Id` FOREIGN KEY (`id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
);

要模拟两个表之间的继承,你的代码应该看起来像这样。

use jlorente\db\ActiveRecordInheritanceTrait,
    jlorente\db\ActiveRecordInheritanceInterface;
use yii\db\ActiveRecord;

class User extends ActiveRecord {

    public function tableName() {
        return 'user';
    }

    public function doSomething() {
        echo 'User does something';
    }
}

class Admin extends ActiveRecord implements ActiveRecordInheritanceInterface {
    use ActiveRecordInheritanceTrait;

    public function tableName() {
        return 'admin';
    }

    public static function extendsFrom() {
        return User::className();
    }

    public function doSomething() {
        echo 'Admin does something';
    }
}

你将能够像使用继承自 User 对象的 Admin 对象一样使用 Admin 对象。

$admin = new Admin();
$admin->username = 'al-acran';
$admin->email = 'al_acran@gmail.com';
$admin->name = 'Al';
$admin->last_name = 'Acran';
$admin->level = 1;
$admin->save();

你可以通过使用父关系属性来调用父方法和方法属性。

$admin->doSomething()           //Admin does something
$admin->parent->doSomething()   //User does something

这个特性在模拟继承时非常有用,但是应该在对父关系应用查询过滤器。

$admin = Admin::find()
    ->joinWith('parent', function($query) {
        $query->andWhere(['username' => 'al-acran']);
        $query->andWhere(['name' => 'Al']);
    })
    ->andWhere(['level' => 1])
    ->one();

注意事项

为了正确使用特性,你必须考虑以下要点

通用

  • 默认情况下,假设的子类的主键被用作父模型的外键,如果你想使用其他属性作为外键,你应该重写 parentAttribute() 方法。
  • 该特性不适用于多个主键和外键。

ActiveRecord 方法

  • 在此特性中重写的来自 ActiveRecord 的方法(如 save、validate 等)不应在使用特性的类上重写,否则功能将丢失。
  • 要正确地重写这些方法,可以扩展使用特性的类,并在那里重写方法,确保所有方法都调用其父实现。

继承调用层次结构

  • 自然调用层次结构被保留,因此如果方法或属性存在于被调用的类或其祖先中,则调用该方法或属性。
  • 如果方法或属性不在自然调用层次结构中,将调用适当的魔术方法(__get、__set、__isset、__unset、__call),并使用 yii2 调用层次结构。如果方法或属性未在此调用层次结构中找到,则执行下一步。
  • 上述过程将重复用于模拟的父对象。
  • 当找到方法或属性或没有更多父对象时,调用层次结构将停止。在这种情况下,将引发 UnknownPropertyException 或 UnknownMethodException。
  • 你可以将模拟的父类连接起来,仅限于 php 调用堆栈的限制。

许可证

版权 © 2015 José Lorente Martín jose.lorente.martin@gmail.com。许可协议为 MIT。有关详细信息,请参阅 LICENSE.txt。