Cakephp Association Property belongs to Image but also has many images - cakephp

I am currently trying to solve a problem which I just noticed since the property didn't actually have a main_image allocated to it.
But as soon as I allocated a main image to it. The Related images caused problems.
Property table has a belongsTo relation
public $belongsTo = array( 'Image' => array(
'className' => 'Image',
'foreignKey' => 'main_image_id'
));
and also a hasMany
public $hasMany = array(
'Image' => array(
'className' => 'Image',
'foreignKey' => 'property_id'
)
);
the problem is when I am populating the related images I am receiving multiple errors similar to the below
Illegal string offset 'id'
my data is like so
property(array)
Image(array)
id1
descriptionPainted Brick Design
imageuploads/properties/3/Amazing-Painted-Brick-Houses-Design.jpeg
property_id3
0(array)
id1
descriptionPainted Brick Design
imageuploads/properties/3/Amazing-Painted-Brick-Houses-Design.jpeg
property_id3
and the view was generated like so
<div class="related">
<h3><?php echo __('Related Images'); ?></h3>
<?php if (!empty($property['Image'])): ?>
<table cellpadding = "0" cellspacing = "0">
<tr>
<th><?php echo __('Id'); ?></th>
<th><?php echo __('Description'); ?></th>
<th><?php echo __('Image'); ?></th>
<th><?php echo __('Property Id'); ?></th>
<th class="actions"><?php echo __('Actions'); ?></th>
</tr>
<?php foreach ($property['Image'] as $image): ?>
<tr>
<td><?php echo $image['id']; ?></td>
<td><?php echo $image['description']; ?></td>
<td><?php echo $image['image']; ?></td>
<td><?php echo $image['property_id']; ?></td>
<td class="actions">
<?php echo $this->Html->link(__('View'), array('controller' => 'images', 'action' => 'view', $image['id'])); ?>
<?php echo $this->Html->link(__('Edit'), array('controller' => 'images', 'action' => 'edit', $image['id'])); ?>
<?php echo $this->Form->postLink(__('Delete'), array('controller' => 'images', 'action' => 'delete', $image['id']), null, __('Are you sure you want to delete # %s?', $image['id'])); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<?php endif; ?>
<div class="actions">
<ul>
<li><?php echo $this->Html->link(__('New Image'), array('controller' => 'images', 'action' => 'add')); ?> </li>
</ul>
</div>
</div>
I am not sure if maybe the relations are setup incorrectly or that maybe I would have to include an if to see if there is data before the array and then implement a for loop.

I will answer it rather then comment. You will get all the properties and their main image like this (place this in your controller action eg. index()):
$properties= $this->Property->find('all', array(
'contain' => array(
'Image' => array(
'conditions' => array(
'main_image' => true
)
)
)
));
$this->set('properties', $properties);
and in your view:
<img src='<?php echo '/realestateagencyadministration/img/' . $property['Image'][0]['main_image'] ?>' style='max-width: 100%;height:150px;;'>
Don't take my for sure on this last one, I am wrinting this out of my head, I think you need [0], but you can easily fix that.

Related

Order by in find() cakephp

Table Unit(id, unitNo, summary).
id | unitNo
1 | 23
2 | 25
3 | 22
In UnitsController:
public function index() {
$this->set('units', $this->Unit->find('all'), array(
'order' => array('Unit.unitNo ASC'),
'fields' => array('Unit.id', 'Unit.unitNo'))
);
}
index.ctp
<table>
<tr>
<th>Unit</th>
<th>Summary</th>
</tr>
<!-- Here is where we loop through our $posts array, printing out post info -->
<?php foreach ($units as $unit): ?>
<tr>
<td>
<?php echo $this->Html->link($unit['Unit']['unitNo'], array('controller' => 'units', 'action' => 'view', $unit['Unit']['id']));
?>
</td>
<td><?php echo $unit['Unit']['summary']; ?></td>
</tr>
<?php endforeach; ?>
<?php unset($unit); ?>
</table>
I want to use order unitNo but the result is still ordering by id.
http://s1104.photobucket.com/user/thai92hp/media/Untitled.png.html
Can anyone help me to fix this problem?
Please give this a try:
public function index() {
$this->set('units', $this->Unit->find('all',
array(
'order' => array('Unit.unitNo ASC'),
'fields' => array('Unit.id', 'Unit.unitNo')
)
));
}
It seems to me that you've given your order settings to $this->set() as the third parameter but what you may want to do is to give it to $this->Unit->find() as the second parameter.

