I don't know if I'm going the right way with the tree behavior but I'm trying to build a comment system for a blog. I would like to have an indentation of 5 level depth.
The generatetreelist method looks like it would be the fastest way to accomplish this but it doesn't look like you can add fields to the query. Am I right ? Is there a way to modify the method ?
Thanks
This is how I do it for categories. You could modify accordingly.
In controller:
$categories = $this->Category->generatetreelist(null,null,null,"|-- ");
$categories_array = array();
foreach($categories as $k => $v)
{
$categories_array[$k] = $this->Category->find('first', array('conditions' => array('Category.id' => $k)));
$categories_array[$k]["Category"]["path"] = $v;
}
$this->set(compact('categories','categories_array'));
In view:
<table>
<thead>
<tr>
<th><?php __('Id');?></th>
<th><?php __('Name');?></th>
<th><?php __('Status');?></th>
<th><?php __('Action');?></th>
</tr>
</thead>
<tbody>
<?php
$i = 0;
foreach ($categories_array AS $categoryId => $category):
$class = 'even';
if ($i++ % 2 == 0) {
$class = 'odd';
}?>
<tr class="<?php echo $class;?>">
<td><?php echo $category['Category']['id']; ?></td>
<td><?php echo $category["Category"]["path"];?></td>
<?php if ($category['Category']['status'] == '1'){
$published = 'Active';
}else {
$published = 'Inactive';
} ?>
<td><?php echo $published;?></td>
<td>
<?php echo $html->link($html->image("icons/16_icon_view.png"), array('action' => 'view', $category['Category']['id']), array('title'=>'View','escape' => false));?>
<?php echo $html->link($html->image("icons/16_icon_edit.png"), array('action' => 'edit', $category['Category']['id']), array('title'=>'Edit','escape' => false));?>
<?php echo $html->link($html->image("icons/16_icon_delete.png"), array('action' => 'delete', $category['Category']['id']), array('class'=>'delete_trigger','rel'=>'#error','title'=>'Delete','escape' => false));?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
If it was me, I would just do this in the result set. As you get a numeric array in the first dimension of the results you could use that when outputting the data to indent or add a class to your comments as you needed.
Related
Total n00b in CakePhp
Im trying to link to the view retrieved data from variable $status, defined in the controller, given the simple condition "done" or "pending".
Given the model:
<?php
class Task extends AppModel {
var $name = 'Task';
var $validate = array(
'title' => array(
'rule' => 'notEmpty',
'message' => 'Title of a task cannot be empty'
)
);
}?>
The Task Controller:
function index($status=null) {
if($status == 'done')
$tasks = $this->Task->find('all', array('conditions' => array('Task.done' => '1')));
else if($status == 'pending')
$tasks = $this->Task->find('all', array('conditions' => array('Task.done' => '0')));
else
$tasks = $this->set('Tasks', $this->Task->find('all'));
$this->set('tasks', $tasks);
$this->set('status', $status);
}
And finally The View:
<h2>Tasks</h2>
<?php if(empty($Tasks)): ?>
There are no tasks in this list
<?php else: ?>
<table>
<tr>
<th>Title</th>
<th>Status</th>
<th>Created</th>
<th>Modified</th>
<th>Actions</th>
</tr>
<?php foreach ($Tasks as $Task): ?>
<tr>
<td>
<?php echo $Task['Task']['title'] ?>
</td>
<td>
<?php
if($Task['Task']['done']) echo "Done";
else echo "Pending";
?>
</td>
<td>
<?php echo $Task['Task']['created'] ?>
</td>
<td>
<?php echo $Task['Task']['modified'] ?>
</td>
<td>
<?php echo $this->Html->link('Edit', array('action'=>'edit', $Task['Task']['id'])); ?>
<?php echo $this->Html->link('Delete', array('action'=>'delete', $Task['Task']['id']), null, 'Are you sure you want to delete this task?'); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<?php endif; ?>
<?php echo $this->Html->link('List Done Tasks', array('action'=>'index','done')); ?><br />
<?php echo $this->Html->link('List Pending Tasks', array('action'=>'index', 'pending')); ?><br />
Clicking the "Done Task" returns an empty list (There are no tasks in this list). Can anyone see what is wrong on the link? Thanks in advance!
You are mixing up the casing in the variable name $Tasks. In your example you are assigning the array to $tasks, but then in your view, your are trying to check a variable names $Tasks, which will turn up empty because it has never been properly set.
Change this line:
$this->set('tasks', $tasks);
To:
$this->set('Tasks', $tasks);
As mentioned by McWayWeb above to case of the variable is incorrect.
As you are setting lower case vars to use in your view i would make the change there. Change all counts of Task in the view to task.
I would also consider setting all viewVars at the same time using the below
$this->set(compact('tasks','status));
Im stuck with moving items of a tree up and down, the item is not being moved to the correct position.
Please check these pictures:
https://docs.google.com/a/wgs.co.id/file/d/0B88jB6a4wxkTdTNtTGl1YjhXdTQ/edit?usp=drivesdk
https://docs.google.com/a/wgs.co.id/file/d/0B88jB6a4wxkTcW5pSFJyUnVhejA/edit?usp=drivesdk
My code for moving items is based on http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::moveDown
Here is my code:
Controller
function admin_moveup($id = null, $delta = null) {
$this->ProductNeed->id = $id;
if (!$this->ProductNeed->exists()) {
throw new NotFoundException(__('Invalid id'));
}
if ($delta > 0) {
$this->ProductNeed->moveUp($this->ProductNeed->id, abs($delta));
} else {
$this->Session->setFlash(
'Silahkan tentukan posisi nomor order terlebih dahulu'
);
}
return $this->redirect(array('admin' => true, 'controller' => $this->params['controller'], 'action' => 'index'));
}
function admin_movedown($id = null, $delta = null) {
$this->ProductNeed->id = $id;
if (!$this->ProductNeed->exists()) {
throw new NotFoundException(__('Invalid id'));
}
if ($delta > 0) {
$this->ProductNeed->moveDown($this->ProductNeed->id, abs($delta));
} else {
$this->Session->setFlash(
'Silahkan tentukan posisi nomor order terlebih dahulu'
);
}
return $this->redirect(array('admin' => true, 'controller' => $this->params['controller'], 'action' => 'index'));
}
View
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>No</th>
<th>Name</th>
<th>Order</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php
if(!empty($data['rows'])) {
$i = 0;
foreach($data['rows'] as $key => $value) {
$i++;
?>
<tr id="row-<?php echo $i; ?>">
<td><?php echo $i; ?></td>
<td><?= $value ?></td>
<td>
<?php
echo $this->Html->link(
'Up',
'/admin/'.$this->params['controller'].'/moveup/'.$key.'/'.$i
);
?>
<?php
echo $this->Html->link(
'Down',
'/admin/'.$this->params['controller'].'/movedown/'.$key.'/'.$i
);
?>
</td>
<td>
<ul class="action">
<li><i class="glyphicon glyphicon-edit" data-toggle="tooltip" title="Ubah"></i></li>
<li><i class="glyphicon glyphicon-ban-circle" data-toggle="tooltip" title="Hapus"></i></li>
</ul>
<?= $html->modalBoxDelete($i, $key) ?>
</td>
</tr>
<?php
}
} else {
echo $html->noData(4);
}
?>
</tbody>
</table>
Re-read the docs that you've linked, the code takes a delta value, ie the numer of positions the item should be moved.
If you'd wanted to move an item by just one row, then you'll have to use a delta of 1, your view template code however passes the items index in the array as the delta value, so for the Kesehan Mata row in your example that would be a 4, hence the item is moved to after Stamina Vitalitas, which is 4 top level items ahead.
So either pass a static value of 1, like
'/admin/'.$this->params['controller'].'/moveup/'.$key.'/1'
'/admin/'.$this->params['controller'].'/movedown/'.$key.'/1'
or if you don't plan to ever move the items by more than 1, simply remove the delta argument alltogether and hardcode the value passed to TreeBehavior::up/down() in your controller methods.
How do I delete multiple rows by checking a checkbox?
I have a table of records, and I'd like to to delete multiple rows at once.
This is my my deleteselected function:
UPDATED
public function order() {
if(!empty($this->data)) {
//If at lesst 1 check box is selected
if (isset($this->data) && !empty($this->data['order_id'])) {
$selectedReferences = $this->data['order_id'];
$flagReferenceAdded = false;
foreach ($selectedReferences as $singleReference) {
//NEW DELETE
$this->Order->id = $singleReference;
$this->Order->delete();
//NEW DELETE
}
//After delete
$this->Session->setFlash(
__('Your All record Are deleted.')
);
return $this->redirect(array(''));
}
else{
echo "Select at least 1 ORDER.";
}
}
and in my view.
<?php
echo $this->Form->create('Order',array('url' => array('controller' => 'admin', 'action' => 'order'))); ?>
<table class="table table-bordered table-hover">
<th>Name</th>
<th>Email</th>
<th>phone</th>
<th>view</th>
<th>delete</th>
<thead>
</tr>
</thead>
<tbody>
<?php foreach ($order as $orders): ?>
<tr>
<td><?php echo $orders['Order']['varfullname']; ?></td>
<td><?php echo $orders['Order']['varemailid']; ?></td>
<td><?php echo $orders['Order']['varphone']; ?></td>
<td>
<?php echo $this->Html->link('',
array('controller' => 'orders', 'action' => 'view', $orders['Order']['id']), array('title'=>'VIEW','class' => 'fa fa-search'));?>
</td>
<td><input type="checkbox" name="order_id[]" value ="<?php echo $orders['Order']['id'];?>" hiddenField = "false">
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</br>
<?
echo $this->Form->end('Deleteselected'); ?>
</div>
</div>
</br>
</div>
<!-- /.row -->
after using below answer my delete selected working fine
Use in ctp
//in ctp Along with EACH record use Checkbox integration . Dont use Checkbox code u used.
<input type="checkbox" name="order_id[]" value ="<?php echo $referenceSingle['Order']['id'];?>" hiddenField = "false">
//In controller
if(!empty($this->data)) {
//If at lesst 1 check box is selected
if (isset($this->data) && !empty($this->data['order_id'])) {
$selectedReferences = $this->data['order_id'];
$flagReferenceAdded = false;
foreach ($selectedReferences as $singleReference) {
//NEW DELETE
$this->Order->id = $singleReference;
$this->Order->delete();
//NEW DELETE
}
//After delete
$this->Session->setFlash(
__('Your All record Are deleted.')
);
return $this->redirect(array(''));
}
else{
echo "Select at least 1 ORDER.";
}
}
UPDATE
Use Above Code in your Index method itself ,Dont create deleteAll method.
OR
Make <form action TO deleteAll
LIKE
echo $this->Form->create('searchCourse',array('url' => array('controller' => 'Courses', 'action' => 'index')));
UPDATE
For proper Workflow refer :
ALWAYS do paperwork and Algorithm ,Before Coding SIR.
I have 4 tables named customers, calls, employees and companies. Customers belong to a company and an employee. Calls belong to a customer and an employee. At the moment in my call index file it shows the relevant customer name and employee name. I want to display, for a call the relevant customer name, the customers company name they belong to and the employee name. I don't know how to display the relevant company name based on the customer. Can someone help? This is my code:
call/ index.ctp
<?php
$usertype=$this->SESSION->read('User.usertype');
?>
<div class="calls index">
<h2><?php echo __('Call Details'); ?> </h2>
<table cellpadding="0" cellspacing="0">
<tr>
<th><?php echo $this->Paginator->sort('id'); ?></th>
<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('Employee Name'); ?></th>
<th class="actions"><?php echo __(''); ?></th>
</tr>
<?php foreach ($calls as $call): ?>
<tr>
<td><?php echo h($call['Call']['id']); ?> </td>
<td><?php echo h($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 h($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['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>
callsController:
class CallsController extends AppController {
/**
* Components
*
* #var array
*/
public $components = array('Paginator');
/**
* index method
*
* #return void
*/
public function index() {
$this->Call->recursive = 0;
$this->set('calls', $this->Paginator->paginate());
}
/**
* view method
*
* #throws NotFoundException
* #param string $id
* #return void
*/
public function view($id = null) {
if (!$this->Call->exists($id)) {
throw new NotFoundException(__('Invalid call'));
}
$options = array('conditions' => array('Call.' . $this->Call->primaryKey => $id));
$this->set('call', $this->Call->find('first', $options));
}
/**
* add method
*
* #return void
*/
public function add() {
if ($this->request->is('post')) {
$this->Call->create();
if ($this->Call->save($this->request->data)) {
$this->Session->setFlash(__('The call has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The call could not be saved. Please, try again.'));
}
}
$customers= $this->Call->Customers->find('list',array('order'=>'customer_name ASC','fields'=>array('id','customer_name')));
$employees= $this->Call->Employees->find('list',array('order'=>'employee_name ASC','fields'=>array('id','employee_name')));
$this->set(compact('customers', 'employees'));
}
/**
* edit method
*
* #throws NotFoundException
* #param string $id
* #return void
*/
public function edit($id = null) {
if (!$this->Call->exists($id)) {
throw new NotFoundException(__('Invalid call'));
}
if ($this->request->is(array('post', 'put'))) {
if ($this->Call->save($this->request->data)) {
$this->Session->setFlash(__('The call has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The call could not be saved. Please, try again.'));
}
} else {
$options = array('conditions' => array('Call.' . $this->Call->primaryKey => $id));
$this->request->data = $this->Call->find('first', $options);
}
$customers= $this->Call->Customers->find('list',array('order'=>'customer_name ASC','fields'=>array('id','customer_name')));
$employees= $this->Call->Employees->find('list',array('order'=>'employee_name ASC','fields'=>array('id','employee_name')));
$this->set(compact('customers', 'employees'));
}
/**
* delete method
*
* #throws NotFoundException
* #param string $id
* #return void
*/
public function delete($id = null) {
$this->Call->id = $id;
if (!$this->Call->exists()) {
throw new NotFoundException(__('Invalid call'));
}
$this->request->onlyAllow('post', 'delete');
if ($this->Call->delete()) {
$this->Session->setFlash(__('The call has been deleted.'));
} else {
$this->Session->setFlash(__('The call could not be deleted. Please, try again.'));
}
return $this->redirect(array('action' => 'index'));
}}
the array looks like this:
Array
(
[Call] => Array
(
[id] => 7
[call_date] => 2013-04-27
[call_time] => 08:31:00
[comments] => Require installation
[next_call_date] => 2014-04-27
[customers_id] => 2
[employees_id] => 3
)
[Customers] => Array
(
[id] => 2
[customer_name] => Snith Jams
[customer_address] => 192 Waverley Road
[customer_suburb] => Caulfield East
[customer_state] => VIC
[customer_postcode] => 3145
[customer_dob] => 2014-04-09
[customer_anniversary] => 2014-04-10
[customer_phone1] => 0492832921
[customer_phone2] => 0392817894
[customer_phone3] => 0482938281
[customer_fax] =>
[customer_email] => tsmith#hotmail.com
[customer_gender] => M
[customer_type] => Silver
[customer_PW] => a1c680c2bfcca40816dd81eff3980cc9828c9088
[customer_username] => samman
[companies_id] => 3
[employees_id] => 11
)
[Employees] => Array
(
[id] => 3
[employee_name] => Jones
[date_hired] => 2013-02-04
[employee_phone_number] => 0449997582
[employee_email] => indianajones#gmail.com
[employee_address] => 22 Queens street Melbourne CBD
[employee_dob] => 1966-01-31
[access_level] => staff
[employee_username] => jones12
[employee_pw] => 603fce7dcbec3c9cba24e87d058a3341e37779b8
)
)
callsController:
public $components = array('Paginator');
public function index() {
$this->Call->recursive = 2;
$this->set('calls', $this->Paginator->paginate());
}
calls/index.ctp:
<div class="calls index">
<h2><?php echo __('Call Details'); ?> </h2>
<table cellpadding="0" cellspacing="0">
<tr>
<th><?php echo $this->Paginator->sort('id'); ?></th>
<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 h($call['Call']['id']); ?> </td>
<td><?php echo h($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 h($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['Customers']['Companies']['company_name']); ?>
</td>
<td>
<?php echo $this->Html->link($call['Employees']['employee_name'], array('controller' => 'employees', 'action' => 'view', $call['Employees']['id'])); ?>
</td>
<?php echo pr($call); ?>
<td class="actions">
<?php echo $this->Html->link(__('View'), array('action' => 'view', $call['Call']['id'])); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
just set recursive to 2
$this->Call->recursive = 2;
(or $this->Calls->recursive = 2 it depends if your model is Call or Calls)
and you can access to Company information like this
$call['Customer']['Company']['name']
Because it seems you are not following cake naming conventions (you are using plural for Models' names) maybe you'll need to use
$call['Customers']['Companies']['name']
I suggest you to follow the conventions, anyway if you print your array doing pr($call); you'll see how the array is structured and how to access your data
I want to paginate in view for a custom array. My controller and view code is given below.
Controller Code:
public function admin_detail(){
$totalByDate = $this->Pbscodemetric->find('all',array('fields'=>array('created')));
$createdDate = Set::extract('/Pbscodemetric/created', $totalByDate);
$uniqueCreatedDate = array_unique($createdDate);
$finalArray = array();
foreach($uniqueCreatedDate as $created){
$downloadsArr = $this->Pbscodemetric->find('all',array('fields'=>array('downloads_iphone','downloads_ipad','downloads_android'),'conditions'=>array('created'=>$created)));
$download_iphone = array_sum(Set::extract('/Pbscodemetric/downloads_iphone',$downloadsArr));
$download_ipad = array_sum(Set::extract('/Pbscodemetric/downloads_ipad',$downloadsArr));
$downloads_android = array_sum(Set::extract('/Pbscodemetric/downloads_android',$downloadsArr));
$finalArray[$created] = array(
'downloads_iphone' => $download_iphone,
'downloads_ipad' => $download_ipad,
'downloads_android' => $downloads_android
);
}
$this->set('finalArray',$finalArray);
}
View Code:
<div class="pbscodemetrics index">
<h2><?php echo __('Pbscodemetrics List Detail'); ?></h2>
<table cellpadding="0" cellspacing="0">
<tr>
<th>Date</th>
<th>iPhone</th>
<th>iPad</th>
<th>Android</th>
</tr>
<?php
foreach($finalArray as $key => $final){?>
<tr>
<td><?php echo $key;?></td>
<td><?php echo $final['downloads_iphone'];?></td>
<td><?php echo $final['downloads_ipad'];?></td>
<td><?php echo $final['downloads_android'];?></td>
</tr>
<?php }?>
</table>
</div>
<div class="actions">
<?php echo $this->element('nav');?>
</div>
Now I want to set pagination. I know in CakePHP default pagination needs Model name. But How can I do that for the above code?
Can anyone help me please..
You could implement a custom pagination, see Custom Query Pagination in the Cookbook. However, it looks like what you're doing there could be done using grouping and the SQL SUM function, that way you could then simply use the built-in pagination. Example:
$alias = $this->Pbscodemetric->alias;
$this->Pbscodemetric->virtualFields = array
(
'downloads_iphone_sum' => sprintf('SUM(`%s.downloads_iphone`)', $alias),
'downloads_ipad_sum' => sprintf('SUM(`%s.downloads_ipad`)', $alias),
'downloads_android_sum' => sprintf('SUM(`%s.downloads_android`)', $alias)
);
$this->paginate = array
(
'fields' => array
(
'downloads_iphone_sum',
'downloads_ipad_sum',
'downloads_android_sum',
'created'
),
'group' => 'created',
'order' => array
(
'created' => 'desc'
),
'limit' => 10
);
$data = $this->paginate($alias);
This will give you Paginator helper compatible results with summed downloads_iphone, downloads_ipad and downloads_android columns, grouped by the created column. It uses virtual fields in order to retreive results in the default CakePHP style, ie they will be accessible like this:
<?php foreach($results as $result): ?>
<tr>
<td><?php echo $result['Pbscodemetric']['created'];?></td>
<td><?php echo $result['Pbscodemetric']['downloads_iphone_sum'];?></td>
<td><?php echo $result['Pbscodemetric']['downloads_ipad_sum'];?></td>
<td><?php echo $result['Pbscodemetric']['downloads_android_sum'];?></td>
</tr>
<?php endforeach; ?>