【问题标题】:Best way to create associative array of unique objects in PHP?在 PHP 中创建唯一对象的关联数组的最佳方法是什么?
【发布时间】:2021-03-09 17:38:17
【问题描述】:

我正在尝试在 PHP 中创建一个唯一对象列表。 我想通过一个唯一的名称访问每个对象,但我还需要该对象知道它的名称。

我的想法是创建一个这样的关联对象数组:

class MyObject()
{
    public $name;
    public $property1;
    public $property2;

    function __construct($name)
    {
        $this->name = $name;
    }

    function doSomething()
    {
        echo $name.$property1;
    }

    function doSomethingElse()
    {
        echo $name.$property2;
    }
}

$array = array();

$name = 'example';
$array[$name] = new MyObject($name);
$array[$name]->property1 = 'xyz';
$array[$name]->property2 = 123;

$name = 'test';
$array[$name] = new MyObject($uniqueName);
$array[$name]->property1 = 'abc';
$array[$name]->property2 = 321;

$array['example']->doSomething();
$array['test']->doSomethingElse();

我对 PHP 和编码很陌生,我觉得这是一个非常愚蠢的解决方案,所以我想问你是否知道任何更好的方法。

【问题讨论】:

  • 我个人认为这种方法会有一个流程:按原样使用此代码,您不能保证此名称的唯一性。我会尝试使用处理添加新对象并将它们与唯一名称(存储在私有属性中)相关联的“主”对象,并确保每次尝试添加新对象时该名称尚未使用。这也提供了一个漂亮的方法,如“getObjectByName(string $name)”和“addObject($object, string $name)”。
  • 什么是独特的对象?具有相同属性的两个对象是否被视为相同?
  • $name 是您的 doSomethingdoSomethingElse 声明中未声明的变量。

标签: php arrays object associative-array


【解决方案1】:

对于您提供的简单用例,实现预定义接口ArrayAccess 可能符合要求。比如:

class UniqueCollection implements ArrayAccess
{
    /**
     * @var  array<string, MyObject>
     */
    private $collection = [];

    /**
     * @param  mixed  $offset
     *
     * @return  bool
     */
    public function offsetExists($offset): bool
    {
        return isset($this->collection[$offset]);
    }

    /**
     * @param  mixed  $offset
     *
     * @return  MyObject|null
     */
    public function offsetGet($offset): mixed
    {
        return $this->collection[$offset] ?? null;
    }

    /**
     * @param  mixed                $offset
     * @param  array<mixed, mixed>  $values
     *
     * @return  void
     */
    public function offsetSet($offset, $values): void
    {
        if ($offset === null) {
            // Error
        }

        // Uncomment if we don't want to overwrite existing MyObject with the same name,
        // eg, throw exception
        // if (isset($this->collection[$offset]) {
        //     // Error
        // }

        $count($values);
        if ($count !== 0 || $count !== 2) {
            // Error
        }

        $myObj = new MyObject($offset);
        if ($count) {
            // Fetch the values only so we only have to deal with zero-based integer offsets
            $values = array_values($values);
            // Establish a convention on which index goes to what property
            $myObj->property1 = $values[0];
            $myObj->property2 = $values[1];
        }

        $this->collection[$offset] = $myObj;
    }

    /**
     * @param  mixed  $offset
     *
     * @return  void
     */
    public function offsetUnset($offset): void
    {
        return unset($this->collection[$offset]);
    }
}

用途:

$set = new UniqueCollection();

$set['example'] = ['xyz', 123];

$set['test'] = [];  // not exactly elegent, but hey ¯\_(ツ)_/¯
$set['test']->property1 = 'abc';  // should work fine, unless we clone the MyObject internally
$set['test']->property2 = 321;  // ditto

$set['example']->doSomething();
$set['test']->doSomethingElse();

我没有对此进行测试,如果有任何问题,请告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-27
    • 2011-08-26
    • 2011-09-18
    • 1970-01-01
    • 2020-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多