CakePHP - Change the "name" attribute of a form input - cakephp

I have a helper which generates a custom form input.
Helper (simplifed code)
public function customInput($field, array $options = array()) {
$defaultOptions = array(
'class' => 'custom-input',
'label' => false
);
$options = array_merge($defaultOptions, $options);
return $this->Form->input($field, $options);
}
Now how can I modify the name attribute of the input by prefixing it with another 'model'. For example, the input will by default have the following name attribute:
<input type="text" name="data[MyModel][field]" />
But I want it to be:
<input type="text" name="data[_custom][MyModel][field]" />
Mainly, what seems tricky is that I don't know how to get the model name that will be used by default. Also, I need something that works if the default model hierarchy is more complicated, like:
<input type="text" name="data[MyModel][AssociatedModel][field]" />
Would need to be modified to:
<input type="text" name="data[_custom][MyModel][AssociatedModel][field]" />

You want name
echo $this->Form->input('whatever', array('name' => 'data[_custom][MyModel][field]'));
There is nothing like data[_custom][MyModel][AssociatedModel][field] in cakes form helper. Your options as far as automation go is:
field // normal, use current model
Model.field // used with not default model / relations
Model.$i.field // User hasMany Post would be Post.$i.field

For the input helper, CakePHP uses $this->model() to get the name of the current model.
You can see it inside lib\Cake\view\FormHelper, or directly from the online API:
http://api20.cakephp.org/view_source/form-helper#line-942
$modelKey = $this->model();
Maybe that helps.

well you can do: $this->Form->input('_custom.MyModel.field'); to create an input in the format you require.
It becomes a case of passing the appropriate model name and associated model with it.
I don't know how you could do this automatically as obviously each relation is different/may have multiple associations.
So using your helper: echo $this->YourHelper->CustomInput('_custom.MyModel.MyAssociation.field', $options) might do the trick.

Related

Filtering parameters in CakePHP

In Rails, we can specify the allowed parameters to be used in the controller when saving data. So, with params being the submitted data, I can do this:
params.require(:person).permit(:name, :age)
Which will ensure that the :person key is present and will filter out anything that is not a person's :name or :age.
Is there any way in CakePHP to accomplish this?
EDIT: I know I can write PHP, I want to know if there's a Cake component / plugin that already does this.
Something in this PHP way:
// submited data
$this->request->data['Person'] = array(
'name' => 'Salines',
'age' => '41',
'job' => 'Web Developer'
);
// check if isset and filter out anything that is not a person's name or age
if(isset($this->request->data['Person']))
{
$permit = array('name' => '','age' => '');
$this->request->data['Person'] = array_intersect_key($this->request->data['Person'],$permit);
}
//and return $this->request->data like
array(
'Person' => array(
'name' => 'Salines',
'age' => '41'
)
);
I'm looking for a Cake-provided solution (if there is one)
Well, define "cake-provided", you mean by the framework itself? No, the core doesn't have this functionality but there are two plugins.
For Cake3: Plum Search
For Cake2 & 3: CakeDC Search
For Cake3 I would go for Plum-Search, it is written by the same person as the initial code of the other plugin but a complete rewrite and makes a better use of Cake3.
Next time you ask name your exact Cake version.
Both plugins implement the PRG pattern but don't explicitly allow or deny query parameters. They'll only grab the parameters you specified in your filter declaration and turn them into the request. Validate and save to exclude unwanted fields.
Make a url link like this
echo $this->Html->url(array('controller'=>'users','action'=>'hello','par1'=>23,'par2'=>'sud'));
In hello function in users controller
pr($this->params->named['par1']);
pr($this->params->named['par2']);

CakePHP controller name in behavior

I created relation Post hasMany Photos, Photos actsAs ImageBehavior.
How put to $data['Photo']['model'] = 'Post'? Automated?
I'm not sure what you are asking about but when you have a form, you can simply add to your $this->data['Photo']['model'] any value you want with hidden fields.
// photo/add.ctp:
$this->Form->create('Photo');
$this->Form->input('model', array('type' => 'hidden', 'value' =>'yourvalue'));
$this->Form->end('Submit');
Update
You can set this value after the form was submitted, so even if someone will replace the hidden field value you can just check it.
function add(){
if(!empty($this->data['Photo']['model']){
$this->data['Photo']['model'] = "yourvalue";
$this->Photo->save($this->data));
}
else
rest of the code...
}
rest of the code

cakephp new field not saving

