My objective is to display records for a related child model (once removed) in the view. My problem is that I receive a 'Notice (8): Undefined index:' error message when I try to output the following query.
Tournaments have many tournamentDetails, and tournamentDetails have many updates. I'm trying to display all the updates for each tournamentDetail that is displayed on the tournaments view.
So my question is how to properly resolve the error message and display the updates for each tournamentDetail on the tournaments view page.
My find data in the 'tournaments' controller view action is:
$updates = $this->Tournament->TournamentDetail->Update->find('all', array( 'tournament_details.tournament_id'=> $this->data['Tournament']['id']));
In the view, I have this code.
<?php foreach ($tournament['Update'] as $update): ?>
<h3>Updates</h3>
<h1><?php echo $update ['title']; ?></h1>
<p><?php echo $update ['body']; ?></p>
<hr/>
<?php endforeach; ?>
This is the same 'foreach' code the I use for the other related child records without problem. I did use the debug() function to investigate but didn't see what I was missing.
The output of the $updates array from the debug function looks like this:
Array
(
[0] => Array
(
[Update] => Array
(
[id] => 1
[title] => first round matches start today
[date] => 2010-03-19
[body] => this tournament's first round matches start today.
[tournament_detail_id] => 4
[homeStatus] => no
)
Is there a special way to display records this deep?
As always, thanks in advance.
Paul
Update: Feb 23/11
After some testing the problem I seem to have is finding and passing the correct value to the $updates variable;
To summarize, I want the $updates variable to hold the current 'tournament_details_id'. This will then display the related update records in the 'tournaments' view.
I'm still a beginner and most likely overlooked the obvious.
Here is the model info:
class Tournament extends AppModel {
var $name = 'Tournament';
var $hasMany = array(
'TournamentDetail' => array(
'className' => 'TournamentDetail',
'foreignKey' => 'tournament_id',)
class TournamentDetail extends AppModel {
var $name = 'TournamentDetail';
var $belongsTo = array(
'Tournament' => array(
'className' => 'Tournament',
'foreignKey' => 'tournament_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
class Update extends AppModel {
var $name = 'Update';
var $belongsTo = array(
'TournamentDetails' => array(
'className' => 'TournamentDetails',
'foreignKey' => 'tournament_detail_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
Controller data:
class TournamentsController extends AppController
function view($slug = null) {
if (!$slug) {
$this->Session->setFlash(__('Invalid Tournament.', true));
$this->redirect(array('action'=>'index'));
}
$this->Tournament->recursive = 1;
$tournament = $this->Tournament->findBySlug($slug);
$updates = $this->Tournament->TournamentDetail->Update->find('all', array('conditions' => array( 'tournament_details_id' => $this->data['TournamentDetails']['id'] )));
$this->set(compact('tournament','updates', $updates ));
Tournament view. This is display the 'tournament details' and (ideally) related tournament detail 'updates'
<h2><?php echo $tournament['Tournament']['name']; ?></h2>
<?php foreach ($tournament['TournamentDetail'] as $tournamentDetail): ?>
<h1><?php echo $tournamentDetail ['title']; ?></h1>
<p><?php echo $tournamentDetail ['body']; ?></p>
<?php endforeach; ?>
<?php foreach ($updates['Update'] as $update): ?>
<h4>Update: <?php echo $update ['date']; ?></h4>
<p> <?php echo $update ['Update'] ['title']; ?></p>
<p><?php echo $update ['Update'] ['body']; ?></p>
<?php endforeach; ?>
I've tested this by adding in the tournament details 'id' as an integer and it pulls up the correct 'update' record. However I seem to have problems configuring the find operation to do the same.
As always I appreciate the help.
Thanks
Paul
Based on your debug output, it seems that your $tournaments variable consists of an array (instead of the associative array) so you might want to use the foreach to access each of those elements:
foreach ($tournaments as $update):
?>
<h3>Updates</h3>
<h1><?php echo $update ['Update']['title']; ?></h1>
<p><?php echo $update ['Update']['body']; ?></p>
<hr/>
<?php endforeach; ?>
It appears that you be using the wrong variable, you talk about the $updates variable but you're using the $tournament variable in your view.
<?php foreach ($updates['Update'] as $update): ?>
<h3>Updates</h3>
<h1><?php echo $update ['title']; ?></h1>
<p><?php echo $update ['body']; ?></p>
<hr/>
<?php endforeach; ?>
Additionally you haven't posted the whole controller method, which includes that find but you might not have sent the data to the view yet either
$this->set(compact('updates'));
Related
How to fix this issue
Error: userHelper could not be found.
this is my search.ctp inside element which is called in default.ctp
<?php echo $this->Form->create(null, ['url' => ['controller' => 'Users', 'action' => 'search']], array('type' => 'get')); ?>
<?php echo $this->Form->input('username'); ?>
<?php echo $this->Form->button('Search', ['type' => 'submit']); ?>
Below is my search controller
public function search() {
$value = $this->request->getData('username');
$results = $this->Users->find('all', ['fields'=>[
'Users.username',
'Users.email',
'Users.id',
'Users.age',
'Users.address',
'Users.gender'
],
'order' => 'Users.id ASC',
'conditions' => array(' username LIKE' => "%".$value."%")
]);
$this->set('user', $results);
$this->set('_serialize', ['user']);
}
search.ctp inside users
<?php
use Cake\ORM\TableRegistry;
use Cake\Filesystem\Folder;
use App\Controller\AppController;
?>
<?php foreach ($user as $users): ?>
<?php echo $this->users->username;?>
<?php endforeach;?>
What is the line inside loop? It shouldn't be.
$this->users->username;
I'm not so sure returning as a array or object in cakephp 3.
But, I'm sure that it should be like that,
$users->username;
or
$users['username'];
I am working on CakePHP 2.7.8. I want to update related list with change in list using Ajax.
I have a customers table and customer_addresses table in the database and customers and customerAddress models in the project.
There is another controller serviceRequests where I have to select customer and address of the selected customer from a drop down list generated by CakePHP from database.
What I have done-
I have added a function getCustomerAddress in the serviceRequests controller
public function getCustomerAddress(){
$customer_id = $this->request->data['Post']['customer_id'];
$customer_address = $this->CustomerAddress->find('list',array(
'condition' => array('CustomerAddress.customer_id' => $customer_id),
'recursive' => -1
));
$this->set('customerAddresses', $customer_address);
$this->layout = 'ajax';
}
to display the retrieved data, I have a view get_customer_address.ctp
<?php
foreach ($customerAddresses as $key => $value): ?>
<option value="<?php echo $key;?>"><?php echo $value; ?></option>
<?php endforeach; ?>
In the add.ctp view of serviceRequests controller for add function, I have added following script at the last.
<div class="serviceRequests form">
<?php echo $this->Form->create('ServiceRequest'); ?>
<fieldset>
<legend><?php echo __('Add Service Request'); ?></legend>
<?php
echo $this->Form->input('customer_id');
echo $this->Form->input('customer_address_id');
echo $this->Form->input('status');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>
<?php
$this->Js->get('#ServiceRequestCustomerId')->event('change',
$this->Js->request(array(
'controller' => 'serviceRequests',
'action' => 'getCustomerAddress'
), array(
'update' => '#ServiceRequestCustomerAddressId',
'async' => true,
'method' => 'post',
'dataExpression' => true,
'data' => $this->Js->serializeForm(array(
'isForm' => true,
'inline' => true
))
))
);
?>
and to render Js, I have added following code to to last of default.ctp
<!-- script for layout -->
<?php echo $scripts_for_layout; ?>
<!-- Js writeBuffer -->
<?php
if(class_exists('JsHelper') && method_exists($this->Js, 'writeBuffer')) echo $this->Js->writeBuffer ();
// writes cached scripts
?>
But on accessing localhost/serviceRequests/add the ajax call is not working and all customer's name and all customer's addresses are showing in the list.
This is an example of how to implement chained selects with cake http://sandbox.dereuromark.de/sandbox/ajax_examples/chained_dropdowns
- the related article for that example is here http://www.dereuromark.de/2014/01/09/ajax-and-cakephp/
in controller
public function home($id=null){
$this->loadModel('Usermgmt.User');
if(isset($id)){
$groups=$this->User->findAllByuser_group_id($id);
$this->set('groups', $groups);
} else{
echo 'no id';
$users=$this->User->find('all');
$this->set('users', $users);
}
}
here i geeting value which matches the user_group_id and prints here i am geeting more then 10 users but i need to print only 5 on one page and need to give pagination how to give pagination here
view
<?php
if (!empty($groups)) {
// print_r($groups);
$sl=0;
foreach ($groups as $row1) {
//print_r($row1);
$sl++; ?>
<div style="width:100%;display:inline-block;">
<div style="float:left">
<?php
//echo $row1['id'];
echo $this->Html->link($this->Html->image('../files/user/photo/'.$row1 ['User']['photo_dir'].'/'.$row1 ['User']['photo'], array('width' => '180', 'height' => '180')),
array('controller'=>'Profiles','action'=>'index',$row1['User']['id']),
array('escape' => false));
?>
</div>
<div>
<?php echo h($row1['User']['first_name'])." ".h($row1['User']['last_name'])."</br>";
echo h($row1['User']['username'])."</br>";
echo h($row1['User']['email'])."</br>";
echo h($row1['User']['mobile'])."</br>";
echo h($row1['UserGroup']['name'])."</br>";
?></div>
<div style="clear:both;"></div>
</div>
<?php }
}?>
Call paginate
The equivalent paginate call to this:
$groups=$this->User->findAllByuser_group_id($id);
(incidentally - that should be findAllByUserGroupId) is this:
$groups = $this->paginate('User', array('user_group_id' => $id));
Changing default options
To achieve:
i need to print only 5 on one page
Modify the paginate property of your controller, e.g.:
class UsersController extends AppController {
public $paginate = array('limit' => 5);
function home($id = null) {
...
$conditions = array();
if ($id) {
$conditions['user_group_id'] = $id;
}
$groups = $this->paginate('User', $conditions);
...
}
}
View Modifications
In your view, the pagination helper, and the pagination information will automatically be available by calling paginate as shown above. To get pagination links use the pagination helper:
echo $this->Paginator->numbers();
See the documentation for more information and examples of using pagination.
As in cakephp pagination can be done using pagination helper of cakephp
In controller action use $this->paginate . From Model return all parameters like fields, conditions and so on in array format , so now in controller you will write
$data = $this->ModelName->functionname();
$currentPage = isset($_REQUEST['currentpage']) ? $_REQUEST['currentpage'] : '';
$this->paginate = array(
'fields' => $data['fields'],
'conditions' => $data['conditions'],
'order' => $data['order'],
'page' => $currentPage,
'limit' => 25
);
$currentPage is fetched from $_REQUEST['currentpage'];
and finally pass this data to Paginate Helper
$data = $this->paginate('ModelName');
Now in view you will use Pagination functions as shown below
<?php echo $this->Paginator->prev('revious'); ?>
<?php echo $this->Paginator->numbers(); ?>
<?php echo $this->Paginator->next('Next'); ?>
I have 2 views, postview.ctp and usercomment.ctp, calling the same comment.ctp element. This element shows image using UploadPack helper. But image on usercomment.ctp doesn't show and has this error message
Notice (8): Undefined index: User [APP\Plugin\upload_pack\Model\Behavior\UploadBehavior.php, line 222]
line 222: $settings = self::$__settings[$modelName][$field];
The self::$__settings in usercomment.ctp is empty , but in postview.ctp it's not empty and the image showed up correctly.
comment.ctp:
<?php echo $this->Html->link($this->upload->image(
$comment['User'],
'User.avatar',
array('style' => 'thumb'),
array('class' => array('img-responsive', 'img-rounded'))
),
array('controller' => 'users',
'action' => 'view',
$comment['User']['id']),
array('escape' => false)
) ?>
And this is code to call comment.ctp on from the both view.
<?php if (!empty($comments)): ?>
<?php foreach ($comments as $comment): ?>
<?php echo $this->element('comment',array('comment' => $comment));?>
<?php endforeach; ?>
<?php endif; ?>
I've checked the $comment array and they're identical. How to fix it?
Load User model on usercomment action in Comment controller.
public function usercomments($id) {
$this->loadModel('User');
if($this->Auth->loggedIn()){
.....
still a novice, but I am fighting with the paginator to limit my view to 10 records [properties] and to sort it on a field in the properties model. What am I doing wrong or miss in my code to get the paginator to control my view???
I have 2 models, Regions and Properties, a region has many properties, for example, my view is /region/view/13 This shows all properties for region 13.
The paginator is displaying the correct amount of properties, set the pages correct and all seems correct, but the paginator is not limiting my view, it just displays all properties by that region in one huge list instead of limit the view to 10 per page.
The sort per sleeps doesn't work either although the url in the browser seems to be ok.
/regions/view/13/sort:sleeps/direction:asc
/regions/view/13/sort:sleeps/direction:desc
Model:
<?php
App::uses('AppModel', 'Model');
/**
* Region Model
*
* #property Country $Country
* #property Property $Property
*/
class Region extends AppModel {
/**
* Display field
*
* #var string
*/
public $displayField = 'regionname';
/**
* belongsTo associations
*
* #var array
*/
public $belongsTo = array(
'Country' => array(
'className' => 'Country',
'foreignKey' => 'country_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
/**
* hasMany associations
*
* #var array
*/
public $hasMany = array(
'Property' => array(
'className' => 'Property',
'foreignKey' => 'region_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
}
Controller:
public function view($id = null) {
if (!$this->Region->exists($id)) {
throw new NotFoundException(__('Invalid region'));
}
$this->Region->recursive = 2; // related to associated model data, Region -> Properties -> PropertyImages
$options = array('conditions' => array('Region.' . $this->Region->primaryKey => $id));
$total = $this->Region->Property->find('count', array(
'conditions' => array('Property.region_id' => $id)
));
$this->set('total', $total); // Push to counter the view.
$this->set('region', $this->Region->find('first', $options)); // Push the properties to the view.
$this->paginate = array(
'limit' => 10,
'conditions' => array('Property.region_id' => $id),
);
$this->Region->Property->virtualFields['sleeps'] = 'Property.sleeps';
$this->set('regions', $this->paginate('Property'));
}
View:
<div class="paging">
<?php
echo $this->Paginator->prev('< ' . __('previous'), array(), null, array('class' => 'prev disabled'));
echo $this->Paginator->numbers(array('separator' => ''));
echo $this->Paginator->next(__('next') . ' >', array(), null, array('class' => 'next disabled')); ?>
</div>
<br>
<?php
echo $this->Paginator->counter(array(
'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}'))); ?><br>
Total properties: <?php echo $total . "\n"; ?><br>
Sort by: <?php echo $this->Paginator->sort('sleeps'); ?>
<?php if (!empty($region['Property'])): ?>
<div class="regionviewfooter"></div>
<?php
$i = 0;
foreach ($region['Property'] as $property): ?>
<!-- We only need 1 image to show up -->
<?php foreach ($property['PropertyImage'] as $key =>$propertyImage): ?>
<div class="regionview">
<div class="regionviewleft">
<?php echo '<span style="font-size:12px;line-height:18px;font-weight:bold;">'; echo $this->Html->link(__($property['description']), array('controller' => 'properties', 'action' => 'view', $property['id'])); echo '</span>'; ?>
<div class="regionviewheader">Sleeps <?php echo $property['sleeps']; echo ' :: ' ?>
<?php
if ($property['minPrice'] == 0) {
echo 'Please call for prices';
} else {
echo 'Prices from ';
echo $this->Number->currency($property['minPrice'], 'GBP');
if ($property['maxPrice'] == 0) {
echo ' PW';
} else {
echo ' - ';
echo $this->Number->currency($property['maxPrice'], 'GBP');
echo ' PW';
}
}
echo '<span style="font-size:11px;line-height:18px;font-weight:normal;">'; echo ' :: ';
echo $this->Html->link(__('View Property'), array('controller' => 'properties', 'action' => 'view', $property['id'])); echo '</span>'; ?>
</div>
<?php echo ($property['shortDesc']); ?><br>
Add to my Enquiry List :: Property Ref. (<?php echo strtoupper($property['ref']); ?>)
</div>
<div class="regionviewright">
<!-- display image -->
<?php echo $this->Html->image(($propertyImage['filename']), array('alt' => ($propertyImage['description']),'width' => '150' ,'height' => '77')); $key ?>
<?php $key++; ?>
</div>
</div>
<div class="clear"></div>
<div class="regionviewfooter"></div>
<?php if ($key == 1) {
break; // Stop, we did 1 image.
}
?>
<?php endforeach; ?>
<?php endforeach; ?>
<?php endif; ?>
<br>Top of Page<br><br>
You're setting your paginated results to $regions, yet in your view, you're looping through and displaying $region (singular), which is a straight-up find() above, with recursive 2, which will pull all properties.
So - although there are many other things that need cleaned up with your code, for now, just use $regions (plural) instead of $region singular in your View.