遍历
只有当对象属性是可访问的(通过 public 访问或具有 public 访问器方法,例如 public getter)时,才会对其进行验证。如果你的对象需要被遍历以验证其数据,你可以使用此约束。
基本用法
在以下示例中,创建两个类 BookCollection
和 Book
,它们都在其属性上具有约束。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
// src/Entity/BookCollection.php
namespace App\Entity;
use App\Entity\Book;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity]
#[Assert\Traverse]
class BookCollection implements \IteratorAggregate
{
/**
* @var string
*/
#[ORM\Column]
#[Assert\NotBlank]
protected string $name = '';
/**
* @var Collection|Book[]
*/
#[ORM\ManyToMany(targetEntity: Book::class)]
protected ArrayCollection $books;
// some other properties
public function __construct()
{
$this->books = new ArrayCollection();
}
// ... setter for name, adder and remover for books
// the name can be validated by calling the getter
public function getName(): string
{
return $this->name;
}
/**
* @return \Generator|Book[] The books for a given author
*/
public function getBooksForAuthor(Author $author): iterable
{
foreach ($this->books as $book) {
if ($book->isAuthoredBy($author)) {
yield $book;
}
}
}
// neither the method above nor any other specific getter
// could be used to validated all nested books;
// this object needs to be traversed to call the iterator
public function getIterator(): \Iterator
{
return $this->books->getIterator();
}
}
当对象实现 \Traversable
接口(例如这里使用了其子接口 \IteratorAggregate
)时,其遍历策略将被隐式设置,并且对象将被迭代,而无需定义约束。主要用于显式添加它,或使用 traverse
选项禁用遍历。如果存在一个 public getter 来返回内部书籍集合,例如 getBooks(): Collection
,则可以在 $books
属性上使用 Valid 约束。
本作品,包括代码示例,根据 Creative Commons BY-SA 3.0 许可协议获得许可。