$this->Model-id not set with CakePHP 1.3 - cakephp

I am trying to retrieve the id of a record in my database in the index() method of my cns_controller.php file. I want to use it for a find(). However, the $this->Cn->id is not returning a value, therefore the find() doesn't work either.
$uses = array('Cn', 'Release');
/*check non-null value in released_user_id,
showing Release tab has been signed off*/
$releaseSignedOff = $this->Release->find('all', array(
'conditions' => array('Release.cn_id =' => $this->Cn->id,
'Release.released_user_id !=' => null)
));
(sizeof($releaseSignedOff) > 0) ? $releaseSignedOff = true : $releaseSignedOff = false;
$this->set('releaseSignedOff', $releaseSignedOff);
Any ideas?
Thanks

I ended up not using my index view, instead I looked up the most recent record in my cns database table and redirected to the view view using the returned value as a parameter:
if (!$id) {
$most_recent_change_note = $this->Cn->find('first', array(
'order' => array('Cn.id DESC')
));
$this->redirect(array('controller' => 'cns',
'action' => 'view/'.$most_recent_change_note['Cn']['id']));
}
For the pagination, I ended up using the $neighbors feature of CakePHP:
function get_neighbors($id) {
$neighbors = $this->Cn->find('neighbors', array('field' => 'id',
'value' => $id));
$this->set('neighbors', $neighbors);
}
Then in my view view, I used those values to create links:
<div class="paging">
<?php echo ($neighbors['next']) ? $html->link('<< Prev',
array('controller'=>'cns',
'action'=>'view/'.$neighbors['next']['Cn']['id'])).' | ' : '<< Prev | ';
echo $html->link('Next >>', array('controller'=>'cns',
'action'=>'view/'.$neighbors['prev']['Cn']['id'])); ?>
</div>
Thanks to Charles and Ross for helping me reach this conclusion. :)

Related

How to (re)set CakePhp Paginator to page 1

I have a table of Parts retrieved from a database and a form with a select tag listing PartTypes and a
[Refresh] button. These are used to filter the table to show only parts that match the selected type.
The table is paginated for performance. When I start on Page 1, I can successfully filter my data table
using my select and refresh button, but if I navigate away from page 1 via the Paginator, and try to
refresh the page with a new PartType (rather than all being visible), I get the following error
Error: The requested address '/product/parts/index/page:2' was not found on this server.
I have been through the PaginatorComponent and PaginatorHelper documentation and cannot see how to
reset the page before filtering my data. What am I missing?
/Controller/PartsController.php
public $paginate = array(
'limit' => 12,
'page' => 1,
'order' => array('Part.name' => 'asc' )
);
public function index() {
// ...
// array $qcond holds the query properties for filtering parts
if (count($qcond) > 0)
$this->paginate['conditions'] = $qcond;
// ...
$this->set('parts', $this->paginate());
}
app/View/Parts/index.ctp
<?php
echo $this->Paginator->prev(__('«'), array('tag' => 'li'), null, array('tag' => 'li','class' => 'disabled','disabledTag' => 'a'));
echo $this->Paginator->numbers(array('separator' => '','currentTag' => 'a', 'currentClass' => 'active','tag' => 'li','first' => 1));
echo $this->Paginator->next(__('»'), array('tag' => 'li','currentClass' => 'disabled'), null, array('tag' => 'li','class' => 'disabled','disabledTag' => 'a'));
?>
Problem solved: Issue was not in the Paginator, but in the Form. Had to manually set the form's url to not use /page:2, rather than let CakePhp deduce the url on it's own.
In Cakephp 2.x You can reset page by using bellow code in Controller:
$this->request->params['named']['page']=1;

CakePHP Routes.php for Slugs