How to you extend a cakePHP project so it can use a new field in the database?
I just given a CakePHP Project that I am trying to extend the model to include a new field. I The original Developer is no longer available, and I haven't worked with CakePHP previously. The problem is that all of the other fields are being saved correctly, but the new field is being saved as an empty string.
The database has been extended to include the new field:
class_time varchar(30)
I extended the original view to support the new field
<?=$form->input('release', array('type' => 'radio', 'legend' => false, 'div' => 'radio', 'options' => array('Agree' => 'Agree ', 'Disagree' => 'Disagree')))?>
<?=$form->input('class_time', array('type' => 'radio', 'legend' => false, 'div' => 'radio', 'options' => array('No preference' => 'No preference ', '6:00-8:30 P.M. ' => '6:00-8:30 P.M. ', '6:30-9:00 P.M.' => '6:30-9:00 P.M.')))?>
As near as I can tell, the page is rendering the HTML correctly
<div class="radio"><input type="hidden" name="data[Account][release]" id="AccountRelease_" value=""><input type="radio" name="data[Account][release]" id="AccountReleaseAgree" value="Agree"><label for="AccountReleaseAgree">Agree </label><input type="radio" name="data[Account][release]" id="AccountReleaseDisagree" value="Disagree"><label for="AccountReleaseDisagree">Disagree</label></div>
<div class="radio"><input type="hidden" name="data[Account][class_time]" id="AccountClassTime_" value=""><input type="radio" name="data[Account][class_time]" id="AccountClassTimeNoPreference" value="No preference"><label for="AccountClassTimeNoPreference">No preference </label><input type="radio" name="data[Account][class_time]" id="AccountClassTime6:00-8:30P.m." value="6:00-8:30 P.M. "><label for="AccountClassTime6:00-8:30P.m.">6:00-8:30 P.M. </label><input type="radio" name="data[Account][class_time]" id="AccountClassTime6:30-9:00P.m." value="6:30-9:00 P.M."><label for="AccountClassTime6:30-9:00P.m.">6:30-9:00 P.M.</label></div>
But when it saves, it is saving the selection for the "release" field (and the others), but not the class_time.
From what I can find in the cakePHP documentation, app/models/account.php is where I believe I would need to define the new field, but it only consists of the following:
<?php
class Account extends AppModel {
var $name = 'Account';
}
?>
Which makes me wonder how the original developer got the "release" to save, even though it doesn't appear to be defined.
Is there something that I am missing, or that still needs to be done?
Whenever you make any changes to your database, please make sure that your app/config/core.php file debug value is 2. Configure::write('debug', 2);
If it is 0 database changes will not be detected.
In CakePHP application, whenever you add a new field or modify the structure in database, you should delete all files inside YourApplication/app/tmp/cache/models folder.
Whenever you do any database change follow the following steps :
Clear files under \app\tmp\cache\models
If you are using any cache engines like memcache, restart the cache service.
Set the debug to 2 in core.php
Quite a bit later, but I was looking for a way to do this today in Cake 3.x. Easiest way, imo:
bin/cake orm_cache build
which will rebuild the cache w/ the current db structure.
Or to just clear w/o rebuild:
bin/cake orm_cache clear
http://book.cakephp.org/3.0/en/console-and-shells/orm-cache.html
Try to clear all models under cache directory.
app/tmp/cache/models
clear cache at /app/tmp/cache
if raising debug level to 2 or 3 is not working.
check if, on using debug($Model), shows your new field under schema attribute of model.
You can also delete cache file if your database changes are not working.
path of your application\app\tmp\cache\models
In cakephp 3 you should also check your entity file for that model, and make sure that the field is under the $_accesible property.
Example:
protected $_accessible = [
'name' => true,
'topic' => true,
'new_field' => true
];
You need to inform cakephp that you have new fields in your db. Why you need to do so is coz cakephp scans the db only once and generates the schemas. Once refers to first time it's run. You can find the schemas in app\tmp\cache\models.
So if you clear the files in the above folder cake will re generate the schema. Now there is a exception to it, if you are in development/debug mode cakephp scans it everytime.
Actually, any changes to database, anytime , you should change debug mode to 2 in app/config/core.php if it is zero. Otherwise it will take values from cache.

How to populate drop-down list with database values in CakePHP

I am very new to CakePHP. Could you please explain me the steps needed to populate a select drop-down with values from the database. Please also suggest me some links to the reference.
Simple, if it's a related model in your controller you pass 'list' into the find(); an cake will make an id => value array for you, and the form helper will know exactly what to do with it.
For example say you want to get the list of categories for a product model, this is in your contoller:
$categories = $this->Product->Categories->find('list');
$this->set(compact('categories'));
Then in your view using the form helper, simply create the select element how you normally would any input:
$form->input('category_id');
The form helper will automatically load the $categories variable we set with $this->set().
You make a find in the db and then set the variable via $this->set(yourvariable) in the controller.
In the view you use the "yourvariable" in the select tag
Fill select 1
Fill select 2
Fill select 3
There is a cakeish way to do it with very less effort
$this->set('arrMain',$this->Post->find('list',
array(
'fields'=>array('id','title')
)));
Will give output as ==>
<select id="UserAge" name="data[User][Age]">
<option value="1">The title</option>
<option value="2">A title once again</option>
<option value="3">Title strikes back</option>
in the controller you do:
$this->loadModel('MyModel'); //if it's not already loaded
$options = $this->MyModel->find('all'); //or whatever conditions you want
$this->set('options',$options);
and in the view
<select...>
<?php foreach ($options as $option): ?>
<option value="<?php echo $option['MyModel']['id']; ?>"><?php echo $option['MyModel']['field']; ?></option>
</select>
Example
in your controller Class
$categories = $this->Articles->find('list')->select(['id', 'title'])->toArray();
$this->set(compact('categories')); // pass result dataset to the view
In Your view file
<?php echo $this->Form->select('articles_categories_id', $categories); ?>
Reading Source
http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html

How to pass data in url using cakephp?

I wanted to now if there is a way to pass a simple string inside url and cakephp some how put it inside one of the inputs of my form without any code writing on view side?
I tried calling this->set("bla","bla"); the field name is bla
but nothing changed in view
As I understood the question you want to have something like this:
in the url you have something like:
http://yourserver.com/controller/action?search=string
and you want to put this "string" in the search field, right?
Then let's imagine that your field's name is data[search_field]. (I am skipping the model, because for my example it's not needed, but it's possible the name to be data[Model][search_field]).
Then in your controller's action you have to do following:
$this->data['search_string'] = $this->params['url']['search'];
You can pass values in the url by using html helper. Try:
echo $this->Html->link('View Some Page', array(
'controller' => 'yourController',
'action' => 'view',
1, // id
'?' => array('yourField' => 'valueToPass'))
);

Resources