Getting values of a POST multi-dimensional array with doctrine - symfony

I have a Symfony3 CRM that implements a form to create an invoice. In this form there is a list of different costs, such as labour, service and materials. I have coded this so it's in a multidimensional array since the user can create any number of fields with whatever they want.
An example of the post array:
[costings] => Array
(
[labour] => 80.30
[materials] => 75.00
[service] => 43.50
....
)
I want to use Doctrine to get the data. To retrieve the costings array, I use this:
$request->request->get('costings');
But I do not know how to get the values within that array. I tried:
$costings->get('labour');
But I get a warning saying I'm trying to call get() on an array. Is there a way to do this or do I need to revert back to just using $_POST?

Simply use this, since you POST costings as normal array.
$costings = $request->request->get('costings');
$labourCostings = $costings['labour'];

Did you try:
$labour = $request->request->get('costings')['labour'];
?
If it doesn't work, try to dump the result of $request->request->get('costings')

Related

Symfony 2.7 findOneBy() Function Finds the Wrong Entity

I've got a controller action that's supposed to be looking for semi-duplicate entries in a collection, and removing them from that Entity's list. New ones should not have an ID yet, and existing ones do, so I'm running findOneBy() with an array of parameters to match on (leaving out ID).
I am baffled and deeply troubled by the error I am getting, where it finds the wrong entity! I've got some relevant code below, I hope this is just a dream or a silly mistake, I can't reproduce the output on my own windows development environment, but my co-worker was testing on his mac, and was getting errors, so I went on his machine and did some quick echoing to see what was going on. See the code and the result below.
CODE
foreach($entity->getTechnicians() as $tech) {
//find new addtions, see if they exist
if (!$tech->getId()) {
echo "Technician " . $tech->getFirstName() . " has no ID, trying to find one that does<br/>";
$found = $em->getRepository('TechnicianBundle:Technician')->findOneBy(array(
'firstName' => $tech->getFirstName(),
'lastName' => $tech->getLastName(),
'email' => $tech->getEmail(),
'residentEngineer' => $tech->getResidentEngineer(),
'officeNumber' => $tech->getOfficeNumber()
));
//if one with an ID already exists
if ($found) {
echo "found technician " . $found->getFirstName() . " that already has id " . $found->getId() . "<br/>";
...
OUTPUT
Technician Four has no ID, trying to find one that does
found technician khjvuov that already has id 7
Probably it's not a findOneBy() issue.
If without add/remove calls it works, it may be caused by modified current pointer of ArrayCollection so when $tech->getFirstName() is called it actually points to another entry.
You may try to iterate your collection like this:
$iterator = $entity->getTechnicians()->getIterator();
while ($iterator->valid()) {
$tech = $iterator->current();
... $entity->addTechnician()/$entity->removeTechnician()
$iterator->next();
}
It will create new ArrayIterator object, so you can modify underlying object preserving ArrayCollection's internal pointer.
This may be obsolete if you are running PHP7 (reference - Note box)
Ultimately, the findOneBy() method uses the load() method of the Doctrine ORM.
In the doc, the parameter $criteria is described as such :
#param array $criteria The criteria by which to load the entity.
You should probably dig deeper into Doctrine API to make sure, but there is a big chance that in the array you are passing as an argument, only the first key => value pair is taken into account (in your example, 'firstName' => $tech->getFirstName()).
If this is the case, you'll probably need to add your own custom method in your entity repository, one that would allow you to query your database with more advanced statements (using OR/AND or LIKE() in SQL for instance).

Symfony 2 custom DQL request inside an array field

I'm trying to make a custom request in my repository with a WHERE clause inside an array field. I tried something like that, not working, but can better show my problem :
$qb ->andWhere( "p.addresses[:index] = :address" )
->setParameter( "index" , $p_idLang )
->setParameter( "address" , $p_address );
Extracted from the documentation about array type:
Maps and converts array data based on PHP serialization. If you need
to store an exact representation of your array data, you should
consider using this type as it uses serialization to represent an
exact copy of your array as string in the database. Values retrieved
from the database are always converted to PHP’s array type using
deserialization or null if no data is present.
Your query doesn't make sense. You have a few options though:
Retrieve p.adresses and check using php if p.adresses[$index] = $address
Try something much less reliable but that could work:
$val_length = strlen($p_address);
$qb ->andWhere( "p.addresses LIKE :indexAddress" )
->setParameter( "indexAddress" , "%i:$p_idLang;s:$val_length:$p_address%" );
Create a new entity and a relation oneToMany between this entity and the new one.
I'd definetely try option 3. Option 1 isn't an option if the array is big or will become big in the future. I wouldn't go for option 2, but as an experiment could be worth trying.

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 to create a unique form using multiple entities fields in symfony2

I want to create a form using some fields from multiple entities. I have all the distinct entites needed already created and i am not using form classes. I need to know how to do to render a form and handle its data so i can save them to the correct tables in my database.
Here is a part of my controller in charge of doing that
public function createPublicSpaceAction() {
//My entities
$Room = new Room();
$GuestList = new GuestList();
$Guest = new Guest();
//I need to know what to do from here
return $this -> render('AcmeUserBundle:Default:Forms/createPublicSpace.html.twig', array());
}
I kept trying to find a solution and i came up with the idea that one form needs one entity. So maybe the solution would be to merge those entities in one so i can build the form easily. I would then have to persist data to corresponding tables. But i can't think of how to merge entities.
I figured out a temporary solution. For those who want to know, I manually created an entity that looks like a merge of all the entity I need. This new entity has no link with Doctrine therefore it cannot create a table. Its goal is simply to allow me to build up a form and be able to manipulate data through that form. I then assign all data submitted to corresponding entities fields and persist them to the database.
Once again i know this is not the best solution. But for some reasons I won't tell, it is for me at this moment. I hope this can help some that are in the same situation than me and do not hesitate to post links that could help or better ways to do that.
It is highly recommended to use form classes http://symfony.com/doc/current/book/forms.html#creating-form-classes
They are designed to save time and make a lot of things just easier.
However to answer your question consider the following. Your action needs to handel a post request. So catch the request object with the post data:
use Symfony\Component\HttpFoundation\Request;
public function createPublicSpaceAction(Request $request)
Then get a form builder intance and create the form:
$builder = $this->createFormBuilder();
$builder->add('floor', 'text', array(
'label' => 'Room floor',
'data' => $room->getFloor()
));
add as much form fields as you need. There are several built-in field types: http://symfony.com/doc/current/book/forms.html#built-in-field-types
Create the form:
$form = $builder->getForm();
Pass the form to your template:
return $this -> render('AcmeUserBundle:Default:Forms/
createPublicSpace.html.twig', array(
'roomForm' = $form
));
To get posted data within your action:
if ('POST' == $request->getMethod()) {
$data = $request->request->get("form");
}
And in your template you can render the form by yourself or let twig do the job:
{{ form_widget(form.floor)}}
So this are the most importend things to mention. However you should go through http://symfony.com/doc/current/book/forms.html They actually tell you everything I wrote down.
Good luck ;)

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