【问题标题】:Get object from arraycollection从数组集合中获取对象
【发布时间】:2012-09-29 21:10:55
【问题描述】:

我在按 ID 从对象数组集合中获取对象时遇到问题。

以下是我的代码:

protected $_rootLocation;

public function __construct(Location $rootLocation)
{
    $this->_rootLocation= $rootLocation;

    var_dump($this->_rootLocation);
}

public function getLocationById($id)
{
    $value = null;
    foreach($this->_rootLocationas $root)
      {
            if ($id == $root->getId())
            {
                $value = $root;
                break;
            }
       }

    return $value;
}

然后函数返回“NULL”所以它不起作用......

编辑

我喜欢这样:

    $manager = new LocationManager($rootLocation);

    echo "<pre>";
    var_dump($manager->getLocationById('291'));
    echo "</pre>";

【问题讨论】:

  • 如果在 foreach 循环初始化程序之后添加这一行,结果是什么?回声 $id 。 ':'。 $root->getId();
  • 这意味着循环没有迭代?这意味着它没有什么可以循环的,不支持所需的接口。除非您正在进行一些自定义缓冲。如果不能看到 myClasse 是如何形成的,就很难知道更多。这将我们引向@JvdBerg 的答案。您是否尝试过启用错误报告:error_reporting(E_ALL); ini_set('display_errors', '1');

标签: php symfony doctrine-orm


【解决方案1】:

您的函数返回 null,因为找不到对象!

这取决于myClasse对象的实现,它必须实现iterator接口并且getId()方法必须在每次迭代时返回一个有效的Id。

【讨论】:

  • 但是我做了 var_dump($this->_rootObject) 并且它给我返回了一个对象的arrayCollection(输入我的类)......
  • 还有GetId()和集合的id,是否和请求的id匹配?
  • 当然是的,但是我有一些非常奇怪的东西,当我将 var_demp() 放入 foreach 时,我没有任何反应?所以它拒绝运行 foreach 或 foreach 中排除的内容?
  • 如果 foreach 没有循环(你没有从 var_dump 得到输出)那么集合是空的!您应该在构造函数中使用 var_dump($rootObject)。
  • 在构造函数中使用 var_dump 它返回 Myclass 类型的对象的数组集合...
【解决方案2】:

想象一下,数组中的所有对象都没有您要查找的 ID。你的函数只会返回null。例如一个空数组。

如您所见,返回null 并不意味着该功能不起作用。它完美地工作并且做了你指定的事情,只是不存在这样的对象。

然后由您决定如果发生这种情况该怎么办。正如您在问题中没有说的那样,没有什么要补充的,只是为您提供了一些选择:

  • 您可以检查函数是否返回null,然后将其视为“未找到”情况。

    $result = $collection->getObjectById($id);
    if (null === $result) {
        # object not found
    } else {
        # object found
    }
    
  • 如果只应为现有对象调用函数,则可以在函数内抛出异常:

    public function getObjectById($id) {
    
        foreach ($this->_rootObject as $root) {
            if ($id == $root->getId()) {
                return $root;
            }
        }
    
        throw new InvalidArgumentException(sprintf('Not a valid ID: %d', $id));
    }
    

或者最后:

  • 提供一个额外的功能来首先检查现有的 ID:

    private function findById($id) {
    
        foreach ($this->_rootObject as $object) {
            if ($id == $object->getId()) {
                return $object;
            }
        }
        return null;
    }
    
    public function hasObjectById($id) {
    
        return null !== $this->findById($id);
    }
    
    public function getObjectById($id) {
    
        if (null !== $root = $this->findById($id)) {
            return $root;
        }
    
        throw new InvalidArgumentException(sprintf('Not a valid ID: %d', $id));
    }
    

您也可能有兴趣为自己创建一个封装您需求的类,因此您不需要在“我管理根集合对象”对象中实现它,这不仅仅是间接的。那么这基本上就是你自己的集合类。一个例子:

interface Identifiable {
    public function getId();
}

/**
 * Example Object Class
 */
class MyObject implements Identifiable {
    private $id;

    public function __construct($id) {
        $this->id = (int) $id;
    }

    public function getId() {
        return $this->id;
    }
}

/**
 * Example Collection
 */
class IdentifiableCollection implements Countable, IteratorAggregate
{
    private $objects;

    public function attach(Identifiable $object) {
        $id = $object->getId();
        $this->objects[$id] = $object;
    }

    public function count() {
        return count($this->objects);
    }

    public function has($id) {
        return isset($this->objects[$id]);
    }

    public function getById($id) {
        if ($this->has($id)) {
            return $this->objects[$id];
        }
        throw new InvalidArgumentException(sprintf("No object is identifiable for %d", $id));
    }

    public function getIterator() {
        return new ArrayIterator($this->objects);
    }
}

// create the collection
$collection = new IdentifiableCollection();

// fill the collection with some objects (ID 1 - 20)
foreach(range(1, 20) as $id) {
    $collection->attach(new MyObject($id));
}

// test if an id exists and return object
$id = 2;
var_dump($collection->has($id), $collection->getById($id));

// iterate over the collection
foreach ($collection as $object) {
    var_dump($object);
}

这个集合类只提供附加对象,而不是删除它们,但您可以根据需要对其进行扩展。如果您想重用现有功能,也可以从现有类扩展,如 ArrayObject 或 SplObjectStorage。在一个有点相关的问题的另一个答案中给出了一个例子:

【讨论】:

  • 我想说你的问题更多的是你需要研究孩子。 var_dump 中缺少根元素的类型,这会很有帮助(它在一开始)。
  • 我不明白你的意思
  • 数据类型。 var_dump 输出的顶部被切除。
  • 你的意思是$this->_rootLocation,你想知道所有var_dump的返回,在CLI我不能有所有的var_dump输出?
猜你喜欢
  • 1970-01-01
  • 2021-09-05
  • 2014-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-06
  • 1970-01-01
相关资源
最近更新 更多