I want to manually add items to a collection - works fine with a collection returned from get(), but fails when collection returned from paginate(), e.g.
$rows = $query->get();
$rows->add(new Model());
working fine
$rows = $query->paginate(10);
$rows->add(new Model());
give this error: Paginator.php 502: call_user_func_array() expects parameter 1 to be a valid callback, class 'Illuminate\Support\Collection' does not have a method 'add'
I guess paginate is returning a paginator object rather than an eloquent collection, just wondering if there is a way to append to this?
Thanks :-)
Laravel 5:
$rows->getCollection()->add(new Model());
Laravel 4:
add is Eloquent\Collection method and you can't use it on the Paginator which relies on Support\Collection.
Use this workaround if you need to append items:
$items = $rows->getItems();
$items[] = new Model();
$rows->setItems($items);
Related
I have a question: I need to get communication with algolia, but i cannot get that work, since of leak of documentation. I have symfony 5.4 but algora docs provide only for version 4, second when I trying to get some of my entities indexed i get stuck at the point when i have to provide entityManager which suppose to implement ObjectManager, but that one it is not wired in the service. And how many people suggest we should not use this directly and use EntityManagerInteface instead. So how i have to index my Entity?
What i did:
composer require algolia/search-bundle
Added credentials:
ALGOLIA_APP_ID="U1RFIHY01W"
ALGOLIA_API_KEY="YourAPIKey"
Trying to index in the controller for testing:
public function searchPosts(Post $post, ManagerRegistry $em): JsonResponse
{
$posts = $this->postRepository->searchPosts('82819');
$postsArray = [];
/**#var Post $post */
foreach ($posts as $post){
$postsArray = $post->normalize();
}
$this->searchService->index($em->getManager(), $postsArray);
return new JsonResponse($this->searchService->getConfiguration());
}
Right now since i use ManagerRegestry i get an error:
get_class(): Argument #1 ($object) must be of type object, int given
Can you help me work around? Thank you
Separate the two instructions with :
$entityManager= $em->getManager();
and then
$this->searchService->index($entityManager, $lpostsArray);
In my Symfony2 controller, I have two queries:
like in this example:
$object = $this->getDoctrine()->getManager()
->createQuery('SELECT PARTIAL o.{id,name,field1}
FROM SomeBundle:SomeEntity o
WHERE o.id = :objectId')
->setParameter('objectId', $objectId)
->getResult();
$objects = $this->getDoctrine()->getManager()
->createQuery('SELECT PARTIAL o.{id,name,field1, field2}
FROM SomeBundle:SomeEntity o ')
->getResult();
Effect that I receive in collection $objects is collection of SomeBundle:SomeEntity objects except for the one that I received to variable $object for which I receive Proxy object.
If I output $objects collection and for each element I want to print output that includes fields: name, field1, field2, I receive null for field2 for this object. In fact if I get this $object in any other controller launched with this one together, the field2 is also null on each reference to the object.
For example, if I want to display each object as:
name field1 field2
I get following array for $objects:
nameExample field1Example field2Example
nameExample field1Example field2Example
nameExample field1Example
nameExample field1Example field2Example
nameExample field1Example field2Example
where the third row is the $object.
If I get field2 in the first query it is also visible on getResult of the second one. But that makes me control all fields received for any Entity object in whole Request.
What could I made wrong?
How can I avoid that effect? I still want to work with objects not with multidimensional arrays (as for HYDRATE_ARRAY)
Is there a way to force doctrine to result always with entity objects not with proxies objects?
Thank you in advance.
This happens because Doctrine keeps an internal reference to each entity it returns. When you request an entity you've requested before, it will re-use the previous object. The reason for this is that having two different copies of the same entity would create conflicts if you try to manipulate both of them. For more details, see http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/unitofwork.html#how-doctrine-keeps-track-of-objects
The one solution is to detach the entity you got first (using either $em->detach($object) or $em->clear()) before executing the second query. Be aware, any changes you've made that have not been flushed yet will be gone.
Another option is to either refresh the entity using $em->refresh($object) (this will cause it to be fully loaded) or tell Doctrine it needs to refresh all entities for the second query:
$query = $this->getDoctrine()->getManager()->createQuery('SELECT PARTIAL o.{id,name,field1, field2} FROM SomeBundle:SomeEntity o ');
$query->setHint(Query::HINT_REFRESH, true);
$objects = $query->getResult();
This will make Doctrine refresh all the entities it finds for this second query.
Not sure what I did..
But now my Entity is returning "PersistentCollection" when I try to get the related atribute.
Until yesterday it was returning "ArrayCollection".
I cant use "foreach" in PersistentCollection, so I get errors..
No idea what I touched to make this.. What I have to check?
I think the solution is use Presistent Collection with methods of Collection.
For Example, you can get elements of Collection by such way:
$array = $presistentCollectionObject->getValues();
foreach ($array as $obj) {
dump($obj);
}
Note that if you dump PresistentCollection object directly, element ArrayCollection (which is contained inside) will be empty.
I feel like this shouldn't be to hard, but try as I might, I keep getting errors.
What I'm wanting to do, is to have a single "add" function that will handle the basic functionality of adding records to any / all tables. Basically, the post data will contain the table name, as well as the fields / values to be inserted. The controller itself, confirms the user has access to do these things, and then verifies the fields are valid, before creating a new instance of the entity, that's where things go haywire:
$entityName = 'Products';
$row = new $entityName(); //doesn't work
$row new Products(); //works
I haven't found a way or any examples of creating a new entity using the Entity Manager, or else that might work, because i've created functions using EM to do queries, updates, and deletes, but I just can't get this to work with the add functions.
1. Your problem is almost certainly namespacing (see below). Try this instead:
$entityName = 'My\Bundle\Entity\Products';
$row = new $entityName();
Should work. ;)
2. If you want to create new instances using an EntityManager, try this:
$entityName = 'My\Bundle\Entity\Products';
$row = $em->getClassMetadata($entityName)->newInstance();
...assuming $em is your EntityManager. :-)
3. To "prove" that your problem is namespacing, try this in a plain .php file that you run from the command line:
namespace Foo;
class Test {}
$class1 = 'Foo\Test';
$class2 = 'Test';
$x = new Test(); // Will work
$y = new $class1(); // Will work
$z = new $class2(); // Will trigger "Class 'Test' not found" fatal error
Two things:
Try with "Products" instead of 'Products'
I suppose that your entity Products has a namespace, it is required (even if you declared an use statement). So try with "My\Bundle\Entity\Products".
I am very new to Solr and I am probably missing something simple however, having followed Xavier Briand's presentation I have set up Symfony2, Solarium and Nelmio\SolariumBundle.
"nelmio/solarium-bundle": "2.0.*#dev",
"solarium/solarium": "3.0.*"
Having implemented a toSolrDocument method for my doctrine php object.
public function toSolrDocument(\Solarium_Document_ReadWrite $doc)
{
$doc->id = $this->getId();
$doc->description = $this->getTitle();
$doc->path = "path";
return $doc;
}
I am faced with the following error.
Catchable Fatal Error: Argument 1 passed to ::toSolrDocument() must be an instance of Solarium_Document_ReadWrite, instance of Solarium\QueryType\Update\Query\Document given, called in Controller.php
The controller calling this toSolrDocument method has the following function
public function indexItems(){
$client = $this->get('solarium.client');
// get an update query instance
$update = $client->createUpdate();
// create documents
$documents = array();
$em = $this->getDoctrine()->getManager();
$repo = $em->getRepository('<Bundle>:<Object>');
$items = $repo->findAll();
foreach ($items as $item) {
$documents[] = $item->toSolrDocument($update->createDocument());
}
// add the documents and a commit command to the update query
$update->addDocuments($documents);
$update->addCommit();
// this executes the query and returns the result
$result = $client->update($update);
}
Most of this method again comes directly from Xavier's presentation and it is clear to see that the method $update->createDocument() does not return the correct type. In fact it returns an instance of the my php object. Does anyone know where I am going wrong here? Another thing that might be of help is that even when I try to pass a Solarium Document directly I get an exception.
foreach ($items as $item) {
$rw_item = new \Solarium_Document_ReadWrite();
$documents[] = $item->toSolrDocument($rw_item);
}
The exception is
FatalErrorException: Error: Class 'Solarium_Document_ReadWrite' not found in
I can't seem to find this class in any of the bundles and I am wondering if my setup might be causing the issues. Any help would be very much appreciated.
One additional point to note is that when I am running the solr jar I see the query requests come in from my symfony2 page it is only this indexing action that I can not work out so the config may be alright and I am miss understanding the use of the bundle.
You just need to use the correct class for the argument.
use Solarium\QueryType\Select\Result\AbstractDocument;
...
public function toSolrDocument(AbstractDocument $doc)
{
You could also not type hint it:
public function toSolrDocument($doc)
{