Returning PersistentCollection not ArrayCollection - symfony

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.

Related

CakePHP3: Adding an association in a behavior

I'm having a table called settings, which contains typcial setting information, like isactive, activationdate,... which should be associated to a lot of other entities. Now I was wondering if I could put that in a SettingsBehavior, so that I just have to load the Behavior in all Table Objects I need it.
I thought about adding something like this in SettingsBehavior::beforeFind():
$event->getSubject()
->hasOne('Settings')
->setName('Settings')
->setForeignKey('parent_id')
->setConditions(['Settings.parenttype' => $event->getSubject()->getTable()]);
But the Query is already created. At least I'm able to add a setting entity to the entity using the SettingsBehavior.
In the Behaviors initialize() as far as I know I don't have a reference to the subject.
I then tried to do this in SettingsBehavior::beforeFind():
$query->leftJoin('Settings', [
$event->getSubject()->getAlias() . '.id = Settings.parent_id',
'Settings.parenttype' => 'users'
]);
But it also didn't add a setting to my found entity. Does anyone have tried something similiar, or has an idea how to do this? Maybe I'm even wrong trying to do something like this, through a behavior?
Thank you!
The table (subject as you called it) that a behavior is being attached to, is injected via the behaviors constructor, and stored in the _table property, which you can use in the initialize() method.
public function initialize(array $config)
{
// ...
$this->_table->hasOne('Settings', /* ... */);
}
You can then contain or join the association in the behaviors beforeFind() callback.
public function beforeFind(Event $event, Query $query, \ArrayObject $options)
{
// ...
$query->contain('Settings');
}

Symfony : Custom repository function returns a non-object result

Here is the content of my custom repository function for my entity Feed.
return $this->createQueryBuilder('f')
->select('f, COUNT(s)')
->leftJoin('f.subscriptions','s')
->groupBy('f')
->having('f.inCatalog = TRUE')
->orHaving('COUNT(s) > 0');
->getQuery()->getResult();
I want to get every feed with at least one subscription in my catalog, then browse it in a foreach loop but it returns this :
FatalErrorException: Error: Call to a member function getId() on a non-object in * line *
Any idea how to solve this problem ?
I saw you could do, for example, $feed[0]->getId() but I want an object, not an array.
Some topics are similar but I didn't find any good answer.
EDIT : Well, i think i found the answer to my own question...
To get what i want, i need to remove the COUNT() in the select. I don't want it and it is only needed in the HAVING.
This looks to be working :
return $this->createQueryBuilder('f')
->leftJoin('f.subscriptions','s')
->groupBy('f')
->having('f.inCatalog = TRUE')
->orHaving('COUNT(s) > 0');
->getQuery()->getResult();
Now the result returns an array of objects as i wanted.
Thanks to the people who answered.
You have to use at least a primary key in your select, f.id in this case I guess and group by this id
Try it with partial...
$qb->select('partial f.{id, subscriptions}, count(s.id)');
the results might be given back in an array, so you can try access it
{{ feed[0][0]->getId() }}
see my similar question:
How can I select count(field) and still get an object with createQueryBuilder

Return a value from entity to view file in symfony

I want to return a value from entity to view file. Below is my entity function
public function getVisitorName($id)
{
$repository = $this->getDoctrine()->getRepository('SystemVmsBundle:VisitorsDetails');
$product = $repository->findOneBy(array('id' =>$id));
$name=$product->getFirstname();
return $name;
}
This is the line in my view file which calls that function
{{ entity.visitorName(entity.visitorId) }}
Its not giving me any error. But only a blank page. How can i fix this?
This is my controller code
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('SystemVmsBundle:EntryDetails')->findAll();
return array(
'entities' => $entities,
);
}
I am trying to fetch the visitors name(from visitors table) corresponding to the visitor id(in entry table).How will i do it then?
you have two ways of doing it:
1) Map your SystemVmsBundle:EntryDetails entity, to SystemVmsBundle:VisitorsDetails as OntToOne by adding field details to your EntryDetails; , and then in twig template just call it via
{{ entity.details.name }}
2) instead of creating getVisitorName(), it is better to create twig function for this, with same functionality.
Your indexAction() is not returning a response object, it is just returning an array of entities. Controller actions should return a Response containing the html to be displayed (unless they are for e.g. ajax calls from javascript). If you are using twig templates you can use the controller render() method to create your response, something like this:
return $this->render('<YourBundle>:<YourViewsFolder>:<YourView>.html.twig', array(
'entities' => $entities,
));
When you've corrected that I suspect you'll get an error because $this->getDoctrine() won't work from an entity class. The code you have in the getVisitorName() method just shouldn't be in an entity class.
As #pomaxa has already suggested, I believe there should be a relationship between your EntryDetails and VisitorsDetails entities although I don't know enough about your data from the question to know what type of relationship it should be (OneToOne / ManyToOne). If your EntryDetails entity had a relationship to VisitorsDetails, the EntryDetails class would then contain a $visitorsDetails attribute and methods to get/set it. Then the line in your twig file would look like this:
{{ entity.visitorsDetails.firstName }}
There is a section on Entity Relationships / Associations in the Symfony Manual.
Also, I hope you don't mind me giving you a little advice:
Be careful when you copy and paste code as it appears you have done in getVisitorName(). You have kept the variable name '$product' although there are no products in your system. This sort of thing can cause bugs and make the code more difficult to maintain.
I recommend you avoid tacking 'Details' onto the end of entity names unless you genuinely have two separate and related entities such as Visitor + VisitorDetails and a good reason for doing so. I think the entities in your example are actually 'Visitor' and 'VistorEntry'.
Unless you are writing a re-usable component, I recommend you use specific variable names like '$visitorEntries' rather than '$entities' in your controller and twig.
In general, the more meaningful your variable names, the more readable, maintainable and bug-free your code is likely to be. Subsequently, it will also be much easier for people on SO to understand your code and give you help when you need it.