cake php views from belongsTo association

i have two tables with the following columns, guardians(id,student_no) and student(id,admission_no). student_no is foreign to admision_no. students has a hasMany association with guardians, guardians has a belongsTo association with students.
here are my models
STUDENT
public $hasMany = array(
'Guardian' => array(
'className' => 'Guardian',
'foreignKey' => 'student_no',
'dependent' => true,
)
)
GUARDIAN
public $belongsTo = array(
'Student' => array(
'className' => 'Student',
'foreignKey' => 'student_no',
)
)
Guardian controller
public function view($id = null) {
if (!$this->Guardian->exists($id)) {
throw new NotFoundException(__('Invalid guardian'));
}
$options = array('conditions' => array('Guardian.' . $this->Guardian->primaryKey => $id));
$this->set('guardian', $this->Guardian->find('first', $options));
}
Guardian view.ctp
(truncated to view only the associated student from within the Guardian model)
<h3><?php echo __('Associated Students'); ?></h3>
<?php if (!empty($guardian['Student'])): ?>
<table cellpadding = "0" cellspacing = "0">
<tr>
<th><?php echo __('Admission No'); ?></th>
<th><?php echo __('First Name'); ?></th>
<th><?php echo __('Last Name'); ?></th>
<th><?php echo __('Gender'); ?></th>
<th><?php echo __('Date Of Birth'); ?></th>
<th><?php echo __('Join Date'); ?></th>
<th><?php echo __('Form'); ?></th>
<th><?php echo __('Student Class'); ?></th>
<th><?php echo __('Middle Name'); ?></th>
<th class="actions"><?php echo __('Actions'); ?></th>
</tr>
<?php foreach ($guardian['Student'] as $student): ?>
<tr>`
<td><?php echo $student['admission_no']; ?></td>
line(115) <td><?php echo $student['first_name']; ?></td>
<td><?php echo $student['last_name']; ?></td>
<td><?php echo $student['gender']; ?></td>
<td><?php echo $student['date_of_birth']; ?></td>
<td><?php echo $student['join_date']; ?></td>
<td><?php echo $student['form']; ?></td>
<td><?php echo $student['student_class']; ?></td>
<td><?php echo $student['middle_name']; ?></td>
</tr>
<?php endforeach; ?>
</table>
i can view associated parent details from students view with above similar code,
however in guardians view i get error for the associated guardian
ERROR:Warning (2): Illegal string offset 'first_name' [APP/View/Guardians/view.ctp, line 115]
and for three lines below it.what exactly is going wrong
Do some debugging: debug($guardian)
In your belongsTo assocaition, a guardian can only have a single student, so you are iterating over the columns of that one single student, ie consequently the $student variable will be a string, hence the error.
See also Cookbook > Models > Associations > belongsTo

Cake PHP Pagination changes to limit records per page

I have the following code in my calls/index.ctp. At the moment it is showing all records in one page. I want to limit 20 records per page. When I baked the project, the pagination was provided, but I'm still a beginner and doesn't know how to change the pagination. Can someone please help?
calls/index.ctp:
<div class="callsIndex">
<h2><?php echo __('Call Details'); ?> </h2>
<div class="bottomButtonnew"><?php echo $this->Html->link(__('Add Calls'), array('action' => 'add')); ?></div>
<table cellpadding="0" cellspacing="0">
<tr>
<th><?php echo $this->Paginator->sort('Call Date'); ?></th>
<th><?php echo $this->Paginator->sort('Call Time'); ?></th>
<th><?php echo $this->Paginator->sort('Comments'); ?></th>
<th><?php echo $this->Paginator->sort('Next Call Date'); ?></th>
<th><?php echo $this->Paginator->sort('Customer Name'); ?></th>
<th><?php echo $this->Paginator->sort('Company Name'); ?></th>
<th><?php echo $this->Paginator->sort('Employee Name'); ?></th>
<th class="actions"><?php echo __(''); ?></th>
</tr>
<?php foreach ($calls as $call): ?>
<tr>
<td><?php echo date("d-m-Y", strtotime($call['Call']['call_date'])); ?> </td>
<td><?php echo h($call['Call']['call_time']); ?> </td>
<td><?php echo h($call['Call']['comments']); ?> </td>
<td><?php echo date("d-m-Y", strtotime($call['Call']['next_call_date'])); ?> </td>
<td>
<?php echo $this->Html->link($call['Customers']['customer_name'], array('controller' => 'customers', 'action' => 'view', $call['Customers']['id'])); ?>
</td>
<td>
<?php echo $this->Html->link($call['Companies']['company_name'], array('controller' => 'companies', 'action' => 'view', $call['Companies']['id'])); ?>
</td>
<td>
<?php echo $this->Html->link($call['Employees']['employee_name'], array('controller' => 'employees', 'action' => 'view', $call['Employees']['id'])); ?>
</td>
<td class="actions">
<?php echo $this->Html->link(__('View'), array('action' => 'view', $call['Call']['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')
));
?> </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>
<br>
</div>
callsController:
<?php
App::uses('AppController', 'Controller');
class CallsController extends AppController {
public $components = array('Paginator');
public $paginate = array(
'limit' => 10
);
public function index() {
$userid=$this->Session->read('User.userid');
if(isset($userid)&&$userid!=null)
{
$this->Call->recursive = 0;
$this->set('calls', $this->Paginator->paginate());
$result=$this->Call->getcalls($userid);
$this->set('result', $result);
}
else{
$this->set('loggedout',"loggedout");
$this->render("../Pages/home");
$this->layout = '../Pages/home';
}
}
//some code
}
You can do it easily by using pagination component.You should do it in your AppController.In your AppController you can type below code
Public $components =array('paginator');
public function beforeFilter()
{
parent::beforeFilter();
$this->Paginator->settings=array(
'limit'=>10
);
}
Than in you index method just change this line
$this->set('calls', $this->Paginator->paginate());
I think that will work fine now.This code will work for all controller.But if you want to change this only your CallsController. Do this code.
<?php
App::uses('AppController', 'Controller');
class CallsController extends AppController {
public $components = array('Paginator');
public function index() {
$this->Paginator->settings = array(
'limit' => 10
);
$userid=$this->Session->read('User.userid');
if(isset($userid)&&$userid!=null)
{
$this->Call->recursive = 0;
$this->set('calls', $this->Paginator->paginate());
$result=$this->Call->getcalls($userid);
$this->set('result', $result);
}
else{
$this->set('loggedout',"loggedout");
$this->render("../Pages/home");
$this->layout = '../Pages/home';
}
}
//some code
}
Note : There is two way to apply pagination one is by using component another is in controller.
The correct call in your example should be like this:
$this->set('calls', $this->paginate());
So your code is:
<?php
App::uses('AppController', 'Controller');
class CallsController extends AppController {
public $components = array('Paginator');
public $paginate = array(
'limit' => 10 //Here can you change the default limit
);
public function index() {
$userid=$this->Session->read('User.userid');
if(isset($userid)&&$userid!=null)
{
$this->Call->recursive = 0;
$this->set('calls', $this->paginate());
$result=$this->Call->getcalls($userid);
$this->set('result', $result);
}
else{
$this->set('loggedout',"loggedout");
$this->render("../Pages/home");
$this->layout = '../Pages/home';
}
}
//some code
}
<?php
App::uses('AppController', 'Controller');
class CallsController extends AppController {
public $components = array('Paginator');
public $paginate = array(
'limit' => 20
);
}

How to add posts to homepage cakephp?

I'm new to cakephp. So I want to ask you, how to add posts to homepage.
I created posts by this tutorial http://book.cakephp.org/2.0/en/getting-started.html#blog-tutorial
What should I do next?
I tried to google it, but nothing works.
Thanks.
home.ctp
<h1>Blog posts</h1>
<table>
<tr>
<th>Id</th>
<th>Title</th>
<th>Created</th>
</tr>
<!-- Here is where we loop through our $posts array, printing out post info -->
<?php foreach ($posts as $post): ?>
<tr>
<td><?php echo $post['Post']['id']; ?></td>
<td>
<?php echo $this->Html->link($post['Post']['title'],
array('controller' => 'posts', 'action' => 'view', $post['Post']['id'])); ?>
</td>
<td><?php echo $post['Post']['created']; ?></td>
</tr>
<?php endforeach; ?>
<?php unset($post); ?>
</table>
You have to redirect your homepage to the index() of PostsController.
Go to your routes.php file and change this line:
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
for this one:
Router::connect('/', array('controller' => 'posts', 'action' => 'index'));
(assuming that your index() actually contain a list of all your posts)
Router::connect will catch when an user attempt to go to the url on the first parameter, and will redirect it to the action in the controller on the second parameter

CakePHP 2 How to pass variables through the URL when using pagination?

I have a project in CakePHP application and I want to add pagination to it. I have added pagination to it, but when I click on a page number or go to the next page my application breaks.
The page relies on variables being passed to the controller in order to display the correct data. Here is my code for the view:
<table class="table table-striped">
<thead>
<tr>
<th>Job ID</th>
<th>Date</th>
<th>Site</th>
<th> </th>
</tr>
</thead>
<tbody>
<?php foreach ($data as $jobsheet) { ?>
<tr>
<td>
<?php echo $jobsheet['Jobsheet']['jobnum']; ?>
</td>
<td>
<?php echo date("l, jS F Y", strtotime($jobsheet['Jobsheet']['jobdate'])); ?>
</td>
<td>
<span class="companyname"><strong><?php echo $jobsheet['Siteaddress']['sitename'] ?></strong></span><br />
<?php echo $jobsheet['Siteaddress']['addressline1']; ?>,
<?php echo $jobsheet['Siteaddress']['addressline2']; ?>,
<?php if ( $jobsheet['Siteaddress']['addressline3'] = '') { ?>
<?php echo $jobsheet['Siteaddress']['addressline3']; ?>,
<?php } else { ?>
<?php } ?>
<?php echo $jobsheet['Siteaddress']['city']; ?>,
<?php echo $jobsheet['Siteaddress']['county']; ?>,
<?php echo $jobsheet['Siteaddress']['country']; ?>,
<?php echo $jobsheet['Siteaddress']['postcode']; ?>
</td>
<td><a data-toggle="modal" href="#viewjobsheet<?php echo $jobsheet['Jobsheet']['id']; ?>" onClick="document.getElementById('jbif<?php echo $jobsheet['Jobsheet']['id']; ?>').src='/modal/customers/<?php echo $company['Company']['id']; ?>/jobs/<?php echo $jobsheet['Jobsheet']['id']; ?>/view/';" title="View" class="icon-eye-open"></a>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="controls">
<?php echo $this->Paginator->prev('« Previous', null, null, array('class' => 'disabled')); ?>
<?php echo $this->Paginator->numbers(); ?>
<?php echo $this->Paginator->next('Next »', null, null, array('class' => 'disabled')); ?>
<br />
<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}'
));
?>
</div>
</div>
This is the controller:
function index(){
$companyid = $this->params['customer'];
$this->set('companyid', $companyid);
$siteid = $this->params['site'];
$this->loadModel('Jobsheet');
// Job Sheets
$jobsheets = $this->Jobsheet->find('all', array('conditions' => array('Jobsheet.company' => $companyid), 'recursive' => 2, 'order' => 'Jobsheet.jobdate DESC', 'limit' => '10'));
$this->set('jobsheets', $jobsheets);
$this->paginate = array(
'limit' => 10
);
$data = $this->paginate('Jobsheet');
$this->set(compact('data'));
}
While the pagination does work, it ends up loosing the variable and this breaks what I'm trying to do. What am i missing?
One method is to use PaginatorHelper::options (see the API)
For example, say we want to pass the variable $pass between Paginator page changes. So first pass the variable to the View.
public function index() {
$pass = 'testString';
$this->set(compact('pass'));
$this->set('posts', $this->paginate());
}
In the View, we can then add this to the parameters that Paginator passes when changing pages using Paginator::options and the url option.
<?php
$this->Paginator->options(array(
'url' => array(
'pass' => $pass
)
));
?>
So if you moved from page 1 to page 2, the resulting url would be something similar to:
http://localhost/cake/posts/index/pass:testString/page:2
This is also how Paginator passes sort orders and sort keys. So while "pass" in pass:testString can be anything you want, be sure not to use sort, direction, and page.
As long as you are changing pages through the Paginator links, the passed variables will remain. Note that you can access the values of the passed arguments in both the View and the Controller by the property:
$this->passedArgs

Resources