CakePHP Find Related Data - cakephp

My Gallery model is related to my image model, but when I retrive images from galleries_controller I cant see any result and instead see this error:
Warning (2): Invalid argument supplied for foreach() [APP\views\galleries\view.ctp, line 35]
Here is the code from my controller action:
function view($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid gallery', true));
$this->redirect(array('action' => 'index'));
}
$this->set('gallery', $this->Gallery->read(null,$id));
$this->Gallery->Image->find('all',array('conditions' => array('Image.gallery_id'=> $id)));
$this->set('images', $images);
}
This is the loop I have in my galleries/view to iterate through the array.
<?php
$i = 0;
foreach ($images['Image'] as $image):
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}
?>
<tr<?php echo $class;?>>
<td><?php $image['id'] ;?></td>
<td><?php echo $image['name'];?></td>
<!--<td><?php echo $image['img_file'];?></td>-->
<td><?php echo $html->image('uploads' . DS . 'images' . DS . $image['img_file'], array('alt' => 'Gallery Image')); ?></td>
</tr>
<?php endforeach; ?>

You aren't setting anything with your set. Your find is being executed and then not stored in a variable. Furthermore, your view loop is iterating through incorrectly.
Change your controller to:
function view($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid gallery', true));
$this->redirect(array('action' => 'index'));
}
$this->set('gallery', $this->Gallery->read(null,$id));
$images = $this->Gallery->Image->find('all',array('conditions' => array('Image.gallery_id'=> $id)));
$this->set('images', $images);
}
And your view code to:
<?php
$i = 0;
foreach ($images as $image):
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}
?>
<tr<?php echo $class;?>>
<td><?php $image['Image']['id'] ;?></td>
<td><?php echo $image['Image']['name'];?></td>
<!--<td><?php echo $image['Image']['img_file'];?></td>-->
<td><?php echo $html->image('uploads' . DS . 'images' . DS . $image['Image']['img_file'], array('alt' => 'Gallery Image')); ?></td>
</tr>
<?php endforeach; ?>
That having been said, since all you want to do is pull in associated images when a gallery is viewed, you should look into setting up your model associations and then doing a find on your gallery that will include the images you want like so:
$this->set('gallery',$this->Gallery->find('first', array('conditions' => array('Gallery.id' => $id), 'recursive' => 1));
If the above don't work, then there is something misconfigured in your models. Please post your model code so we can investigate further.

Related

Cakephp application form

I created an application form using cakephp 2.
Now I want to know, How can users view only their application details using their user id. Here is the Form controller, the application form and the table for displaying the form
//Form controller
public function index() {
$this->set('posts', $this->Post->find('all'));
}
public function view($id = null) {
if (!$id) {
throw new NotFoundException(__('Invalid post'));
}
$post = $this->Post->findById($id);
if (!$post) {
throw new NotFoundException(__('Invalid post'));
}
$this->set('post', $post);
}
public function add() {
if ($this->request->is('post')) {
$this->Post->create();
if ($this->Post->save($this->request->data)) {
$this->Flash->success(__('Your post has been saved.'));
return $this->redirect(array('action' => 'index'));
}
$this->Flash->error(__('Unable to add your post.'));
}
}
//Create form
echo $this->Form->create('Post');
echo $this->Form->input('esta',['label'=>'New or Estabilished']);
echo $this->Form->end('Save Post');
//Form display
<table>
<tr>
<th>Id</th>
<th>Title</th>
<th>Created</th>
</tr>
<?php foreach ($posts as $post): ?>
<tr>
<td><?php echo $post['Post']['id']; ?></td>
<td>
<?php echo $this->Html->link($post['Post']['describe_idea'],
array('controller' => 'posts', 'action' => 'view', $post['Post']['id'])); ?>
</td>
<td><?php echo $post['Post']['created']; ?></td>
</tr>
<?php endforeach; ?>
<?php unset($post); ?>
</table>
You said that you are using cakephp 2.x please find below code to find record
for Single Record
$posts = $this->Post->find('first', array(
'conditions' => array('id' => 1)
));
For Multiple record
$posts = $this->Post->find('all', array(
'conditions' => array('id' => 1)
));
Add filter in your action
CakePHP 3.x
$posts = $this->Posts->find()
->where([
'Posts.user_id' => $this->Auth->user('id')
]);
CakePHP 2.x
$posts = $this->Posts->find('all', [
'user_id' => $this->Auth->user('id')
]);
Note: Make sure to login user to set Auth data.

edit 2 models with one view and controller cakephp

I have 2 models. Typology and TypologyPicture. and 2 controllers Typologies and TypologyPictures. I want to edit both typology and typologyPcture from one controller.
<?php echo $this->Form->create('TypologyPicture', array('type'=>'file')); ?>
<legend><?php echo __('Edit Typology Picture'); ?></legend>
<?php echo $this->Form->input('id'); ?>
<!-- Here is the first part for the update Typolohgy -->
<?php echo $this->Form->input('Typology.item_id',array('empty'=>true)); ?>
<?php echo $this->Form->input('Typology.title'); ?>
<?php echo $this->Form->input('Typology.description');?>
<?php echo $this->Form->input('Typology.thumbnail',array('type'=>'file')); ?>
<?php echo $this->Form->input('Typology.typology_category_id',array('empty'=>true)); ?>
<?php echo $this->Form->input('Typology.typology_condition_id',array('empty'=>true)); ?>
<?php echo $this->Form->input('Typology.price',array('placeholder'=>'Price')); ?>
<!-- Here is the second part for the update Typpology Picture -->
<?php echo $this->Form->input('pic_path', array('label'=>'Picture','type'=>'file')); ?>
<?php echo $this->Form->end(__('Submit')); ?>
This is the view. which contain the field for typology (item_id|title|description|thumbnial|typology_category_id|typology_condition_id)
and the field for typologypictures (pic_path)
The controller (that is at TypologyPicturesController) is:
public function edit($id = null) {
if (!$this->TypologyPicture->exists($id)) {
throw new NotFoundException(__('Invalid typology picture'));
}
if ($this->request->is(array('post', 'put'))) {
if(empty($this->data['TypologyPicture']['pic_path']['name'])){
unset($this->request->data['TypologyPicture']['pic_path']);
}
if ($this->TypologyPicture->saveAll($this->request->data)) {
$this->Session->setFlash(__('The typology picture has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The typology picture could not be saved. Please, try again.'));
}
} else {
$options = array('conditions' => array('TypologyPicture.' . $this->TypologyPicture->primaryKey => $id));
$this->request->data = $this->TypologyPicture->find('first', $options);
$opt = array('conditions' => array('Typology.id' => $this->request->data['TypologyPicture']['typology_id']));
$this->request->data = $this->Typology->find('first', $opt);
}
if ( AuthComponent::user('role')==='admin' ||AuthComponent::user('role')==='superadmin' ){ //if the user is admin or superadmin, show all on dropdown
$items = $this->Typology->TypologyItem->find('list');
} else {// else if the user is author, show only item created by him.
$items = $this->Typology->TypologyItem->find('list', array('conditions' => array('TypologyItem.user_id' => AuthComponent::user('id'))));
}
$typologyCategories = $this->Typology->TypologyCategory->find('list');
$typologyConditions = $this->Typology->TypologyCondition->find('list');
$users = $this->Typology->TypologyUser->find('list');
$this->set(compact('items', 'typologyCategories', 'typologyConditions', 'users'));
if ( AuthComponent::user('role')==='admin' ||AuthComponent::user('role')==='superadmin' ){
$typologies = $this->TypologyPicture->ItemTypologyPicture->find('list');
} else {
$typologies = $this->TypologyPicture->ItemTypologyPicture->find('list', array('conditions' => array('ItemTypologyPicture.user_id' => AuthComponent::user('id'))));
}
$this->set(compact('typologies'));
}
And when i try to edit, it opens the form, the fields are filled properly, but wheni press save there is new row inserted at typologyPicture and no change at all to Typology.
So what i want is that when the user press submit only the correspondings rows are updated and not to insert new rows.....

Edit 2 controller from one controller (Correct)

i have small problem so i need some help. maybe its very easy but i just need a push... so i am withing one controller
public function edit($id = null) {
if (!$this->TypologyPicture->exists($id)) {
throw new NotFoundException(__('Invalid typology picture'));
}
if ($this->request->is(array('post', 'put'))) {
if(empty($this->data['TypologyPicture']['pic_path']['name'])){
unset($this->request->data['TypologyPicture']['pic_path']);
}
if ($this->TypologyPicture->save($this->request->data)) {
$this->Session->setFlash(__('The typology picture has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The typology picture could not be saved. Please, try again.'));
}
} else {
$options = array('conditions' => array('TypologyPicture.' . $this->TypologyPicture->primaryKey => $id));
$this->request->data = $this->TypologyPicture->find('first', $options);
//$options1 = array('conditions' => array('Typology.id' => $id));
$opt = array('conditions' => array('Typology.id' => $this->request->data['TypologyPicture']['typology_id']));
$this->request->data = $this->Typology->find('first', $opt);
}
if ( AuthComponent::user('role')==='admin' ||AuthComponent::user('role')==='superadmin' ){ //if the user is admin or superadmin, show all on dropdown
$items = $this->Typology->TypologyItem->find('list');
} else {// else if the user is author, show only item created by him.
$items = $this->Typology->TypologyItem->find('list', array('conditions' => array('TypologyItem.user_id' => AuthComponent::user('id'))));
}
$typologyCategories = $this->Typology->TypologyCategory->find('list');
$typologyConditions = $this->Typology->TypologyCondition->find('list');
$users = $this->Typology->TypologyUser->find('list');
$this->set(compact('items', 'typologyCategories', 'typologyConditions', 'users'));
if ( AuthComponent::user('role')==='admin' ||AuthComponent::user('role')==='superadmin' ){
$typologies = $this->TypologyPicture->ItemTypologyPicture->find('list');
} else {
$typologies = $this->TypologyPicture->ItemTypologyPicture->find('list', array('conditions' => array('ItemTypologyPicture.user_id' => AuthComponent::user('id'))));
}
$this->set(compact('typologies'));
}
so as you see from contact controller i want to access the contact that i want to edit and its its pictures that are stored in contact_picture table. contact by itself has like an icon or an avatar, and in contact picture are stored the gallery. so here the problem is that i get all the data as it supposed to, but the image of the contact (avatar, or icon) doesent dispay, the path is retrived correctly but it just doesent display the image.
So what im asking is that if there is another way or easy way or even better way to do that i would really appruciate it...really.
Thanks in advance!
EDIT: The View Part:
<?php echo $this->Form->create('TypologyPicture', array('type'=>'file')); ?>
<legend><?php echo __('Edit Typology Picture'); ?></legend>
<?php
$dir = "/img/uploads/typology/images/";
echo $this->Form->input('id'); ?>
<?php echo $this->Form->input('Typology.item_id',array('empty'=>true)); ?>
<?php echo $this->Form->input('Typology.title'); ?>
<?php echo $this->Form->input('Typology.description');?>
<?php echo $this->Form->input('Typology.thumbnail',array('type'=>'file')); ?>
<?php echo $this->Form->input('Typology.typology_category_id',array('empty'=>true)); ?>
<?php echo $this->Form->input('Typology.typology_condition_id',array('empty'=>true)); ?>
<?php echo $this->Form->input('Typology.price',array('placeholder'=>'Price')); ?>
<!-- Here is the second part of the update -->
<?php echo $this->Form->input('pic_path', array('label'=>'Picture','type'=>'file'));
echo $this->Form->input('hiddenimage', array('type'=>'hidden','value'=> $this->Form->value('pic_path') ));
$Image = $this->Form->value( 'pic_path');
if(empty($Image) || $Image==NULL)
{$Image = "/img/uploads/noimg.jpg";}
else {$Image = $dir . $Image; }
echo $this->Html->image($Image,array('align'=>'absbottom','style'=>'max-height:100px'));
?>
<?php echo $this->Form->end(__('Submit')); ?>
So when i do echo to the image it doesent display correctly... if i remove the typology model part like a normal edit, it displays normal...
try by removing the img part from $dir and $Image;
$dir = "/img/uploads/typology/images/";
should be
$dir = "uploads/typology/images/";
and
{$Image = "/img/uploads/noimg.jpg";}
should be
{$Image = "uploads/noimg.jpg";}

Displaying HABTM data in view

I have a simple cakephp 2.x app that I baked using the bake script. The two main tables are conditions and drugs. A condition HABTM drugs and vice verca. I'm trying to display the drugs that belong to a condition in the condition index, basic listing all conditions, but ONLY those drugs. I have tried doing it like this, to display the drugs belonging to a condition in a comma seperated list, which works in another 1.3 app:
<?php
$condition_drugs = '';
foreach($condition['Drug'] as $drug):
$condition_drugs .= $drug['drug'] . ', ';
//echo $drug['generic'];
endforeach;
//echo substr($condition_drugs, 0, -2);
echo $condition_drugs;
?>
But it gives the following two errors:
Undefined index: Drug [APP/View/Conditions/index.ctp, line 22], and Invalid argument supplied for foreach() [APP/View/Conditions/index.ctp, line 22]
I also looked at another article here that suggested doing it in a similar way. Is there something wrong with the code I have? Do I need a find in my model based on the ID? Here's the full index view code and controller:
View:
<div class="conditions index">
<h2><?php echo __('Conditions'); ?></h2>
<table cellpadding="0" cellspacing="0">
<tr>
<th><?php echo $this->Paginator->sort('condition'); ?></th>
<th><?php echo $this->Paginator->sort('principles'); ?></th>
<th><?php echo $this->Paginator->sort('treatment'); ?></th>
<th><?php echo $this->Paginator->sort('clinical_tips'); ?></th>
<th>Drugs</th>
<th class="actions"><?php echo __('Actions'); ?></th>
</tr>
<?php
foreach ($conditions as $condition): ?>
<tr>
<td><?php echo h($condition['Condition']['condition']); ?> </td>
<td><?php echo h($condition['Condition']['principles']); ?> </td>
<td><?php echo h($condition['Condition']['treatment']); ?> </td>
<td><?php echo h($condition['Condition']['clinical_tips']); ?> </td>
<td>
<?php
$condition_drugs = '';
foreach($condition['Drug'] as $drug):
$condition_drugs .= $drug['drug'] . ', ';
//echo $drug['generic'];
endforeach;
//echo substr($condition_drugs, 0, -2);
echo $condition_drugs;
?>
</td>
<td class="actions">
<?php echo $this->Html->link(__('View'), array('action' => 'view', $condition['Condition']['id'])); ?>
<?php echo $this->Html->link(__('Edit'), array('action' => 'edit', $condition['Condition']['id'])); ?>
<?php echo $this->Form->postLink(__('Delete'), array('action' => 'delete', $condition['Condition']['id']), null, __('Are you sure you want to delete # %s?', $condition['Condition']['id'])); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<p>
<?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}')
));
?> </p>
<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>
</div>
<div class="actions">
<h3><?php echo __('Actions'); ?></h3>
<ul>
<li><?php echo $this->Html->link(__('New Condition'), array('action' => 'add')); ?></li>
</ul>
</div>
Controller:
<?php
App::uses('AppController', 'Controller');
/**
* Conditions Controller
*
* #property Condition $Condition
*/
class ConditionsController extends AppController {
/**
* index method
*
* #return void
*/
public function index() {
$this->set('title_for_layout','Condition Index');
$this->Condition->recursive = 0;
$this->set('conditions', $this->paginate());
}
/**
* view method
*
* #throws NotFoundException
* #param string $id
* #return void
*/
public function view($id = null) {
$this->Condition->id = $id;
if (!$this->Condition->exists()) {
throw new NotFoundException(__('Invalid condition'));
}
$this->set('condition', $this->Condition->read(null, $id));
}
/**
* add method
*
* #return void
*/
public function add() {
if ($this->request->is('post')) {
$this->Condition->create();
if ($this->Condition->save($this->request->data)) {
$this->Session->setFlash(__('The condition has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The condition could not be saved. Please, try again.'));
}
}
$drugs = $this->Condition->Drug->find('list',array('fields'=>array('id','generic')));
$this->set(compact('drugs'));
}
/**
* edit method
*
* #throws NotFoundException
* #param string $id
* #return void
*/
public function edit($id = null) {
$this->Condition->id = $id;
if (!$this->Condition->exists()) {
throw new NotFoundException(__('Invalid condition'));
}
if ($this->request->is('post') || $this->request->is('put')) {
if ($this->Condition->save($this->request->data)) {
$this->Session->setFlash(__('The condition has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The condition could not be saved. Please, try again.'));
}
} else {
$this->request->data = $this->Condition->read(null, $id);
}
$drugs = $this->Condition->Drug->find('list',array('fields'=>array('id','generic')));
$this->set(compact('drugs'));
}
/**
* delete method
*
* #throws MethodNotAllowedException
* #throws NotFoundException
* #param string $id
* #return void
*/
public function delete($id = null) {
if (!$this->request->is('post')) {
throw new MethodNotAllowedException();
}
$this->Condition->id = $id;
if (!$this->Condition->exists()) {
throw new NotFoundException(__('Invalid condition'));
}
if ($this->Condition->delete()) {
$this->Session->setFlash(__('Condition deleted'));
$this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(__('Condition was not deleted'));
$this->redirect(array('action' => 'index'));
}
}
To include habtm data, you need $recursive = 1;
You have set it to 0

Updating specified rows in CakePHP using array of ID's?

This code is only updating one row (the one that matches the first in the array):
Edit: showing more code!
Here's my view. It's grabbing db entries based on an association (there's one model "clients" that has a one-to-many relationship with two other models, Programs and Users).
<div class="view">
<h2><?php echo h($program['Program']['title'])?></h1>
<?php echo $this->Form->create('User', array('action' => 'pushing')); ?>
<table id="pushTable">
<tr><th colspan="5">Select the athletes you would like to push this program to:</th></tr>
<tr>
<?php $i=0; ?>
<?php foreach ($clients['Players'] as $player) {?>
<?php if ($i == 0) {?><tr><?php } ?>
<td><?php echo $this->Form->checkbox($player['id']) . ' ' . $player['username'];?></td>
<?php if ($i == 4) {?></tr><?php $i = 0; } else { $i++; } ?>
<?php } ?>
</tr>
</table>
<?php echo $this->Form->end(__('Push')); ?>
</div>
In my Users controller:
public function pushing() {
if ($this->request->is('post') || $this->request->is('put')) {
$athletes = $this->request->data['User'];
foreach ( $athletes as $player => $flag){
if ($flag == 0){
unset($athletes[$player]);
}
}
$this->User->updateAll(
array('User.data' => "'foo'"),
array('User.id' => $athletes)
);
$this->Session->setFlash(__('Programs were pushed!'));
}
}
}
$athletes is the array is collected from checked boxes, and there seem to me no problems with that... so I'm not sure why the updateAll isn't iterating over each ID in the array...
Maybe it's not working for a db related reason? I'm developing on MAMP... maybe the db isn't set up for "atomic" stuff (only heard about that here today!).
I had previously tried using a foreach to loop over the id's, then in the foreach just did this (edit: more code!)
public function pushing() {
if ($this->request->is('post') || $this->request->is('put')) {
foreach ($this->request->data['User'] as $player => $flag) {
if ($flag) {
$this->User->id = $player; // set ID to player we want to save ($player is id that was suplpied in view to checkbox
$this->User->saveField('data', 'foo'); // then, push the data!
}
}
$this->Session->setFlash(__('Programs were pushed!'));
}
$this->autoRender = false;
$this->redirect(array('action' => 'index'));
}
But that caused weird results with redirection. No matter where I put redirection in that action, the save just wanted to do its own thing. That $this->autoRender did nothing. The controller still tried to resolve to the /pushing/ route
Give this a shot :)
In your view:
<div class="view">
<h2><?php echo h($program['Program']['title'])?></h1>
<?php echo $this->Form->create('User', array('action' => 'pushing')); ?>
<table id="pushTable">
<tr><th colspan="5">Select the athletes you would like to push this program to:</th></tr>
<tr>
<?php $i=0; ?>
<?php foreach ($clients['Players'] as $player) {?>
<?php if ($i == 0) {?><tr><?php } ?>
<td><?php echo $this->Form->input('Player.' . $player['id']. '.id', array('type' => 'checkbox', 'value' => $player['id'])) . ' ' . $player['username'];?></td>
<?php if ($i == 4) {?></tr><?php $i = 0; } else { $i++; } ?>
<?php } ?>
</tr>
</table>
<?php echo $this->Form->end(__('Push')); ?>
</div>
In your controller:
public function pushing() {
if ($this->request->is('post') || $this->request->is('put')) {
$athletes = $this->request->data['Player'];
$athlete_ids = array();
foreach($athletes as $a){
$athlete_ids[$a['id']] = $a['id'];
}
$this->User->updateAll(
array('User.data' => "'foo'"),
array('User.id' => $athlete_ids)
);
$this->Session->setFlash(__('Programs were pushed!'));
}
}
}
Hi had to change the code a bit to make it for work me..
$contactsids = array();
foreach($selected as $key => $val){
if(($val <> '') && ($val <> 0) ) {
$contactsids[$val] = $val;
}
}
$this->Contact->updateAll(
array('Contact.contact_category_id' => $category_id),
array('Contact.id' => $contactsids)
);

Resources