Paginate With and Without Contain Key CakePHP 2 - cakephp

I am using CakePHP 2.x and would like to apply pagination in my controller but I would like it to be available in one case with a contain key and the other case without the contain key. As an example consider this example:
class BlogController extends AppController {
public $name = "Blog";
public $paginate = array(
'Post'=>array(
'limit'=>30,
'conditions'=>array('publish'=>1),
),
);
function just_posts() {
// I want to paginate Post as it is
}
function posts_with_comments() {
// I want paginate Post with 'contain'=>'comments'
}
}
In my real life case the purpose in doing this is for performance, to reduce the query time. But I am at a loss how to implement this. The $this->paginate(...) will only accept an argument to filter records. Is there a way to make two paginators available for the same model in a controller?

You should be able to modify your controller's paginate property within the relevant action to include the contain before doing the paginate:-
$this->paginate['Post']['contain'] = 'Comment';
This would extend the controller's defaults for the specific action.

Related

use unassociate model in another model with condition in cakephp [duplicate]

Can I use another Model inside one model?
Eg.
<?php
class Form extends AppModel
{
var $name='Form';
var $helpers=array('Html','Ajax','Javascript','Form');
var $components = array( 'RequestHandler','Email');
function saveFormName($data)
{
$this->data['Form']['formname']=$data['Form']['formname'];
$this->saveField('name',$this->data['Form']['formname']);
}
function saveFieldname($data)
{
$this->data['Attribute']['fieldname']=$data['Attribute']['fieldname'];
}
}
?>
Old thread but I'm going to chime in because I believe the answers to be incomplete and lacking in "why". CakePHP has three ways to load models. Though only two methods work outside of a Controller, I'll mention all three. I'm not sure about version availability but this is core stuff so I believe they'll work.
App::import() only finds and require()s the file and you'll need to instantiate the class to use it. You can tell import() the type of class, the name and file path details.
ClassRegistry::init() loads the file, adds the instance to the object map and returns the instance. This is the better way to load something because it sets up "Cake" things as would happen if you loaded the class through normal means. You can also set an alias for the class name which I've found useful.
Controller::loadModel() uses ClassRegistry::init() as well as adds the Model as a property of the controller. It also allows $persistModel for model caching on future requests. This only works in a Controller and, if that's your situation, I'd use this method before the others.
You can create instances of other models from within any model/controller using one of these two methods.
If you're using Cake 1.2:
App::import('model','Attribute');
$attr = new Attribute();
$attr->save($dataYouWantToSavetoAttribute);
If you're using Cake 1.1:
loadModel('Attribute');
$attr = new Attribute();
$attr->save($dataYouWantToSavetoAttribute);
An obvious solution everyone missed is to create an association between two models, if appropriate. You can use it to be able to reference one model from inside another.
class Creation extends AppModel {
public $belongsTo = array(
'Inventor' => array(
'className' => 'Inventor',
'foreignKey' => 'inventor_id',
)
);
public function whoIsMyMaker() {
$this->Inventor->id = $this->field('inventor_id');
return $this->Inventor->field('name');
}
}
In CakePHP 1.2, it's better to use:
ClassRegistry::init('Attribute')->save($data);
This will do simply
<?php
class Form extends AppModel
{
//...
$another_model = ClassRegistry::init('AnotherModel');
//...
}
?>
In CakePHP 3 we may use TableRegistry::get(modelName)
use Cake\ORM\TableRegistry;
$itemsOb = TableRegistry::get('Items');
$items = $itemsOb->find("all");
debug($items);
If you want to use Model_B inside Model_A, add this line at the beginning of Model_A file:
App::uses('Model_B_ClassName', 'Model');
and then you will be able to use it inside Model_A. For example:
$Model_B = new Model_B_ClassName();
$result = $Model_B->findById($some_id);
var $uses = array('ModeloneName','ModeltwoName');
By using $uses property, you can use multiple models in controller instead of using loadModel('Model Name').
App::import('model','Attribute');
is way to use one model into other model. Best way will be to used association.

Filter data based on User field cakePHP

So I have a company based system and I am keeping all data within the one database and I separate the data by using a site_id field which is present in all tables and in the users table.
Now at the moment I am doing a condition on every single find('all'). Is there a more global way to do this. Maybe in the AppController? Even for saving data I am having to set the site_id every single save.
Something like
public function beforeFilter() {
parent::beforeFilter();
$this->set('site_id', $this->Auth->user('site_id'));
}
Any direction would only help. Thanks
TLDR:
Create a Behavior with a beforeFind() method that appends a site_id condition to all queries.
Example/Details:
Create a behavior something along the lines of the below. Note, I'm getting the siteId from a Configure variable, but feel free to get that however you want.
<?php
class SiteSpecificBehavior extends ModelBehavior {
public function setup(Model $Model, $settings = array()) {
$Model->siteId = Configure::read('Site.current.id');
}
public function beforeFind(Model $Model, $query = array()) {
$siteId = $Model->siteId;
$query['conditions'][$Model->alias . '.site_id'] = $siteId ;
return $query;
}
}
Then on any/all models where you want to make sure it's site-specific, add:
public $actsAs = array('SiteSpecific');
This can be tweaked and improved up certainly, but it should give you a good idea.

First 'find' call does not return associated data. Second 'find' call does

