I have never worked with MongoDb and I am also new to symfony and ODM. I have a collection called userlist. In userlist I want to save multiple books. The book Id's get selected on a Form which I send to the server, in my controller I want to use all the selected BookIds use find($id) and save the returned Book details in my Userlist.
Document\Userlist.php
class Userlist{
/**
* @MongoDB\Id
*/
private $id;
/**
* @MongoDB\Field(type="string")
*/
private $name;
/**
* @MongoDB\Field(type="collection")
*/
private $books;
}
public function __construct()
{
$this->books = new ArrayCollection();
}
public function getBooks(): ?array
{
return array_unique($this->books);
}
public function setBooks(array $books): self
{
$this->books= $books;
return $this;
}
MyController.php
foreach ($_POST['books'] as $bookObjectId) {
$bookData= $dm->getRepository(Book::class)->find($bookObjectId);
$userlist->setBooks($bookData);
$dm->persist($userlist);
$dm->flush();
}
If I use above I get Collection type requires value of type array or null, Doctrine\Common\Collections\ArrayCollection given. So if I take $this->books = new ArrayCollection(); out this error disappears. Unfortunately all I get saved to the document is
books [0]
No data is saved. If I use
$bookData= $dm->getRepository(Book::class)->find($bookObjectId);
$books = array('_id' => $bookData->getId(),
'name' =>$bookData->getBookName());
$userlist->setBooks($bookData);
$dm->persist($userlist);
$dm->flush();
Then the data will be all saved, but I would like to just get my 1 Document and save it straight into another document without re-creating an Array with calling all the getters and then save that. I have tried to read all over the internet, but I just don't get it. I also tried
public function addBooks(Book $books)
{
$this->books[] = $books;
return $this;
}
but again no luck. The Form by the way has got no BookId form field. Instead I create this dynamic with jQuery, but I doubt that this is a problem. Can anyone point in the right direction by any chance, this would be brilliant. Thank you very much.
UPDATE
My repository file:
public function findReturnArray($id)
{
return $this->createQueryBuilder()
->hydrate(false)
->field('_id')->equals($id)
->getQuery()
->execute()->toArray();
}
In the controller:
foreach ($_POST['bookIds'] as $orderObjectId) {
$bookData[] = $dm->getRepository(Book::class)->findReturnArray($bookObjectId);
}
$userlist->setBooks($bookData);
$dm->persist($userlist);
That does save both books into books but I have 1 issue. It is saved like this
books
[] [0]
{}[0]
bookId
bookName etc
[] [1]
{}[0]
bookId
bookName
what I would like is:
books
{}[0]
bookId
bookName etc
{}[1]
bookId
bookName
setBooks is still the same but I took the $this->books = new ArrayCollection(); out. any idea how I can stop this now?
If you want to persist references to Book
documents in your Userlist
document, you have to use the ReferenceMany
annotation (see docs).
class Userlist
{
// ...
/**
* @MongoDB\ReferenceMany(targetDocument="My\Namespace\Book", storeAs="id")
*/
private $books;
public function __construct()
{
$this->books = new ArrayCollection();
}
public function getBooks(): array
{
return $this->books->getValues();
}
public function addBook(Book $book)
{
if ($this->books->contains($book)) {
return;
}
$this->books->add($book);
}
}
foreach ($_POST['books'] as $bookObjectId) {
$book = $dm->getRepository(Book::class)->find($bookObjectId);
$userlist->addBook($book);
}
$dm->persist($userlist);
$dm->flush();
UPDATE
After reading your update, I guess this is the change you are looking for:
public function findReturnArray($id)
{
return $this->createQueryBuilder()
->hydrate(false)
->field('_id')->equals($id)
->getQuery()
->getSingleResult();
}