When I try to add some entries into the join table of two classes, I run into issues with CakePHP.
Here is my join table:
posts_comments
id
post_id
comment_id
my post Model:
<?php
class Post extends AppModel {
var $hasManyAndBelongsTo = array('Comment')
}
?>
My Comment Model:
<?php
class Commentextends AppModel {
var $hasAndBelongsToMany = array('Post');
}
?>
My Controller:
ForumController:
function save() {
if ($this->data) {
$this->loadModel('PostComment');
$this->layout = null;
debug($this->data);
$this->PostComment->save($this->data);
}
$this->redirect(array('action' => 'view', $this->data['PostComment']['PostId']));
}
And my view.ctp:
<?php
echo $this->Form->create('PostComment', array('url' => 'save', 'id' => 'save')); ?>
echo $this->Form->hidden('PostComment.PostId', array('value' => $id));
echo $this->Form->input('PostComment.CommentId', array('label' => '', 'type' => 'select', 'multiple' => 'checkbox', 'options' => $CommentName, 'selected' => $CommentId));
echo $this->Form->submit('save', array('id' => 'submit'));
echo $this->Form->end();
?>
When I click on submit, nothing is submitted, and the redirection happens, but the data contained in my $this->data is not save in my BDD.
But what I want is that when I submit my form, I don't want that CakePHP create a new post or a new comment, I just want a new relation between the two.
I already succeed to done it, but I used
$this->myObject->query("INSERT INTO blablabla")
The problem is that I have a multiple checkboxes, so I don't really know how I can easily check that one box has been unchecked or checked.
You can work in a simpler way if you create another model with two hasMany relations instead of one with HABTM.
HasAndBelongsToMany between two models is in reality shorthand for
three models associated through both a hasMany and a belongsTo
association.
I found it is one of the simplest ways to save and retrieve data.
For more information: http://book.cakephp.org/2.0/en/models/saving-your-data.html#what-to-do-when-habtm-becomes-complicated
At the new model, you could do something like:
public addRecord($userId, $postId)
$this->data[$this->alias]['user_id'] = $userId;
$this->data[$this->alias]['post_id'] = $postId;
return $this->save($this->data[$this->alias]);
}
Related
I am using wordpress 4.1 along with WP MVC.
I have 3 three tables that need to be added with a single form input.
Tables: (prefix for all tables: 'wp_w2store_'): manufacturers, addresses, countries, zones.
When I choose to add a 'Manufacturer', i need to add the fields of address table in the same form and along with that i have to retrieve country_name and zone_name from the respective tables, which are also form the fields list of 'Address'.
I dont even get the form inputs in the form and i get this error:
MVC Fatal Error: Field "user_id" not found for use in a form input.
since 'user_id' is the first foreign field to this form, it alone is shown here. if i remove that field, the error will be shifted to next available field and so on.
In the add() function of admin_manufacturers_controller, i have loaded the model 'Address' and set that with all its fields in an array variable, $addresses, as follows:
public function add() {
$this->set_manufacturers();
$this->set_addresses();
$this->create_or_save();
}
private function set_addresses() {
$this->load_model('Address');
$addresses = $this->Address->find(array('selects' => array('id', 'user_id', 'first_name', 'last_name',
'address_1', 'address_2', 'email', 'city', 'zip', 'zone_id', 'country_id',
'phone_1', 'phone_2', 'fax', 'type', 'company', 'tax_number', 'customer_note')));
$this->set('addresses', $addresses);
}
and this is the add.php of manufacturers:
input fields for manufacturers table:
<?php echo $this->form->create($model->name); ?>
<?php echo $this->form->belongs_to_dropdown('Address', $addresses, array('style' => 'width: 200px;', 'empty' => true)); ?>
<?php echo $this->form->input('enabled');?>
<?php echo $this->form->input('ordering');?>
input fields for address table:
<h4>Address Fields</h4>
<?php echo $this->form->input('Address.user_id');?>
<?php echo $this->form->input('Address.first_name');?>
<?php echo $this->form->input('Address.last_name');?>
<?php echo $this->form->input('Address.email');?>
<?php echo $this->form->input('Address.address_1');?>
<?php echo $this->form->input('Address.address_2');?>
and so on...
Since I dont have enough reputation, i dont have privilege to add an image in the question. Kindly bear.
Any suggestions to rectify this issue is thankfully welcome.
This issue is solved by adding the code below to the manufacturer model for joining the tables:
$manufacturers = $this->Manufacturer->find(array(
'selects' => array(
'id','address_id','enabled','ordering','address.*'),
'joins' => array(
'table' => $this->Address->table,
'on' => 'address.id = Manufacturer.address_id',
'alias' => 'address',
'type' => 'LEFT JOIN'
)
)
);
Thanks.
I have several tables and corresponding models, that is to say, Staffs, Dpmembers, Subjects and Positions tables.
In my Staff model I create hasOne on Department because I want to retrieve data from Department table which is working.
But I have also created more associations of hasMany on Dpmember, Subject and Position models because I want to save the corresponding staff records.
The view newstaff.ctp looks like this
<div class="staff form">
<?php echo $this->Form->create('Staff');?>
<h3><?php echo __('Add a new staff member'); ?></h3>
<?php
echo $this->Form->input('name');
echo $this->Form->input('marital',array('label'=>'Marital status','options'=>array('empty'=>'Choose status','Single'=>'Single','Divorced'=>'Divorced','Married'=>'Married')));
echo $this->Form->input('Children');
echo $this->Form->input('nationality');
echo $this->Form->input('location');
echo $this->Form->input('email');
echo $this->Form->input('phone',array('label'=>'Phone number'));
echo $this->Form->input('nextofkeen',array('label'=>'Next of keen'));
echo $this->Form->input('keenrelation',array('label'=>'Next of keen relationship','options'=>array('Choose option'=>'Choose option','Husband'=>'Husband','Wife'=>'Wife','Guardian'=>'Gaurdian','Child'=>'Child')));
echo $this->Form->input('school');
echo $this->Form->input('award');
echo $this->Form->input('schoolperiod');
echo $this->Form->input('workplace',array('label'=>'Workplace'));
echo $this->Form->input('workposition');
echo $this->Form->input('workperiod');
echo $this->Form->input('dpmember.department.',array('options'=>$department,'empty'=>'Choose Department','label'=>'Department'));
echo $this->Form->input('subject.subjcet',array('options'=>array('Choose option'=>'Choose option','Science'=>'Science','Social Studies'=>'Social studies','English'=>'English','Mathematics'=>'Mathematics'),'label'=>'Subject'));
echo $this->Form->input('position.role',array('options'=>array('Choose option'=>'Choose option','Class teacher'=>'Class teacher','Bursar'=>'Bursar','Cook'=>'Cook'),'label'=>'Position'));
echo $this->Form->submit('Save staff', array('class' => 'btn btn-success', 'title' => 'Click here to add the user') );
?>
<?php echo $this->Form->end(); ?>
</div>
My Staff Model Staff.php like this
<?php
class Staff extends AppModel{
public $hasOne = array(
'Department'=>array(
'className'=>'Department'
));
public $hasMany = array(
'Dpmember'=>array(
'className'=>'Dpmember',
'foreign_key'=>'Dpmember.staff_id'
),
'Subject'=>array(
'className'=>'Subject',
'foreign_key'=>'Subject.staff_id'
),
'Position'=>array(
'className'=>'Position',
'foreign_key'=>'Position.staff_id'
)
);
}
?>
In my StaffsController.php I have a function newstaff() with the code below
public function newstaff() {
/*Create a select form field for departments */
$department = $this->Staff->Department->find('list',array('fields'=>array('Department.title','Department.title')));
$this->set('department', $department);
/*End creation of a select form field for departments */
if (!empty($this->request->data)) {
debug($this->request->data); // returns all data
debug($this->Staff->Subject->subject); // has returned null
debug($this->Staff->Position->position); // has returned null
debug($this->Staff->Dpmember->departement); // has returned null
}
}
I don't know why but for some reason, I have not been able to found out. Running debug($this->request->data) returns expected data.
But accessing individual associated form fields returns null values not the expected data. Please help me.
Thank you
You seem to be using CakePHP 3.0 syntax, while using CakePHP 2.3. The data returned is an array in Cake 2, not an object. So the data is under array keys, like:
$this->request->data['Staff']['Subject']['subject'];
$this->request->data['Staff']['Position']['position'];
$this->request->data['Staff']['Dpmember']['departement'];
Well I think finally I have got the values which are not null. Since I created relationships or rather associations among the models and am using CakePHP 2.3 the right way is
$this->request->data['associateModel']['FormField'];
Therefore I was supposed to do.
$this->request['Subject']['subject'];
$this->request['Subject']['position'];
$this->request['Subject']['department'];
Thank you very much #Oldskool
I need to create CRUD screen using yii-framework. Simple CRUD screen using one table is working perfectly fine. I'm facing problem/issue while using dropdown (linking table).
I have installed giix extension which is suppose to create CRUD with dropdown if FK is specified but I dnt have MySql Engine InnoDB on my hosting provider, so I'm not able to use that extension. I need to do it manually.
I have two tables
main:-
id
store_id
prefix
store:-
id
name
Now store_id of main is FK to id of store table. And I want to create CRUD for main table.
So that Add Screen should show:-
Store Name:- Dropdown
prefix:- Textbox
View screen should use name column of store table instead of showing store_id
Thanks in anticipation.
Generate CRUD using Gii, then read my blog. http://jmmurphy.blogspot.com/2013/05/using-yii-model-relations.html
Basically you will have something like this for your store_id field after Gii Generation
<?php echo $form->labelEx($model,'store_id'); ?>
<?php echo $form->textField($model, 'store_id', array('size'=>60,'maxlength'=>255));?>
<?php echo $form->error($model,'store_id'); ?>
The textField line is replaced by:
<?php $list = CHtml::listData(Store::model()->findAll(), 'id', 'name'); ?>
<?php echo $form->dropDownList($model, 'store_id', $list, array('empty'=>'(Select a Store)')); ?>
You also need to define relations in your Main model so that you can access related tables (even if your database does not support foreign keys) like this:
public function relations()
{
return array(
'store'=>array(self::BELONGS_TO, 'Store', 'store_id'),
);
}
And to complete this relation, you should also add the following relation to your Store model:
public function relations()
{
return array(
'main'=>array(self::HAS_MANY, 'Main', 'store_id'),
);
}
These relations define a One to Many relation between Store and Main where store is the parent, and Main is the Child. To make it a One to One relationship change HAS_MANY to HAS_ONE. The HAS_* goes in the parent model and points to the foreign key attribute in the child table. The BELONGS_TO goes in the child and tells the attribute in the child table that points to the primary key in the parent.
Now to see the store name in the view action, you need to change 'store_id' in your view.php to an array that looks like:
array(
'name' => 'store_id',
'value' => $model->store->name,
)
The admin view is slightly different. I am not sure exactly why, but to view the store name instead of the id in the admin view you will need to use an array that looks like:
array(
'name' => 'store_id',
'value' => '$data->store->name',
)
Note that Gii generates this so that $data is the model instead of $model, and also it does a funky double indirection thing so that you need to put the variable declaration in single quotes.
Thanks jmarkmurphy for your help. You helped me lot and I have marked your answer as correct only as you gave me guidance. Just posting exact code in detail.
I changed view.php with below code:-
<?php $this->widget('zii.widgets.CDetailView', array(
'data'=>$model,
'attributes'=>array(
'id',
'store.name',
'prefix',
),
));
Also changed admin.php with below code:-
<?php echo CHtml::encode($data->store->name); ?>
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'main-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'id',
'store.name',
'prefix',
array(
'class'=>'CButtonColumn',
),
),
)); ?>
Thanks once again jmarkmurphy. Thanks a lot . My application is now working and exactly the way I wanted.
I'm creating an AJAX form. The problem is when I'm trying to create a input form with formhelper, my input's name attribute is not correctly renedered in the view. Here's my code:
$form->input('MainAttribute.'.$i.'.SubAttribute.'.$j.'.score', array('label' => '', 'options' => $scores));
I created it that way because I want SubAttribute to be inside MainAttribute. When I inspect the HTML, the name attribute of the form is cutted of like:
name="data[SuperMainAttribute]"
How can I specify the name attribute to the one that I'm planning on doing?
(e.g. data[MainAttribute][0][SubAttribute][0][score])
Edit:
Here are my model relationships:
Control hasMany MainAttribute
MainAttribute hasMany SubAttribute
The ctp is in a view of the Control Controller
In general, almost anytime you call FormHelper::input, the first parameter will appear in one of the following formats:
for the primary model, or hasOne and belongsTo associations: $form->input('Model.field')
for hasMany associations: $form->input("Model.{$n}.field")
for hasAndBelongsToMany associations: $form->input("Model.Model.{$n}.field")
(In these cases, $n is an iterator (0,1,2,3, etc.), allowing you to add multiple records to hasMany- and hasAndBelongsToMany-associated models.)
Your specific case is tricky, because you want to save a Control record, and all of its MainAttribute records, and all of each MainAttribute's SubAttribute records. This isn't possible without some data manipulation in the controller. The way I'd probably tackle this problem is the following.
In the view:
echo $form->create('Control', array('action'=>'add'));
echo $form->input('Control.field_name');
$iLimit = 4;
$jLimit = 2;
for ($k=$i=0;$i<$iLimit;$i++) {
echo $form->input("MainAttribute.{$i}.field_name");
for ($j=0;$j<$jLimit;$j++) {
echo $form->input("SubAttribute.{$k}.ixMainAttribute", array('type'=>'hidden','value'=>$i));
echo $form->input("SubAttribute.{$k}.field_name");
$k++;
}
}
echo $form->end('Submit');
In ControlsController:
function add()
{
if (! empty($this->data)) {
// Perform data validation separately...
if ( $this->Control->save( $this->data['Control'], false )) {
foreach ( $this->data['MainAttribute'] as $k => $_data ) {
$_subAttributes = Set::extract("/SubAttribute[ixMainAttribute={$k}]", $this->data);
$insert = array(
'MainAttribute' => am( $_data, array('control_id' => $this->Control->id)),
'SubAttribute' => $_subAttributes
);
$this->Control->MainAttribute->saveAll($insert, array('validate'=>false));
}
}
}
}
HTH.
I have two combos; provinces and cities.
I would like to change cities value when the province combo value changes. Here is my code
<div class="cities form">
<?php
$v = $ajax->remoteFunction(array('url' => '/cities/','update' => 'divcity'));
print $form-> input('Province.province_id', array('type' => 'select', 'options'=> $provinces, 'onChange' => $v));
?>
<div id="divcity">
<?php
echo $form->input('Cities.cities_name');
?>
</div>
Every time I change province combo, it call cities/index.ctp. anybody want to help?
really thank for your help
wawan
The 'url' => '/cities/' is calling the default index action of the cities controller.
This automatically renders the cities/index.ctp view.
Have you included the RequestHandler component in the cities controller?
This can be used to detect Ajax requests and then render a different view.
You need to first include the RequestHandler Component at the top of the CitiesController, then write a function to list cities, optionally requiring a Province's id.
I think you'll end up having something like this:
<?php
// In the view
$v = $ajax->remoteFunction(array('url' => '/cities/list','update' => 'divcity'));
print $form-> input('Province.province_id', array('type' => 'select', 'options'=> $provinces, 'onChange' => $v));
// In CitiesController
function list($province_id = null) {
// use $this->City->find('list', array('fields'=>array('City.id', 'City.name')))
// to generate a list of cities, based on the providence id if required
if($this->RequestHandler->isAjax()) {
$this->layout = 'ajax';
$this->render();
}
} ?>