The following is declared in model 'GradingPeriod':
class GradingPeriod extends AppModel {
public $belongsTo = array('AcademicYear' => array('className' => 'AcademicYear', 'foreignKey' => 'academic_year_id'));
...
public function getEnrolledSections(){
$this->recursive = 1;
debug($this->findById(21)); // Does **not** return AcademicYear
// model data when function is called
// from a different model.
debug($this->findById(21)); // **Does** return AcademicYear
// model data when function is called
// from a different model.
die();
}
}
When called from a controller or inside the GradingPeriod model, this works fine. The first 'find' call does return the GradingPeriod model's associated data (AcademicYear).
When called from a different model, the first 'find' call does not return the GradingPeriod model's associated data (AcademicYear). The second 'find' call does return the GradingPeriod model's associated data (AcademicYear).
class ReportCard extends AppModel {
public function callToGradingPeriod(){
$objGradingPeriod = ClassRegistry::init('GradingPeriod');
$objGradingPeriod->getEnrolledSections();
}
}
I have tried this with CakePHP 2.1.2 and 2.2.3 with the same results.
I know calling one model from another may be considered bad form, but why is this code behaving as it does? Thank you in advance for any assistance you can provide.
This is not really an answer as far as why it's working (or not) the way it is, but a suggestion for you and any future users trying something similar:
Don't EVER use recursive to get associated data. Set public $recursive = -1; in your AppModel and never look back. When you want related data, use CakePHP's Containable Behavior.
It might seem like recursive is your friend - or that it's "just easier", but I promise it will cause issues further down the road - either when you want more data, or just when you get more data in your database (memory issues/errors among other things). It's bad practice, and I believe they're even going to remove recursive all together in CakePHP 3+.
Trust me on this one - ditch recursive, and use contain() instead.

CakePHP: To Create A New Controller

I'm using CakePHP 2.0.5 (but this isn't necessarily a cakephp specific question). I have a Coupon and a User model. Each time a user prints a coupon (proccessed by: Coupon Controller):
class CouponsController extends AppController {
public function printcoupon($id = null) {
// code
}
}
I want to save the information to a "coupons_printed" table (id/coupon_id/user_id/created). Should I create a new model for this, or should I just create a function inside of the Coupon model similar to (and call it in the controller each time that page is viewed)?:
class Coupon extends AppModel {
function insertIntoPrinted($id) {
$this->query("UPDATE coupons_printed SET .....");
}
}
Whatever you do, a raw SQL query is not the best way to go. Always use CakePHP methods if at all possible (and almost always it is possible).
You should put the insertIntoPrinted() function in the CouponsPrinted model (although, as a side note, PrintedCoupon would be a more natural way to name the model...) You can then add a HasMany relationship to the Coupon model ($hasMany = array( 'CouponsPrinted' )) and call the function in the CouponsController:
public function printcoupon($id = null) {
$this->Coupon->CouponsPrinted->insertIntoPrinted( $id );
}
CakePHP's model has a thing call association.
In your case, Coupon has a hasMany association with coupons_printed.
You can create a new model, or query using the association in the Coupon model, the generated queries will be the same, I believe.
Your CouponsController already depend on Coupon Model, so not creating another model is a better solution.

Can I use one model inside of a different model in CakePHP?

Can I use another Model inside one model?
Eg.
<?php
class Form extends AppModel
{
var $name='Form';
var $helpers=array('Html','Ajax','Javascript','Form');
var $components = array( 'RequestHandler','Email');
function saveFormName($data)
{
$this->data['Form']['formname']=$data['Form']['formname'];
$this->saveField('name',$this->data['Form']['formname']);
}
function saveFieldname($data)
{
$this->data['Attribute']['fieldname']=$data['Attribute']['fieldname'];
}
}
?>
Old thread but I'm going to chime in because I believe the answers to be incomplete and lacking in "why". CakePHP has three ways to load models. Though only two methods work outside of a Controller, I'll mention all three. I'm not sure about version availability but this is core stuff so I believe they'll work.
App::import() only finds and require()s the file and you'll need to instantiate the class to use it. You can tell import() the type of class, the name and file path details.
ClassRegistry::init() loads the file, adds the instance to the object map and returns the instance. This is the better way to load something because it sets up "Cake" things as would happen if you loaded the class through normal means. You can also set an alias for the class name which I've found useful.
Controller::loadModel() uses ClassRegistry::init() as well as adds the Model as a property of the controller. It also allows $persistModel for model caching on future requests. This only works in a Controller and, if that's your situation, I'd use this method before the others.
You can create instances of other models from within any model/controller using one of these two methods.
If you're using Cake 1.2:
App::import('model','Attribute');
$attr = new Attribute();
$attr->save($dataYouWantToSavetoAttribute);
If you're using Cake 1.1:
loadModel('Attribute');
$attr = new Attribute();
$attr->save($dataYouWantToSavetoAttribute);
An obvious solution everyone missed is to create an association between two models, if appropriate. You can use it to be able to reference one model from inside another.
class Creation extends AppModel {
public $belongsTo = array(
'Inventor' => array(
'className' => 'Inventor',
'foreignKey' => 'inventor_id',
)
);
public function whoIsMyMaker() {
$this->Inventor->id = $this->field('inventor_id');
return $this->Inventor->field('name');
}
}
In CakePHP 1.2, it's better to use:
ClassRegistry::init('Attribute')->save($data);
This will do simply
<?php
class Form extends AppModel
{
//...
$another_model = ClassRegistry::init('AnotherModel');
//...
}
?>
In CakePHP 3 we may use TableRegistry::get(modelName)
use Cake\ORM\TableRegistry;
$itemsOb = TableRegistry::get('Items');
$items = $itemsOb->find("all");
debug($items);
If you want to use Model_B inside Model_A, add this line at the beginning of Model_A file:
App::uses('Model_B_ClassName', 'Model');
and then you will be able to use it inside Model_A. For example:
$Model_B = new Model_B_ClassName();
$result = $Model_B->findById($some_id);
var $uses = array('ModeloneName','ModeltwoName');
By using $uses property, you can use multiple models in controller instead of using loadModel('Model Name').
App::import('model','Attribute');
is way to use one model into other model. Best way will be to used association.

Resources