I am trying to get my CakePHP app to use slugs instead of ids. I have read several tutorials and the CakePHP book about it, but I must be missing something simple.
My table has a "slug" field that I want to use for the URL instead of the default id.
I changed my ItemsController view to this:
public function view($slug = null) {
if (!$this->Item->exists($slug)) {
throw new NotFoundException(__('Invalid item'));
}
$this->set('item', $this->Item->findBySlug($slug));
}
And added this to my routes.php
Router::connect(
'/items/:slug',
array('controller' => 'items', 'action'=>'view'),
array('pass'=>array('slug'))
);
Yet I still get "Invalid Item, requested address not found..." when going to:
mycakeapp/items/slug-value
However, if I change everything from 'slug' to 'id' then the URL:
mycakeapp/items/id-value
works just fine
Can someone help me? Thanks in advance.
Well, read the documentation for Model::exists().
Returns true if a record with particular ID exists.
If $id is not passed it calls Model::getID() to obtain the current
record ID, and then performs a Model::find('count') on the currently
configured datasource to ascertain the existence of the record in
persistent storage.
It expects an id not a slug.
Here is a proper example from a model method to display an artist:
public function view($id = null, $options = array()) {
$defaults = array(
'contain' => array(
/* ... */
),
'conditions' => array(
'OR' => array(
$this->alias . '.' . $this->primaryKey => $id,
$this->alias . '.slug' => $id
)
)
);
$artist = $this->find('first', Hash::merge($defaults, $options));
if (empty($artist)) {
throw new NotFoundException(__('Invalid Artist'));
}
return $artist;
}
The controllers try/catches the exception and sets the exception message to the session by calling Session->setFlasH(). Easy. :)

Returning MySQL data to cakephp view

I am pretty new to cakephp and I am banging my head against the wall trying to write a pretty basic statement.
In my view file, I want to say if the is_open column in the events table is true, echo something. If it is not true, echo something else.
<?php
if ($response['data']['Event']['is_open'] == true) {
echo "Yes";
} else {
echo "No";
}
?>
I am having trouble working backwards within the controller to get the data in the first place.
In my controller I have something this:
public function some_function() {
$events = $this->Event->find('all');
}
In my view file, I get this error:
Notice (8): Undefined index: Event [View/Applications/agreement.ctp, line 21]
Can anyone point out what I am doing wrong?
I have been going through the blog tutorial and it's clear in some places to me and not clear in others. Where I am still having trouble is displaying anything in the view.
After further reading I want to do something like this in the controller:
$myVariable = $this->Event->find('first',
array( 'fields' => 'Event.is_open ',
'conditions' => array('Event.id =' => '400') ));
What I am hoping to say is grab the is_open value from the events table where the events.id = 400 (later on this value will be dynamic) Does this look even remotely correct? – mmalv just now edit
How did you come up with $response['data']?
In your EventsController you correctly set the return of $this->Event->find('all') to $events. In order for this variable to be available to your view you need to call Controller::set on it like this:
$this->set('events', $events);
Or even simpler, in one step, you can just do:
$this->set('events', $this->Event->find('all'));
Then in your Event view (perhaps someplace like View/Events/index.ctp) access the variable by the name $events. It should be in the format
Array(
[0] => Array(
'Event' => Array(
'id' => 1,
'name' => 'An open name!',
'is_open' => true
)
),
[1] => Array(
'Event' => Array(
'id' => 1,
'name' => 'Another event but closed',
'is_open' => false
)
)
)
So now all you need in your view is to run a loop like:
foreach ($events as $key => $value) {
if ($value['Event']['is_open']) {
echo "Yes";
} else {
echo "No";
}
}
All this is thoroughly explained in the cookbook, just go through the blog tutorial.

how to tell cakephp to use function index($type) to just go to the index page?

I have this application that directs users to Types of attractions with this function:
public function index($type=null) {
$this->set('title','What to do when you visit Gulf Shores');
$this->paginate['Attraction']=array(
'limit'=>9,
'order'=>array('Attraction.id'=>'asc'),
'conditions'=>array(
'active'=>1,
'attr_type'=>$type
)
);
$c=$this->paginate('Attraction');
$this->set('attractions', $c);
}
and it works great, but I'd like users to also be able to go to a front page /attractions/ that doesn't filter out by attr_type. This function shows zero results (as obviously $type still = null) for the front page. Is there a step I'm missing or must I have a view.ctp file and function in my controller?
You could use an if statement to determine the conditions:
public function index($type = null) {
$this->set('title', 'What to do when you visit Gulf Shores');
$conditions = array(); //create $conditions outside of the if statement
if ($type) { //if $type is equal to anything other than null or 0
$conditions = array(
'active' => 1,
'attr_type' => $type
);
} else {
$conditions = array(
'active' => 1
);
}
$this->paginate['Attraction'] = array(
'limit' => 9,
'order' => array('Attraction.id' => 'asc'),
'conditions' => $conditions
);
$c = $this->paginate('Attraction');
$this->set('attractions', $c);
}
It's not actually necessary to create $conditions outside of the if statement in PHP but it is in a lot of other programming languages because of scope.
If you create a variable inside a if statement is it available outside the if statement?

CakePHP - Paginating an Array

