cakePHP one to one association help needed - relationship

So far this is the part of cakePHP that boggles my simple brain.
I have for this example 2 tables.
vw_penkits and vw_bushings
vw_penkits has a field vw_bushing_id
Here are the Models:
class VwPenKit extends AppModel {
var $name = 'VwPenKit';
var $useTable = 'vw_pen_kits';
public $hasOne = 'VwBushing';
}
class VwBushing extends AppModel {
var $name = 'VwBushing';
var $useTable = 'vw_bushings';
public $belongsTo = array (
'PenKit' => array (
'classname' => 'VwPenKit',
'foreignKey => 'vw_bushing_id'
)
);
}
Here is the VwPenKitsController index()
public function index() {
$this->loadModel('VwBushing');
$bushings = $this->VwBushing->find('list');
$this->set(compact('$bushings'));
$this->set('penkits', $this->VwPenKit->find('all'));
}
Here is the code section for index.ctp
<td><?php echo $penkit['VwPenKit']['kit_name']; ?> </td>
<td><?php echo $penkit['VwPenKit']['kit_description']; ?> </td>
<td><?php echo $penkit['VwBushing']['code']?></td>
<td><?php echo $penkit['VwPenKit']['modified']; ?> </td>
Here is the error when rendered
Pen Kit Database
Version 0.1
Part No. Kit Name Description Bushing Modified Actions
DK-PKCP8020 Bolt Action Pen (30 Cal)
Notice (8): Undefined index: VwBushing [APP/View/VwPenKits/index.ctp, line 46] 2015-04-07 11:00:00 View Edit Delete
Created by: Mike Marek
Contact information: mike#thewoodartiststudio.com.
©2015 The Wood Artist Studio - All Rights Reserved
also once I get this figured out I need an add.ctp and edit.ctp that create a selection list so that user can associate a pen kit to its bushing.
I don't have enough status yet to post images
Thanks in advance
Mike

I'm not 100% sure but it could have to do with your recursive value in your find. If it is set to 0 then it will only find the first level. You need to set it to 1 or 2 depending how deep you want to find.
I would highly recommend making use of the ContainableBehaviour. It will make your life a whole lot easier.
See here.

I did solve the issue and it basically was a Model problem. Once I had the relationship correct all works fine.
Thanks
Mike

Related

Look up data from a diffrent model using Cake

im new to cake (and loving it) but i have hit a problem that i cant seem to find a solution to. Im pretty sure there is an obvious answer to this so my apols in advance if i am asking a stupid question.
Okay, here goes.
I am trying to build a simple message system using Cake PHP version 2.
I have two models at the moment, one handles users (used for loggin in and out) and the other handles messages.
In the messages table i have the following columns:
id | sender_id | recipient_id | subject | body
My MessagesController.php reads as follows:
class MessagesController extends AppController {
public function recent_messages() {
if (empty($this->request->params['requested'])) {
throw new ForbiddenException();
}
return $this->Message->find(
'all'
);
}
}
My View is located in my elements as it actually displayed as a drop down in my navbar. Here is my view:
<?php
$messages = $this->requestAction('/messages/recent_messages');
?>
<?php
foreach ($messages as $message): ?>
<li>
<a href="#">
<div> <strong>Username of sender goes Here</strong></div>
<div><?php echo $message['Message']['subject']; ?></div>
</a>
</li>
<li class="divider"></li>
<?php endforeach; ?>
What i would like to do is to be able to get the actual username of the message sender using the sender_id. Just to clarify the sender_id value is actually the id (primary key) of the user in the users table.
Initially i thought this would be done through setting an association but i cant see how.
If anyone could offer any advice on this i would be most grateful.
I don't understand why you are using $this->requestAction
if your view is recent_messages.ctp you are already calling recentMessages().
Then if you set your relationships you are already retrieving all the data you need
$message['Sender']['username']
contains the information you are looking for. (or $message['User']['username'] it depends on how you wrote your model).
If not read the Manual about setting the relationships.
In brief all you have to do in your Message model is
$belongsTo = array(
'Sender' => array(
'className' => 'User',
'foreignKey' => 'sender_id'
)
)
One further thought.
It seems that you are doing the requestAction from the view. I think it can only be done from the controller and then you pass the result to the view via the $this->set('messages', $message) command.
If I've misinterpreted what you are doing then I'm sorry.

CakePHP Not Saving BelongsTo Key

