How do you work with sub forms in Laravel 4 - php

I'm trying to find the way laravel 4 works with array data in requests but can't find any example, tutorials, documentation about it on the net.
Example:
<select name="productDetails[0][service]">...</select>
<select name="productDetails[0][product]">...</select>
<select name="productDetails[0][action]">...</select>
<select name="productDetails[1][service]">...</select>
<select name="productDetails[1][product]">...</select>
<select name="productDetails[1][action]">...</select>
Ends up being:
$_GET['productDetails'][0]['service']
$_GET['productDetails'][0]['product']
$_GET['productDetails'][0]['action']
$_GET['productDetails'][1]['service']
$_GET['productDetails'][1]['product']
$_GET['productDetails'][1]['action']
Now if i want to make my form work correctly i have the read this data, but i can't assume that productDetails is an array and features 0. I want to use the facilities provided by Laravel/Symfony's HTTP Foundation components.
I tried without avail:
Request::get('productDetails.0.service', null); //Doesn't work
Request::get('productDetails[0][service]', null); //Doesn't work
Request::get('productDetails.1.service', null); //Doesn't work
Request::get('productDetails[1][service]', null); //Doesn't work
I thought these versions would work because you can access session, config and probably many other data sources like this. Just stumped that this doesn't work... On the other hand, this following snippet works, but it's ugly cause you can't assume productDetails is an array at all times, you also can't assume 0 index exists nor "service" index too...
Request::get('productDetails', array())[0]['service']; //Works but ugly
Request::get('productDetails', array())[1]['service']; //Works but ugly
So what is the right way to accomplish this?
Edit #1
Added symfony to the tags, and i realize now that the Request object from Laravel really is an HTTPFoundation from symfony, so how do these guys work with all this? Am i the only one? I'm sure it's just a matter of naming conventions, i might not be using the right terms to search my documentation

Ahhhhh finaly found it:
Request::query('productDetails[0]', array()); //array('service' => 2, 'product' => null, 'action' => null);
Request::query('productDetails[1]', array()); //array('service' => 3, 'product' => null, 'action' => null);
Request::query('productDetails[0][service]', array()); //2
Request::query('productDetails[1][service]', array()); //3
Had to dig a little in the Request class and Symfony HTTPFoundation but was able to find examples and codes down there that explained how it worked.
Hope this helps others...

Any reason not to switch them to be separate inputs?
<select name="productDetailService">...</select>
<select name="productDetailsProduct">...</select>
<select name="productDetailsAction">...</select>
As I'm sure you realize, that would mean processing each one in separately in your form processing code.
However, if you aren't trying to make a form where you need to add new productDetails fields ad-hoc, I don't see a reason to make the code more confusing by using arrays in that way - processing each one separately or treating them as separate fields (vs an aggregate within an array) might be the better way to go.

Related

Add new 'has many' entity without overriding existing ones

I'm trying to accomplish a very simple task using Cakephp and after a couple of days reading and trying I can't find the solution. I'll try to explain it as better as I can:
I have a simple 'has many' relationship between two entities ('Clients' and 'Notes'). A client has many notes.
I have the 'Edit' page for the client and I would like to have in that page this two functionalities:
Read/View all the existing notes (readonly)
Add new note
So, following the documentation and several examples, in my edit form I've written the following code to generate the new note input field:
<?= $this->Form->control( 'client_notes.0.text' ); ?>
This is working just fine if the client has no notes of course. But if the client has any note this field gets populated with the first note so it gets overwritten on the save action.
I've also tried a different approach with no luck either:
I've tried to add a different input field such as
<?= $this->Form->control( 'new_note' ); ?>
and then tried to create a new 'Note' entity on the ClientController but this is where I get most confused. Should I modify the requestData passed to the edit method? How is the best way to do this? I've read that modifying the requestData is no longer doable/advised in cakephp.
Last thing I've tried so far is doing that in the 'beforeMarshal' as I've seen out there but it seems I can't get it right, this is my code:
public function beforeMarshal(Event $event, ArrayObject $data, ArrayObject $options)
{
if (isset($data['new_note'])) {
$text = $data['new_note'];
$data['client_notes'] = [
['text' => $text ]
];
}
}
I'll appreciate any help or guidance. Not looking for the magical code to paste in my project but for learning how to do it as I may have to do similar things in my current project. Thanks in advance!

Zend Framework passing a variable to all views from a controller to anything outside of $this->layout->content()

