This is my add.tcp
...
<?php
echo $this->Form->create('Group');
echo $this->Form->input('group_id', array('label' => 'ID'));
echo $this->Form->input('group_desc', array('label' => 'Group Description'));
echo $this->Form->end('Save');
?>
Table name: groups
Table fields: group_id, group_desc
PK: group_id
This is my controller
...
class GroupsController extends AppController {
public $helper = array('Html', 'Form', 'Session');
public $components = array('Session');
public function add() {
if ($this->request->is('post')) {
if ($this->Group->save($this->request->data)) {
$this->session.setFlash('');
$this->redirect(array('action' => 'index'));
}
}
}
}
When I display this view on the browser, there was nothing for the field group_id but there was for the group_desc, the HTML source for the look like this
...
<form action="/cakephp/index.php/groups/add" id="GroupAddForm" method="post" accept-charset="utf-8" name="GroupAddForm">
<div style="display:none;">
<input type="hidden" name="_method" value="POST">
</div><input type="hidden" name="data[Group][group_id]" id="GroupGroupId">
<div class="input text">
<label for="GroupGroupDesc">Group Description</label><input name="data[Group][group_desc]" maxlength="15" type="text" id="GroupGroupDesc">
</div>
<div class="submit">
<input type="submit" value="บันทึก">
</div>
</form>
Why it was hidden?
CakePHP automagically determines that you do not want a user to manually enter an ID, as such hides it for you.
If you would like to force ID field to be shown, set the type to text:
echo $this->Form->input('group_id', array('type' => 'text', 'label' => 'ID'));
Because primary key inputs are hidden by default.
CakePHP creates the primary key for you on add as auto increment INT or uuid CHAR
Manually creating your primary keys is not recommended.
you can change the hidden type to text:
echo $this->Form->input('group_id', array('label' => 'ID', 'type' => 'text'));
As per your database structure I want to suggest something:
Your group table has group_id as primary key
make it auto_increment from database and there is no need to put that id manually on add form, it will be saved automatically. Form fields generate as per model structure.
Related
I've read CakePHP multiple checkbox array HTML the right way but getting strange results. I have a list of tags (from a Model called Tag). I want to loop through these and output checkboxes for them in a View.
So I have obtained the Tag data in my Controller with:
$tags = $this->Tag->find('list', ['order' => ['name' => 'ASC']]);
$this->set('tags',$tags);
When I loop through it in my View I am trying to output the checkboxes in between Bootstrap markup:
<?php echo $this->Form->create('GroupTag'); ?>
<?php foreach ($tags as $tag_id => $tag): ?>
<div class="checkbox">
<label>
<?php echo $this->Form->checkbox('tag_id[]', array( 'value'=> $tag_id)); ?>
<?php echo $tag; ?>
</label>
</div>
<?php endforeach; ?>
I copied the syntax for tag_id[] from the post I linked to.
But when I inspect the markup it's producing the following as the name attribute for each <input type="checkbox">:
data[GroupTag][tag_id[]]
Should this not be
data[GroupTag][tag_id][]
?
The idea is that I have multiple checkboxes with a name attribute tag_id[] and then in the Controller I can loop through what has been checked.
Please can someone advise on this as I can't get it working and have looked into examples provided on here/docs.
Try this
$this->Form->checkbox('tag_id.', array( 'value'=> $tag_id))
You can also do this:
$this->Form->input('GroupTag.tag_id', [
'type' => 'select',
'multiple' => 'checkbox',
'options' => $tag_id
]);
FormHelper::select(string $fieldName, array $options, array $attributes)
Example:
$options = array(
'Value 1' => 'Label 1',
'Value 2' => 'Label 2'
);
echo $this->Form->select('Model.field', $options, array(
'multiple' => 'checkbox'
));
Output:
<div class="input select">
<label for="ModelField">Field</label>
<input name="data[Model][field]" value="" id="ModelField"
type="hidden">
<div class="checkbox">
<input name="data[Model][field][]" value="Value 1"
id="ModelField1" type="checkbox">
<label for="ModelField1">Label 1</label>
</div>
<div class="checkbox">
<input name="data[Model][field][]" value="Value 2"
id="ModelField2" type="checkbox">
<label for="ModelField2">Label 2</label>
</div>
</div>
I have a CakePHP Add Photo View that is using optgroups so that the HABTM related Tag model's data is shown in grouped fashion in the view. In the Photo controller I send the related Tag model data as follows to get the optgroups grouping of Tags by Tag Category:
//fields shown to create optgroups eg group tags by category
$this->set('tags', $this->Photo->Tag->find('list', array(
'fields' => array('Tag.id', 'Tag.tagname', 'Tag.category'),
'conditions' => array(
'Tag.account_id' => $this->Session->read('Auth.User.account_id')))));
}
The view shows the Tags nicely grouped by Category. So that part works perfectly.
However, after adding a new Photo and selecting one or more Tags to assign to it, it does save the Photo properly but not the assigned Tags.
I believe that CakePHP saveAll is expecting a data array as would be delivered without the optgroup Category > Tag hierarcy, and is therefore not saving Tag data when new Photo is added and Tags are assigned to the Photo.
What do I need to do to give it the proper array to save the related Tags? Will it be in the controller after Create() where I 'remove' the Category grouping?
A bit of background on this from CakePHP http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html
"If you would like to generate a select with optgroups, just pass data in hierarchical format. This works on multiple checkboxes and radio buttons too, but instead of optgroups wraps elements in fieldsets:"
$options = array(
'Group 1' => array(
'Value 1' => 'Label 1',
'Value 2' => 'Label 2'
),
'Group 2' => array(
'Value 3' => 'Label 3'
)
);
echo $this->Form->select('field', $options);
Output:
<select name="data[User][field]" id="UserField">
<optgroup label="Group 1">
<option value="Value 1">Label 1</option>
<option value="Value 2">Label 2</option>
</optgroup>
<optgroup label="Group 2">
<option value="Value 3">Label 3</option>
</optgroup>
</select>
Ok so this problem had nothing to do with the array structure.
It turns out I had 'Photo.Tag' instead of just 'Tag' in the Add Photo View. Here is the old Add Photo View code that didn't work:
<div class="photos form">
<p><?php echo $this->element('admin_nav'); ?></p>
<?php echo $this->Form->create('Photo'); ?>
<fieldset>
<legend><?php echo __('Add Photo'); ?></legend>
<?php
echo $this->Form->input('account_id', array('type'=>'hidden'));
//echo $this->Form->input('filename', array('type'=>'hidden'));
echo $this->Form->input('filename', array('type' => 'file', 'label' => 'Upload photo'));
echo $this->Form->input('desc');
echo $this->Form->input('Photo.Tag' , array('label'=>'Tags', 'multiple'=>'checkbox'));
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>
Here is the new Add Photo View code which now saves the new photo with the tags selected:
<div class="photos form">
<p><?php echo $this->element('admin_nav'); ?></p>
<?php echo $this->Form->create('Photo'); ?>
<fieldset>
<legend><?php echo __('Add Photo'); ?></legend>
<?php
echo $this->Form->input('account_id', array('type'=>'hidden'));
//echo $this->Form->input('filename', array('type'=>'hidden'));
echo $this->Form->input('filename', array('type' => 'file', 'label' => 'Upload photo'));
echo $this->Form->input('desc');
echo $this->Form->input('Tag' , array('label'=>'Tags', 'multiple'=>'checkbox'));
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>
While the Cakephp documentation on Saving Data makes references to how the array should be formatted, this appears to refer to all of the other relationships excluding HABTM. HABTM relationships can be saved in one action with the save on the parent model, in this case the Photo model eg:
$this->Photo->save($this->request->data)
will save the new Photo being added, plus any of the selected Tags, and they will be saved in the join table photostags.
What is a bit unusual, is that $this->Photo->save($this->request->data) appears to work same as $this->Photo->saveAll($this->request->data).
I have a CakePHP 2.0 app that uses the AuthComponent with User model to successfully login to manage posts and other controllers and models. I'll call that the "super admin" part of the site.
However, I need to create an entirely separate part of the site for advertisers. I have created model Advertiser and controller AdvertisersController. I have also created table advertisers. I am able to successfully add an advertiser user, but when I attempt to login, it fails with the invalid username or password error.
I followed suggestions in the Cookbook for Authentication and tried both of these options in the beforeFilter of my AdvertisersController:
$this->Auth->authenticate = array(
AuthComponent::ALL => array(
'userModel' => 'Advertiser',
'fields' => array('username' => 'username', 'password' => 'password'),
'Form',
'Basic'
));
$this->Auth->authenticate = array(
'Form' => array('userModel' => 'Advertiser'),
'Basic' => array('userModel' => 'Advertiser')
);
Any ideas? Is it not possible to use the AuthComponent with two different models/controllers?
EDIT: I updated my AdvertisersController to this:
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->authenticate = array(
AuthComponent::ALL => array('userModel' => 'Advertiser'),
'Form',
'Basic'
);
$this->Auth->allow('add', 'logout'); // Letting advertisers register themselves
}
Now the login is failing altogether -- no failed password error. I even tried a bogus username and password. Here is the login method in my controller:
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->redirect(array('controller' => 'advertisers', 'action' => 'admin'));
} else {
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
}
I added an else print_r($this->data); exit; statement after the close of the first if and got an empty array. Couldn't even get to the login page.
Also, the output for the form is this -- POST is the method.
<form action="/advertisers/login?url=advertisers%2Flogin" id="AdvertiserLoginForm" method="post" accept-charset="utf-8">
<div style="display:none;"><input type="hidden" name="_method" value="POST"/></div>
<fieldset>
<legend>Please enter your username and password</legend>
<div class="input text required">
<label for="AdvertiserUsername">Username</label>
<input name="data[Advertiser][username]" maxlength="50" type="text" id="AdvertiserUsername"/>
</div>
<div class="input password required">
<label for="AdvertiserPassword">Password</label>
<input name="data[Advertiser][password]" type="password" id="AdvertiserPassword"/>
</div>
</fieldset>
<div class="submit">
<input type="submit" value="Login"/>
</div>
</form>
I reposted this question with more information here. Joshua was a big help getting admin prefixing sorted out for this scenario. If it seems like "too much" for your app -- see his comments here. It looks more complicated than it is, and it helps keep user controls much more defined.
I'm building a non-javascript version of a website, as there are a number of customers who don't have javascript enabled. On this site, the customer selects what country they will be visiting and then displays the data related to that country accordingly.
I've managed to get this to work. They use a HTML drop down menu to select the country, click on Submit, and the page reloads with the data related to the selected country. However, it does not change the country displayed in the HTML drop down menu, so when the page reloads it reverts back to "Select A Country".
What I would like to have happen is that if you clicked on United Kingdom from the drop down box for example, when the page reloads the drop down should display United Kingdom.
Here is the code I am currently using for the view file:
<form name="countryselect" action="/selected-country/" method="post">
<select id="country-list" name="countryselected">
<?php foreach($countries as $coun) { ?>
<option value="<?php echo $coun['Tariff']['countryslug']; ?>"><?php echo $coun['Tariff']['countryname']; ?></option>
<?php } ?>
<input type="submit" value="Submit" />
</select>
</form>
And in my controller file I am using this:
$countries = $this->Tariff->find('all', array('conditions' => array('Tariff.gsmid' => '1')));
$this->set('countries', $countries);
if (!isset($_POST['countryselected'])) {
} else {
$countryselect = $_POST['countryselected'];
$tarcounselect = $this->Tariff->find('first', array('conditions' => array('Tariff.countryslug' => $countryselect)));
$this->set('tarcounselect', $tarcounselect);
}
Cheers!
If you use Cake, you should not build the form and the select manually but use the Cake FormHelper instead. It will then keep the selected country automatically:
Controller:
$this->set('countries', $this->Tariff->find('list', array('conditions' => array('Tariff.gsmid' => '1'), 'fields' => array('countryslug', 'countryname'))));
View:
<?php
echo $this->Form->create();
echo $this->Form->select('Tariff.countryslug', $countries);
echo $this->Form->end(__('Submit'));
?>
And then to retrieve the selected country in the controller:
if($this->request->is('post'))
{
$countryslug = $this->request->data['Tariff']['countryslug'];
}
I have a checkbox list that I create using the form helper
echo $form->input('Interest.interest_id', array('label' => __l('Interests'), 'multiple' => 'checkbox'));
It then created for each checkbox and automatic id
eg.
<input id="InterestInterestId1" type="checkbox" value="1" name="data[Interest][interest_id][]">
<input id="InterestInterestId2" type="checkbox" value="2" name="data[Interest][interest_id][]">
Is it possible to have my own unique id that I create for each checkbox? For example customInterestInterestId1, customInterestInterestId2 ...
You should be able to do this:
echo $form->input('Interest.interest_id',
array('label' => __l('Interests'),
'multiple' => 'checkbox',
'id'=>'your_custom_id_')); // add ID to the array
It works for the other auto-magic input types; but I haven't tested it with a multiple check box.
Cake will then generate:
... id="your_custom_id_1" ...
... id="your_custom_id_2" ...