I'm trying to save a record that belongs to another model. Yet, I get an error that the foreign key is missing. The CakePHP docs show examples of this working but I can't get it to work.
Here is the Form:
echo $this->Form->create('Message', array('action'=>'add'));
echo $this->Form->hidden('Ticket.id');
echo $this->Form->input('Message.message');
echo $this->Form->submit('Save Message');
echo $this->Form->end();
Here is what is returned to the controller upon submit:
Array(
[Ticket] => Array
(
[id] => 2
)
[Message] => Array
(
[message] => Message text
)
)
Here is my Message model:
class Message extends AppModel {
public $belongsTo = array('Ticket');
}
Here is my Ticket model:
class Ticket extends AppModel {
public $hasMany = 'Message';
}
Here is my controller logic:
$this->Message->save($this->request->data);
Here is the error message I receive:
Error: SQLSTATE[HY000]: General error: 1364 Field 'ticket_id' doesn't have a default value
The CakePHP documents are pretty clear that Cake will grab the id from the Ticket array. The only way I can get this to work is if I manually assign the ticket id to the message array.
$this->request->data['Message']['ticket_id'] = $this->request->data['Ticket']['id']
I shouldn't have to do that. Where's the magic? I've read at least 20 similar posts but none exactly like this (probably because this is so basic that nobody has this problem because it works for them).
I'm using version 2.4.2
Thanks for any help.
Don't use Model::save() in this case, the reason is that you also want to save associated data, in order for you save data for the main model along with its associated models you need to use Model::saveAssociated().
Your controller should be looking like this
$this->Message->saveAssociated($this->request->data);

cakephp view printing out the same values from database

created a view function and any time i click the link to view a template, the url at the top of the page is correct but it spits out the same list of fields in the database.
the fields are
accounts - id, company name, abn
template - id, name, description, account_id
field - id, name, field type, template_id
function view(){
$accounts=$this->User->AccountsUser->find('list',
array('fields'=>array('id', 'account_id'),
'conditions' =>array('user_id' =>
$this->Auth->user('id'))));
$templates=$this->Template->find('first',
array('conditions' => array(
'Template.account_id' => $accounts)));
$fields=$this->Field->find('all',
array('conditions' => array(
'Field.template_id' => Set::extract('/Template/id', $templates))));
$this->set('template', $templates);
$this->set('account', $accounts);
$this->set('field', $fields);
}
here is the view
<div class = "conlinks">
</br></br></br></br></br><h2>Here is your template fields</h2></br>
<?php foreach($field as $fields): ?>
<tr>
<td align='center'><?php echo $fields['Field']['name']; ?>
</tr></br>
<?php endforeach; ?>
</div>
so the problem is its grabbing the exact same list of fields, not the correct template_id when it prints out the fields
You should be able to debug this for yourself. Just narrow the bug down step by step.
For starters, in your view function, do a print_r on the following variables, and make sure each one contains a logical result:
$accounts
$templates
$fields
If you find unexpected results there, I'd be looking at the parameters you pass into each of your finds, and making sure they're OK. You're passing in $accounts as an array to your find condition - make sure it matches the format that cake expects. Do the same for Set::extract('/Template/id', $templates).
Also look at the SQL that Cake is producing.
If you're not already using it, I'd highly recommend installing Cake's Debug Kit Toolbar - https://github.com/cakephp/debug_kit/ because it makes debugging variables and SQL much easier.
If you do the above steps and can't solve your problem, you should at least be able to narrow it down to a line or two of code. Update your answer to show what line or two is causing the problem, and include print_r's of some of the variables you're working with. That should help others on StackOverflow to give you a specific answer.
Hope that helps!
the issue was I wasn't getting the parameters when click the link
function view($name){
$fields = $this->Template->Field->find('list',array(
'fields'=> array('name'),
'conditions' => array(
'template_id'=> $name)));
$this->set('field', $fields);
}
and the view
<div class = "conlinks">
</br><h2>Here is your template fields</h2>
<?php foreach($field as $name): ?>
<tr>
<td align='center'>
<?php echo $name; ?>
</tr></br>
<?php endforeach; ?>
</br>
<?php
echo $this->Html->link('Back', '/templates/view', array('class' => 'button'));?>
</div>

Edit and save multiple records in cakephp

