Hi I'm currently working on a project and was wondering if it was possible to do two find functions in cakephp?
For example I am making a sports news website and I am grouping the news articles as top story, understory and headline.
What I want to do is retrive top stories so i can highlight these as the prominent story and then understory will be beneath as a lesser story and then headlines will be the least important.
This is what I have so far
function latestnews() {
$articles = $this->Article->find('all',
array('limit' =>3,
'order' =>
array('Article.date_created' => 'desc')));
if(isset($this->params['requested'])) {
return $articles;
}
$this->set('articles', $articles);
$articler = $this->Article->find('all',
array('Article.type' => 'topstory',
'Limit' => '1'
));
$this->set('articles', $articler);
}
however this doesn't seem to work, it doesn't limit the $articles function but instead echos all the data in the table.
in the view im doing a standard foreach statement to echo the data and I get thrown a undefined variable error.
Is what i am saying even possible or should I create different functions and then use them as elements?
Thanks for any input in advance!
You can bind the associationship with itself dynamically. Try this code:
function latestnews() {
$this->Article->bindModel(array('hasMany' => array('TopStory' => array('className' => 'Article',
'foreignKey' => false,
'conditions' => array('Article.type' => 'topstory')
),
'Highlight' .....
)));
$articles = $this->Article->find('all',
array('limit' =>3,
'order' => array('Article.date_created' => 'desc')));
if(isset($this->params['requested'])) {
return $articles;
}
$this->set('articles', $articles);
$articler = $this->Article->find('all',
array('Article.type' => 'topstory',
'Limit' => '1'
));
$this->set('articles', $articler);
}
Hope it will work for you.
#Arun Nope that didn't seem to work, I get this error, Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Article.type' in 'where clause' also I've tried to put it in an element with its own function and I then get thrown this error...
Notice (8): Undefined variable: data [APP/View/Elements/Articles/topstories.ctp, line 5]
Warning (2): Invalid argument supplied for foreach() [APP/View/Elements/Articles/topstories.ctp, line 5]
Notice (8): Undefined property: View::$Paginator [CORE/Cake/View/View.php, line 806]
Fatal error: Call to a member function prev() on a non-object in /Applications/XAMPP/xamppfiles/htdocs/kickoff/app/View/Elements/Articles/topstories.ctp on line 21
The controller code is the following...
function topstories() {
$this->paginate = array(
'conditions' => array('Article.type' => 'topstory'),
'limit' => 2,
'order' => array(
'date_created' => 'asc'
)
);
$data = $this->paginate('Article');
$this->set(compact('data'));
}
I find this error confusing as if I don't put this in an element and in a view instead it works perfectly! however in an element not so perfect :S
any ideas as to why this is the case??
Instead of using two find methods in one function I instead chose to simply create different functions and use them as elements for example...
function premiershiptopstory() {
$pltopnews = $this->Article->find('all', array(
'conditions' => array('Article.league' => 'premiership',
'Article.type' => 'topstory')));
if(!empty($this->request->params['requested'])) {
return $pltopnews;}
$this->set('article', $pltopnews);
}
However in the view you must request the action otherwise you will get thrown an error, to request the action simply use this line of code...
<?php $pltopnews = $this->requestAction('/Articles/premiershiptopstory');
Hope this helps others!
Related
I'm trying to limit my pagination results by the $this->Session->read('Player.team_id')... so that the logged in user can only see his related team members.
PlayersController.php
public $paginate = array(
'conditions' => array(
'Player.team_id' => $this->Session->read('Player.0.Team.id')
),
'limit' => 20,
'order' => array('Player.fullname' => 'asc')
);
public function index() {
$this->Paginator->settings = $this->paginate;
$this->Player->recursive = 0;
$this->set('players', $this->Paginator->paginate());
}
This causes an error when viewing player/index
Error: syntax error, unexpected T_VARIABLE
File: /home/www/public_html/dev/app/Controller/PlayersController.php
Line: 21
If I hardcode the 'conditions' as below then it works fine and only retrieves the records I want
'conditions' => array('Player.team_id' => 1)
In the Player.php model login action it writes the Session Variable Team.id and Team.name.
I have used the $this->Session->read else where in my app (views and other models) and it works fine. It just doesn't seem to work with in the pagination component?
This is simply invalid PHP syntax, class members can only be initialized with constant values, that is values that can be evaluated at compile time (strings, numbers, booleans, arrays, etc...)
Assign the session value at runtime in the Controller::beforeFilter() callback (or even directly in the index() action in case appropriate) instead:
public $paginate = array(
'limit' => 20,
'order' => array('Player.fullname' => 'asc')
);
public function beforeFilter() {
parent::beforeFilter();
$this->paginate['conditions'] = array(
'Player.team_id' => $this->Session->read('Player.0.Team.id')
);
}
Also as pointed out in the comments, make sure that the session key you are accessing actually exists and holds the expected value!
See also http://www.php.net/manual/en/language.oop5.properties.php
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.
I am trying to test a controller function that accepts a json payload.
As per the documentation of testAction() this can be done via setting $options['data'] to the appropriate string. Its not working for me.
See the documentation quoted here: http://api20.cakephp.org/class/controller-test-case (Please scroll down the the testAction() section).
Here is my test case.
public function testCreate(){
//Some code here
$this->testAction('/shippingbatches/create', array('data' => '[3,6]', 'method' => 'post'));
//Some more code here
}
Here is my controller function
public function create(){
debug($this->request); //This debug shows me an empty array in $this->request->data
ob_flush();
$order_ids = json_decode($this->request->data);
//Some more code here
}
The first line of the controller function is showing me an empty array in $this->request->data. If the 'data' passed from the testAction() is an actual array it comes in nice & fine. But not when it is set to a string (unlike it says in the documentation).
Here is the output of the debug.
object(Mock_CakeRequest_ef4431a5) {
params => array(
'plugin' => null,
'controller' => 'shippingbatches',
'action' => 'create',
'named' => array(),
'pass' => array(),
'return' => (int) 1,
'bare' => (int) 1,
'requested' => (int) 1
)
data => array()
query => array(
'case' => 'Controller\ShippingBatchesController'
)
url => 'shippingbatches/create'
base => ''
webroot => '/'
here => '/shippingbatches/create'
}
Please help.
Gurpreet
When passing data like that, you must receive it using CakeRequest::input().
public function create() {
$json = $this->request->input('json_decode', true);
debug($json);
}
I should note that I discovered this by reading Cake's test cases for ControllerTestCase::testAction. Reading test cases can give you insight into how Cake's internals work and give you hints on writing tests.
I am having a problem with my CakePHP 1.3 app, and I'm not sure if it's a code issue or a DB issue.
I have a pretty simple function in one of my controllers, and whenever I add a query portion to that controller, I get the following (infuriating and completely unhelpful) error message:
Missing Controller
Error: InternalError.htmlController could not be found.
Error: Create the class InternalError.htmlController below in file:
app/controllers/internal_error.html_controller.php
Here is the Model ForecastZones
class ForecastZone extends AppModel {
var $name = 'ForecastZone';
var $displayField = 'name';
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $belongsTo = array(
'State' => array(
'className' => 'State',
'foreignKey' => 'state_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
var $hasMany = array(
'ForecastZonePoly' => array(
'className' => 'ForecastZonePoly',
'foreignKey' => 'forecast_zone_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
}
Here is the controller function that inexplicably fails:
function poly($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid forecast zone', true));
$this->redirect(array('action' => 'index'));
}
$this->layout = false;
$result = $this->ForecastZone->query("SELECT coords FROM forecast_zone_polies WHERE forecast_zone_id = $id;");
$this->set('forecastZone', $result);
}
CakePHP epic fails whenever I call this controller action. It hangs for a LONG time... and then instead of telling me something useful like "database query took too long" or "model association broken" or something like that... it just gives up and gives me this complete BS error message.
This is not a path issue, the paths are correct. If I remove the $result variable, everything works fine and I get the appropriate "forecastZone is not set" error message. The crux of this issue seems to be a query that takes forever, and then Cake not properly reporting the error message.
Please help clear this up for me. Very frustrating... not "Cake" at all by any stretch of the word.
EDIT: I wanted to add that I originally had been using
$this->ForecastZone->read(null,$id);
To grab the data, but the hanging & failing of the query kept happening so I switched to the raw query in hopes that might change something.
EDIT 2:
More things I tried:
Added this line to the top of my controller:
var $uses = array('ForecastZone','ForecastZonePolies');
And then tried to do things "the right way" that still fail. UGH!
$result = $this->ForecastZonePolies->find('all',array('conditions' => array('ForecastZonePolies.forecast_zone_id' => $id)));
$result = $this->ForecastZone->ForecastZonePolies->find('all',array('conditions' => array('ForecastZonePolies.forecast_zone_id' => $id)));
None of these work.
First I'd check app/tmp/logs/error.log and app/tmp/logs/debug.log. If this really is an internal error, you should get details there.
From the weird inflecting, I'd suggest you to put Router::parseExtensions('html') in your app/config/routes.php to make sure this isn't a redirect issue.
So this is what I am trying to do.
My table say(Courses) has multiple entries with same id.
When I get the data from paginate it shows all the records. So if I have 3 records with Id 5 it will show record number 5 three times.
Now What I want is that it should show the record only once.
I searched online but can't find anything.
If anyone has come across such problem and found a solution to it please let me know.
Thanks,
I came across your problem, as I had a similar problem. David Z's solution did not work for me, but I did find that the group variable in $paginate worked for me.
So using your code sample above, this is how I'd think it should work.
$paginate = array(
'Courses' => array(
'limit' => 20,
'fields' => array('Courses.id'),
'conditions' => $cond,
'group' => array('Courses.id'),
'order' => array('Courses.id' => 'asc')
)
);
To hopefully shed some more light on the solution that worked for me, I have Systems that belong to Companies. I wanted to get a list of the unique companies, for the systems I have. This is the exact code I used, that worked for me
$this->paginate = array ('fields' => array ('Company.*'),
'order' => array('Company.name' => 'ASC'),
'group' => array('Company.id'));
$this->set('companies', $this->paginate($this->Company->System));
Hope this has helped
Looking at the CakePHP cookbook, the documentation for pagination shows that you can override the $paginate member. Behind the scenes, this similar to passing in the parameters for your model's find('all'). Maybe try setting parameter to explicitly return the filds that you are interested with the distinct keyword to narrow down the values you need?
class RecipesController extends AppController {
var $paginate = array(
'fields' => array('Model.field1', 'DISTINCT Model.field2')
);
}
So here is how my paginate variable looks like:
var $paginate = array(
'Courses' => array(
'limit' => 20,
'page' => 1,
'order' => array(
'Courses.id' => 'asc')
),
);
The condition variable looks something like this:
$cond = array("Courses.id LIKE "=>$this->data['id_search'],
"Courses.length LIKE "=>$this->data['length_search'],
"Courses.marks LIKE "=>$this->data['marks']
);
And this is how I am calling paginate.
$data = $this->paginate('CdmaRfReport',$cond);
I tried doing
$paginate = array(
'Courses' => array(
'limit' => 20,
'fields' => array('DISTINCT Courses.id'),
'page' => 1,
'conditions' => $cond,
'group' => array('id'),
'order' => array(
'Courses.id' => 'asc')
)
);
It doesn't seem to help.
I also tried
$cond = array("DISTINCT Courses.id "=>$this->data['id_search'],
"Courses.length LIKE "=>$this->data['length_search'],
"Courses.marks LIKE "=>$this->data['marks']
);
Even this errors out
I might be something wrong. But I am not able to figure it out.
Any suggestions please let me know.