Ok, the subject makes no sense so Ill try to better describe it here.
Zend Frame work in use here. And I have run into a problem passing variables to my views, well the views included into the "top.phtml" that make up the template. What I am trying to do is implement a breadcrumb concept. The bread crumb file is included into the top.phtml before the content view file. So the breadcrumb variable isn't defined as far as the breadcrumb file is concerned.
I can print_r my array of settings for the breadcrumbs within the controllers view, no problem so it is working I know that much, just anything above that view in particular in the order of things can't get the variable. So I guess what I am looking to have answered is is there a means off passing a variable to the overall scheme of things similar in concept to
$this->view->variable_name = blah;
where something as high as the top.phtml can pick it up for use?
You may be looking for Placeholders.
Example:
Setting a placeholder value from a controller:
$this->view->placeholder('some_placeholder_name')->set('blah');
Setting a placeholder value from a view
$this->placeholder('some_placeholder_name')->set('blah');
Retrieving the placeholder value in a view script or layout:
$value = $this->placeholder('some_placeholder_name');
Placeholder content is rendered towards the end of your application execution so the value set in your controller should be available in your top level top.phtml view script.
I think this will work:
$this->layout()->breadcrumbs = ...
And then print $this->layout()->breadcrumbs in your top.phtml.
Zend Layout
After sending hours trying to get placeholder() to work with partialLoop(), I finally gave up and hacked a fix to pass vars to a partial:
$vars = (array) $this->getVars();
foreach ($this->rows as $row) {
$partialVars = array(
'row' => $row,
'vars' => $vars,
);
echo $this->partial('row.phtml', $partialVars);
}
ugly, but it worked.
+1 for everyone for giving me a clue, however none of the above worked well in my favor. However between them all, they lead me towards finding my answer which is
Zend_Registry
In my Controller I built my array and passed it to Zend_Registry like
$breadArray = array(
array("icon"=>"i_robot", "href"=>"systems/"),
array("href"=>"metrics","text"=>"Metrics")
);
Zend_Registry::set('breaded_crumbs', $breadArray);
Then in my breadcrumb.phtml which is loaded before the content and view I used
print_r(Zend_Registry::get('breaded_crumbs'));
to see if it was working, and it gave me the array's so I for anyone in the future looking to extend a variable outside of the view itself, the registry seems to be the way to go. I tried placeholder and layout, both gave me errors about not being something or another, and when I got them to work in part I wasn't getting what I was expecting.

Zend_Form_Element_Select default value

In my form, I want to set the selected (default) value for a select element. However, using setDefaults is not working for me.
Here is my code:
$gender = new Zend_Form_Element_Select('sltGender');
$gender->setMultiOptions(array(
-1 => 'Gender',
0 => 'Female',
1 => 'Male'
))
->addValidator(new Zend_Validate_Int(), false)
->addValidator(new Zend_Validate_GreaterThan(-1), false);
$this->setDefaults(array(
'sltGender' => 0
));
$this->addElement($gender);
My controller is simply assigning the form to a view variable which just displays the form.
It works by using $gender->setValue(0), but it would be easier to set them all at once with an array of default values. Am I misunderstanding something here?
Also, where is the Zend Framework documentation for classes and methods? I am looking for something similar to the Java documentation. The best I could find is this one, but I don't like it - especially because every time I try to search, it crashes.
Have you tried:
$this->addElement($gender);
$this->setDefaults(array(
'sltGender' => 0
));
Also, take a look at http://framework.zend.com/issues/browse/ZF-12021 .
As you can see, the above issue is similar to the issue you're describing. It seems Zend is very particular about the order you create objects and assign settings.
I'm afraid you're going to have to do things in the order Zend wants you to do them (which doesn't seem well documented, but is only discovered thru trial and error), or hack their library to make it do what you want it to do.

Is it possible to define more than one post-validator in Symfony?

I need to perform several post-validations in a Symfony form. First time I came across this issue I wrote this:
$this->validatorSchema->setPostValidator(
new sfValidatorCallback(array(
'callback' => array($this, 'checkStatusHasMethod'))
));
since I only wanted to check a certain situation.
But as the application has grown, I need now to perform additional checks. I would like to keep every validation isolated in different methods, instead of having a big checkX method where everything is kept together.
Is it possible to associate a sfPostValidator with more than one method or create several sfPostValidator instances in validatorSchema?
Thanks!
Try mergePostValidator() (or similar, can't remember the exact method name)
As far as I remember, there's a validator called sfValidatorAnd() that allows you to do that.
Edit : you can do that :
new sfValidatorAnd(
array(
new sfValidatorString(),
new sfValidatorRegex(),
)
);

simple cakephp problem

I know this is a really simple thing that I really should know but I'm trying to learn cakephp without having done much php before. I've been told thats a stupid idea, but I'm doing it for fun and so I'm doing it.
I want to pass an array from one controller action to another controllers action and then pass it to the view. I have:
sponges_controller.php
$info = $this->data;
$this->redirect(array('controller'=>'baths', 'action'=>'dashboard', $info));
baths_controller.php
function dashboard($info) {
$this->set('info', $info);
}
and then
<?php echo debug($info); ?>
in the view for dashboard.
I've tried various ways but can't make it work. All it does is print out Array()
Plz help me! :) Julia
You can't pass data that way from one controller to the other as far as I know, at most you can concat a string to the action, like an ID for view or editing.
If you want to pass the info you could try setting it in the SESSION variable in the following way:
$this->Session->write('Info', $info);
And in your other controller you can check for it:
$this->Session->read('Info');
It looks like cake will not let you pass an array into a controller action. I set up a simple example and I got an 'array to string conversion error'. Is there a specific reason why you aren't just posting the data to baths/dashboard? I can think of a workaround for your problem, but it is quite messy.
8vius's solution above will definitely work.
Here is another way, but using sessions is probably a lot better
$str = http_build_query($info);
$this->redirect('/baths/dashboard?'.$str);
So then in your baths/dashboard action, you will have access to your data using the php $_GET array.
So if you originally had this->data['name'] you can access it with $_GET['name']
I'm not sure about the passing data in different controllers but within the same controller we can do it just like a function call by writing something like this.
$this->function_name($info);
This will perfectly work as intended. I've not tried this type of data passing in different controllers function.

Categories