How to use setAttribute on a form collection in ZF2?

I haven't found any documentation for setting field attributes to for Zend Framework 2 form collection. I can set the value of a single input field like this:
$form->get('title')->setAttribute('value', $value);
What I can't figure out is how to set the values for a collection.
$form->get('sample_collection') returns a Zend\Form\Element\Collection Object
It seems like I need to go one layer deeper and select the specific field so that I can use the ->setAttribute on it.
Thank you in advance for your help in solving this.
I had some real trouble with this, the only way I could actually get access to a fieldset inside a collection was with the following. (If the collection has more then one fieldset you would have to add an if statement inside the foreach loop to get the fieldset you want.)
$array = array('keys'=>'values');
$collection = $form->get('name_of_collection');
foreach ($collection as $coll)
{
$fieldset = $coll;
}
$element = $fieldset->get('name_of_element');
$element->setValueOptions($array);
I expected the following to work, which does not. I am not sure if this is a bug in the Zend framework or if I am doing something wrong.
$collection = $form->get('name_of_collection');
$fieldset = $collection->get('name_of_fieldset');
$element = $fieldset->get('name_of_element');
If you just want to access a single element inside a fieldset NOT inside a collection. The following has worked fine for me.
$fieldset = $form->get('name_of_fieldset');
$element = $fieldset->get('name_of_element');
$element->setAttribute('id', 'name_of_element');
I hope this can be of help to someone.
Use form collection as an array:
$elements = $form->get('sample_collection');
foreach($elements as $element){
$element->setAttribute('value', $value);
}

How to remove all items in a magento product collection?

Seems doesn't works:
<?php
$collection = Mage::getModel('catalog/product')->getCollection();
foreach($collection->getItems() as $key => $_product){
//product
$collection->removeItemByKey($key);
}
?>
$collection is still populated
If you'd like to work with an empty collection, the best approach would be to load it with a filter that would always produce an empty set. Here's an example:
$collection = Mage::getModel('catalog/product')->getCollection()
->addFieldToFilter('entity_id', 0);
Because Magento product ids start at 1, this collection would remain empty, until you add items to it with the addItem() method.
clear() and removeItemByKey(), on the other hand, will only trigger a second run to the database to refetch the data you don't want in there.
You question doesn't make sense. Running the following code
$c = Mage::getModel('catalog/product')->getCollection();
foreach($c->getItems() as $key=>$item)
{
$c->removeItemByKey($key);
}
foreach($c->getItems() as $key=>$item)
{
var_dump($key);
}
var_dump( "Done" );
results in only the word "done" being output (Magento 1.6.1).
My guess it something about your installation of Magento is making the call to $c->getItems(); trigger a reload of the collection. So, you remove all the items, but then when you call your second getItems, the collection is refetched.
There's clear() method in Varien_Data_Collection class which clears the collection.
I'm not sure if the method exists in the time the question was asked, but it exists in Magento 1.7
There's also a possibility to remove all the items without "fake loading" (in opposite to Shay Acrich's answer):
class MyCollection extends SomeCollection {
// ...
public function setEmpty()
{
$this->clear();
$this->_totalRecords = 0;
$this->_setIsLoaded(true);
return $this;
}
// ...
}
Setting _totalRecords to 0 is required in order not to allow getSize() method to reload the collection.
Nevertheless, one needs to extend / modify a collection's code, because both the field _totalRecords and the method _setIsLoaded() are protected.
There should be noted, that if a particular collection ignores flags like _totalRecords and _isCollectionLoaded the above solution may not work as expected.
$collection->clear()
should do the work.

Resources