In my cakephp app I have an Option model.
In my option/index view I display 2 options with inputs and radio button fields.
I want to update both of them, but I get a weird behaviour.
The option I alter doesn't get saved and instead a new option is inserted with the new value.
Here is my view
<h2 class='page-title' id='manage-options'>Opzioni</h2>
<?php echo $form->create(null, array('action'=>'index')); ?>
<table>
<tr>
<td><?= $options[0]['Option']['name']?></td>
<td><?= $form->radio(
$options[0]['Option']['id'],
array(
'1' => 'Sì',
'0' => 'No'),
array('default'=> $options[0]['Option']['value'], 'legend'=>false)
);?>
</td>
</tr>
<tr>
<td><?= $options[1]['Option']['name']?></td>
<td><?= $form->input($options[1]['Option']['id'],array('label'=>false,'value' => $options[1]['Option']['value'] ))?></td>
</tr>
</table>
<?php echo $form->submit('Salva'); ?>
<?php echo $form->end(); ?>
And my controller:
function index() {
if (!empty($this->data)) {
foreach($this->data['Option'] as $id => $value) :
$this->Option->id = $id;
$feedback = $this->Option->read();
$this->Option->saveField('value', $value);
endforeach;
$this->Session->setFlash('Opzioni aggiornate');
}
$this->Option->recursive = 0;
$this->set('options', $this->paginate());
}
Before posting here I spent two hours googling for answers and experimenting. I know about saveAll() and i have tried these solutions:
http://planetcakephp.org/aggregator/items/2172-cakephp-multi-record-forms
http://teknoid.wordpress.com/2008/10/27/editing-multiple-records-with-saveall/
I have been tweaking my code to fit these patterns, but I got no results (oscillating between 'not working' and 'not working and I get an extra record'), so I decided to post my original code.
Can you help, indicating the most proper way to do this?
Cheeers,
Davide
The problem was with the data in the DB. The kind folks on the cakephp IRC channel called my attention to the fact that in most databases ID = 0 equals 'new record'. For some reason I had an option with ID 0, so when updating the underlaying mysql query actually created a new record.
Changed the IDs, problem fixed.
The main problem with your code that I see is that your fields, both the radio and the input, are being built with only an ID value as the first parameter. The correct "cake way" of building a field is having the first parameter be Model.fieldname, in your case I believe it would be $form->input('Option.id', array())?>
If you inspect the html generated by your code you will see the field name is data[id], and it should be data[Option][id] if you want to loop through $this->data['Option'] in your controller.
Try changing your code to include the Model.fieldname as the first parameter and then it should have the data submitted correctly to your controller.

CakePHP assocation question

I'm creating a small timesheet application. Timesheets have athletes, and each athlete has personal split times (like in running, or race car driving)
An Athlete hasMany Run, a Run belongsTo Athlete, An Athlete hasAndBelongsToMany Timesheets (and vice versa). A Timesheet hasMany Run, and finally a Run belongsTo Timesheet.
When I'm adding new runs in my view, I'm unable to get anything but the athlete_id in the select box. I'd really like to have their names instead. Instead of
<?php echo $run['athlete_id'];?>, I've tried <?php echo $athlete['Athlete']['last_name'] ?> but I can't seem to get it to work. Any help would be greatly appreciated. Thanks!
Without knowing exactly how you are building your forms/data it is hard to tell, but how I would do it is.
In the RunController add
$athletes = $this->Run->Athlete->find('list');
$this->set('athletes', $athletes);
and then in the View use this form helper line.
<?php echo $form->input('Run.athlete_id', array('type' => 'select', 'options' => $athletes)); ?>
This should work, there is also a way to use 'compact' to make it a little easier but the above should work fine.
---- BEGIN EDIT ----
I did a little research and found the compact method.
In your RunController use
$athletes = $this->Run->Athlete->find('list');
$this->set(compact('athletes'));
and then in your View use
<?php echo $form->input('Run.athlete_id'); ?>
and the form helper will automatically find the compacted Athlete array and build the select.
---- END EDIT ----
Hope this helps.
Cheers,
Dean
Try printing out the content of the $run: print_r($run) and see if the ['Athlete'] is there.
If not, you might have to manually contain the Athlete model when you do your run query:
$this->Run->contain('Athlete');
Don't forget to use the displayField property of the Model class i.e.
<?php
class Athlete extends AppModel {
public $name = "Athlete";
public $displayField = "name"; // the field name that has the athletes name in it
}
?>
http://book.cakephp.org/view/438/displayField

Resources