Cake handles pagination of a model with a simple $this->paginate(), but what should I use if I want to paginate a array of values?
The Scenario is like this:
$this->set('sitepages', $this->paginate());
This code in my index() returns an array like
Array
(
[0] => Array
(
[Sitepage] => Array
(
[id] => 13
[name] => Home
[urlslug] => home
[parent_id] => 1
[page_title] => Welcome to KIAMS, Pune
[order] => 1
)
)
[1] => Array
(
[Sitepage] => Array
(
[id] => 26
[name] => About Us
[urlslug] => aboutus
[parent_id] => 1
[page_title] =>
[order] => 2
)
)
[2] => Array
(
[Sitepage] => Array
(
[id] => 27
[name] => Overview of KIAMS
[urlslug] => aboutus/overview
[parent_id] => 26
[page_title] =>
[order] => 2
)
)
I retrieved the same data using $this->Sitepage->find('all') and then performed some manipulations as required and form a array which is very similar to the above one, but the ordering gets changed. I want to paginate this new array and pass it to the view. I tried
$this->set('sitepages',$this->paginate($newarray))
But the data is not getting paginated. Can some one please help with paginating the $newarray in CakePHP?
To paginate in CakePHP you need to pass select conditions to the paginate() call.
Other data manipulation should be done in afterFind(), in your model file.
If you don't need these changes to be done in every single retrieval, you might as well consider creating a new model file pointing to the very same table as the current one, and adding an afterFind() method to that new file.
I've just dealt with this same problem...
I found the only way is to use the paginate() function to handle all the logic, rather than passing it a custom array. However, this isn't as bad as it seems:
$this->paginate = array(
'limit' => 2,
'order' => array(
'Report.name' => 'asc'
),
'conditions' => array(
'Account.id' => $this->foo()
),
);
$reports = $this->paginate();
In this example, I'm paginating Reports - but some Reports will not be included, depending on which Account they belong to (Account has some relationship with Report, hasmany, etc.).
By writing $paginate inside your action, you can use a custom callback for the conditions array. So function foo() can be written in your controller (or shoved to model) and returns an array of valid Account IDs.
I found I could easily rewrite my custom logic in this function - keeping both me and the Cake paginator happy.
Hope that helps!
I'm using cakephp version 1.3 and it seems this one is working:
at controller:
$result = $this->Paginate('Event');
$results = $this->Task->humanizeEvent($result);
$this->set('events', $results);
and it seems to display as a normal paginated array, at the view (setup your pagination in view as normal).
The humanizeEvent function just edits a field on the results array, to make it a sentence based on other fields inside the array, and it seems to work properly.
$this->paginate($newarray) is the wrong way to paginate. The first parameter cannot be an array. It must be a model name. You may want to study pagination setup from the manual. This will order alphabetically:
var $paginate = array(
'limit' => 25,
'order' => array(
'Sitepage.name' => 'asc'
)
);
$this->set('sitepages', $this->paginate('Sitepage'));
I create a component checking the paginator code..
Is not the best thing, but It work for me.....
Controller
$slicedArray = array_slice($fullArray,($page - 1) * $this->PaginatorArray->limit ,$this->PaginatorArray->limit)
$this->params['paging'] = $this->PaginatorArray->getParamsPaging('MyModel', $page, $total,count($slicedArray));
$this->helpers[] = 'Paginator';
Component
<?php
/* SVN FILE: $Id$ */
/**
* Pagination Array Component class file.
* #subpackage cake.cake.libs.view.helpers
*/
class PaginatorArrayComponent {
var $limit = 40;
var $step = 1;
function startup( & $controller){
$this->controller = & $controller;
}
function getParamsPaging($model, $page, $total, $current){
$pageCount = ceil($total / $this->limit);
$prevPage = '';
$nextPage = '';
if($page > 1)
$prevPage = $page - 1;
if($page + 1 <= $pageCount)
$nextPage = $page + 1;
return array(
$model => array(
'page' => $page,
'current' => $current,
'count' => $total,
'prevPage' => $prevPage,
'nextPage' => $nextPage,
'pageCount' => $pageCount,
'defaults' => array(
'limit' => $this->limit,
'step' => $this->step,
'order' => array(),
'conditions' => array(),
),
'options' => array(
'page' => $page,
'limit' => $this->limit,
'order' => array(),
'conditions' => array(),
)
)
);
}
}
?>
There was a bug in find("count") and it returned incorrect count if the query resulted in records for only in group. This has been fixed click here

Resources