表示PHP类中的状态数组

时间:2017-09-13 23:12:05

标签: php oop

我不完全确定处理与类中数据库表中的整数相关的状态字段的最佳方法。

说我们有以下内容:

$status = array(1 => 'Active', 2 => 'Inactive', 3 => 'Cancelled');

我正在考虑系统的清晰度,我想要一个类常量和一个用于在关联数组中检索状态的getter,因此该类使用比" 1"更好的定义。或" 2"。

 class User {
  const USER_STATUS_ACTIVE = 1;
  const USER_STATUS_INACTIVE = 2;
  const USER_STATUS_CANCELLED = 3;

  public function getStatusList() {
   return array(User::USER_STATUS_ACTIVE => 'Active',User::USER_STATUS_INACTIVE => 'Inactive',User::USER_STATUS_ACTIVE => 'USER_STATUS_CANCELLED');
  }
 }

然后允许使用以下常量设置状态:

class User {
 private $status_id;

 const USER_STATUS_ACTIVE = 1;
 const USER_STATUS_INACTIVE = 2;
 const USER_STATUS_CANCELLED = 3;

 static public function statusList() {
  return array(User::USER_STATUS_ACTIVE => 'Active',User::USER_STATUS_INACTIVE => 'Inactive',User::USER_STATUS_CANCELLED => 'Cancelled');
 }

 public function setStatus($status_id) {
  try {
   if (!key_exists($status_id, User::statusList())) throw new Exception('Invalid status ID');
   $this->status_id = $status_id;
  }
  catch (Exception $e) {
   die($e);
  }
 }
}

$a = new User();
$a->setStatus(User::USER_STATUS_ACTIVE);

或者,可以为setActive(),setInactive(),setCancelled()创建方法。

但我想弄清楚的是如何最好地处理实际状态值。

将状态分解为静态类会更好吗?

class User {
 private $status_id;

 public function setStatus($status_id) {
  try {
   if (!key_exists($status_id, UserStatuses::statusList())) throw new Exception('Invalid status ID');
   $this->status_id = $status_id;
  }
  catch (Exception $e) {
   die($e);
  }
 }
}

class UserStatuses {
 const USER_STATUS_ACTIVE = 1;
 const USER_STATUS_INACTIVE = 2;
 const USER_STATUS_CANCELLED = 3;

 static public function statusList() {
  return array(UserStatuses::USER_STATUS_ACTIVE => 'Active',UserStatuses::USER_STATUS_INACTIVE => 'Inactive',UserStatuses::USER_STATUS_CANCELLED => 'Cancelled');
 }
}

或者有什么完全不同的东西会更好吗?

2 个答案:

答案 0 :(得分:0)

使用ReflectionClass

我喜欢你的第二个例子;它是一种非常简单有效的枚举类型(类型)。实际上,像Doctrine那样的一些非常大的php ORM使用类似的模式运行。我喜欢做的一件事就是使用ReflectionClass来提高可伸缩性。这将允许您以常量的形式添加新值,而无需更改返回值列表的函数。我还要重构代码以检查枚举类中的值是否有效,以便更好地分离两个类之间的关注点

class User {
    private $status_id;

    public function setStatus($status_id) {
        if (UserStatuses::isStatus($status_id)) {
            $this->status_id = $status_id;
        }
        else {
            throw new Exception('invalid status');
        }
    }
}

class UserStatuses {
    const USER_STATUS_ACTIVE = 1;
    const USER_STATUS_INACTIVE = 2;
    const USER_STATUS_CANCELLED = 3;

    public static function statusList() {
        $oClass = new ReflectionClass(__CLASS__);
        return $oClass->getConstants();
    }

    public static function isUserStatus($int) {
        return in_array($int, self::statusList());
    }
}

答案 1 :(得分:-1)

引用数据库ID不是一个好习惯,因为ID的值通常由数据库本身控制。确实没有数据库列值是静态的,但数据库表上的ID列通常是一个自动递增的内部ID,其FK引用通过UPDATE和DELETE操作中的级联来维护。换句话说,ID是数据库的域,而不是您的代码。

更好的做法是为您的代码添加一个自定义唯一字段,如下所示(我在这里假设MySQL):

ALTER TABLE `my_reference_table` ADD COLUMN `internalCode` VARCHAR(256);
UPDATE `my_reference_table` SET `internalCode` = 'Active' WHERE `id` = 1;
UPDATE `my_reference_table` SET `internalCode` = 'Inactive' WHERE `id` = 2;
UPDATE `my_reference_table` SET `internalCode` = 'Cancelled' WHERE `id` = 3;
ALTER TABLE `my_reference_table` ALTER COLUMN `internalCode` VARCHAR(256) NOT NULL UNIQUE;

一旦你有了这样的数据库数据设置,那么你可以将列internalCode视为静态元素,使PHP常量与那些内部代码匹配,并确保你指的是如果ID发生变化,同一行。

在PHP中存储这些内部代码方面,我通常使用一个带有最终私有构造函数的抽象类,因此非常清楚该类不能被扩展,并且只能在静态上下文中引用,像这样:

class UserStatusConstants {
    const _ACTIVE = 'Active';
    const _CANCELLED = 'Cancelled';
    const _INACTIVE = 'Inactive';

    final private function __construct() {}
}

您可能会在这一点上询问为什么常量名称以下划线为前缀 - 这是为了避免使用常量名称与PHP中的保留字冲突。

无论如何,一旦你有了这个设置,就可以使用各种技术在user_status_id表中设置user值。这是我能想到的三个:

使用JOIN查询进行更新 使用针对用户状态表的JOIN执行UPDATE,并过滤内部代码(请参阅How to do 3 table JOIN in UPDATE query?

选择然后更新 从针对用户状态表的SELECT查询开始,过滤内部代码,然后使用该结果将用户状态ID提供给针对用户表的UPDATE查询。此技术会产生额外的查询,但如果您将第一个查询的结果存储在缓存中(例如Memcached或第三方库),那么从长远来看,这可以加快使用该数据的所有查询。

存储过程 您可以创建一个存储过程,将内部代码作为参数,以及您需要传递以更新用户表中其他字段的任何其他参数