What does getiterator() method do? - symfony

I don't understand the getIterator() methode
Here an exemple where I saw it lately:
(in the following code $list_articles is the result of a query which return a list of articles, with their authors, contents, dates and their categorieS) (one author, content and date for each article, but many categories for each article)
$lastArticle = current($list_articles->getIterator())
return $this->render('XXX.html.twig',array(
'articles' => $list_articles,
'Date' => $lastArticle=>getDate()
));

The combination of current() and getIterator() will return the element pointed internally from a (let's call it that way) cursor of an array
Specifically getIterator() returns an iterator that could helps you if you don't want to "create" it yourself
ArrayObject class implements IteratorAggregate that provide this functionality

Related

SonataAdminBundle Exporter issue with many to many

currently I'm using sonata admin bundle to export a "order" data, how can I export the data with manytomany relationship? I saw a post, it helps a bit, but I still not sure how to get the data in many to many relationship.
Here is my code:
public function getExportFields() {
return [
$this->getTranslator()->trans('Order Number') => 'id',
$this->getTranslator()->trans('First Name') => 'customer.First_name',
$this->getTranslator()->trans('Last Name') => 'customer.Last_name',
...]
Here is fine, but when I try to get 'OrderToProduct' or 'product.name' it failed or only output empty string. I spent to much time on this already, hope someone can give a clue. Thank you.
Well, you can't use product.name, because product is a collection.
Export action iterates through objects and get properties with path defined and tries to stringify them.
What you need to do is a workaround - define some method in Order class - i.e. getProductsAsString(), make it return string you need, and then add
$this->getTranslator()->trans('Products') => 'productsAsString'
But still - it will put whole string in single cell of xls, csv, xml you are trying to export.

How does one have to call the function in this example for JMSPaymentCoreBundle?

How would detailsAction() have to be called in the example provided in the documentation for JMSPaymentCoreBundle?
It makes use of an order object, which in the function definition is passed as an argument.
public function detailsAction(Order $order)
{
$form = $this->getFormFactory()->create('jms_choose_payment_method', null, array(
'amount' => $order->getAmount(),
[...]
Am I right in assuming that the function can only work when passing an order object at the time it is being called? Are there any other ways of achieving this other than doing something like
return $this->forward('MyBundle:Payment:details', array(
'order' => $order,
));
Yes, you are right. The detailsAction requires an Order object in order to work. So, you will have to have one created by the time you get to this action, otherwise it will throw a 404 error (because the route without an order does not exists).
You should create your own Order entity, which then you can persist to the database (once it's started, that is, the submitted form is correct).
Good luck.

Nested models not created as batman objects

Given the following models with one-to-many relationship:
class App.Post extends Batman.Model
#hasMany 'comments'
class App.Comment extends Batman.Model
#belongsTo 'post'
My comments are included in the JSON of the post from the backend. Since i'm having #encode 'comments' the comments are added to the post. However, they are added in an array of simple JS objects instead of an associationset of Batman objects.
Should I really decode them explicitly like this
#encode 'comments',
decode: (value, key, incomingJSON, outgoingAttributes, record) ->
outgoingAttributes = App.Comment.createMultipleFromJSON(incomingJSON.comments)
or am I doing something stupid here?
#hasMany "comments" should automatically set up an encoder to load comments from JSON.
Did you mention that you added your own encoder, like
#encode 'comments'
?
If so, that is overriding the one created by #hasMany 'comments'. Try removing the #encode 'comments'. Does that help?

One to one relationship in Silverstripe

I'll try and put this as simply as possible but basically what I am trying to achieve is this.
There are two page types with a one to one relationship, car and owner. I want to be able te be able to select an owner through a dropdown on the car page. If an owner is already linked to another car I don't want it to appear in the dropdown.
I know that I'll need an if statement but I I'm finding it hard to puzzle out how it should go. I followed this tutorial to create the dropdown and it worked quite well.
Thanks in advance.
You can modify the function that gives you the dropdown values. Your DataObject::get() call
can have a filter for the second argument. Simply select all owners that have a CarID of 0.
So, from the tutorial you provided, you can use this modified code:
new DropdownField(
'OwnerID',
'Please choose an owner',
Dataobject::get("Owner","CarID='0'")->map("ID", "Title", "Please Select")
);
2 things to note:
This assumes your DataObjects are called Car and Owner (change as necessary, but keep the ID at the end of the name as it is written above)
This may not work depending how you set up the relationships with the $has_one assignments on your DataObjects. If there is no CarID field on the Owner table, then this code won't help you (you may have it set up vice-versa). In that case, you'll have to create a function that loops through all cars, and then removes the DataObjects from that DataObjectSet that have an OwnerID of 0. Add a comment if this isn't making sense.
Benjamin Smith' answer is perfectly valid for the dropdown you were asking for, just wanted to point to another approach: instead of taking care of the one-to-one relation yourself, there's the 'HasOneComplexTableField' handling this for you.
use the following code for your Car class:
class Car extends Page {
public static $has_one = array(
'Owner' => 'Owner'
);
function getCMSFields() {
$fields = parent::getCMSFields();
$tablefield = new HasOneComplexTableField(
$this,
'Owner',
'Owner',
array(
'Title' => 'Title'
)
);
$tablefield->setParentClass('Car');
$tablefield->setOneToOne();
$tablefield->setPermissions(array());
$fields->addFieldToTab('Root.Content.Owner', $tablefield);
return $fields;
}
}
note the 'setOneToOne()' call, telling the tablefield to only let you select Owners which aren't already selected on another car.
you'll find more information on this in the silverstripe tutorial: http://doc.silverstripe.org/framework/en/tutorials/5-dataobject-relationship-management

How to write Unit Test case for Zend Db Table Row

I am trying to write test case for my Row classes and I don't really what is the proper way to do that.
I've seen many example use model & table, for example http://techportal.inviqa.com/2010/12/07/unit-testing-databases-with-zend-framework/.
The case doesn't use Row at all and the model is all about getters and setters. I don't want rewrite such things as the Zend_Db_Table_Row can do it automatically.
My row classes are extended from Zend_Db_Table_Row, I don't think there is necessary to write test cases like getters & setters.
And most my row classes are like following
class App_Table_Row_User extends Zend_Db_Table_Row_Abstract {
}
Then, in order to get a better test case coverage, what kind of test case I should write for a class like above?
I presume you need to populate object's attributes (table's column name => values) and run tests for your custom methods.
Zend_Db_Table_Row_Abstract constructor has one parameter - associative array with following keys:
table
data
stored
readOnly
To build useful for testing object you should use at least the "data" entries. It is associative array too. The "data" array has column names as keys and row data as values. So the testing object setUp may look as follows:
$this->object = new App_Table_Row_User(
array(
'data' => array(
'username' => 'Jon Doe',
'password' => 'qwerty',
'email' => 'j.doe#example.com'
)
)
);
You can pass NULL as values in the "data" array entries if you need something similar to the fetchNew return object.
If you are using "save" or any method that requires the table model, I will suggest using mock/stub object and passing it as the "table" parameter in the constructor. You can control any Db related operation that way.
Hope that helps :)

Resources