cakePHP and conditions on deep association - cakephp

The data structure is:
tenants {id, ...}
contracts {id, active, tenant_id, ...}
debts {id, contract_id, ...}
the desired data is:
tenants list, filtered by contracts and debts.
conditions:
contract must be active.
tenant has debts
keep in mind:
tenant has many contracts
contracts has many debts
contain won't help, since it will not filter the tenants.
My idea is to manually create the joins, and add filters to them. but how exactly?
my questions:
How can i do it with native cake?
how would you do it?

You have to put all this logic on models.
For each tables create a model (You can use the Cake Bake tools or write it by yourself).
class Tenant extends AppModel{
public $hasMany = array('Contract'); // feel free to ajust settings
}
class Contract extends AppModel{
public $belongsTo = array('Tenant');
public $hasMany = array('Debt');
}
class Debt extends AppModel{
public $belongsTo = array('Contract');
}
Now you can use on your Tenant controller something like that :
function action(){
$this->Tenant->recursive = 2;
$all_contracts = $this->Tenant->find('all');
}
But that solution is not the best, you can wrap this logic into model's method.
class Tenant extends AppModel
{
public $hasMany = array('Contract');
public function contracts($is_active = true) {
/*
Create your own logic here, you have many solutions to retrieve data like
load the containable behaviors, create a custom find method, custom query ...
Do stuff here not in controller action.
*/
$this->Behaviors->load('Containable');
$this->contain(array(
'Contract' => array(
'conditions' => array(
'active' => $is_active
),
'Debt'
)
));
return $this->find('all');
}
}
class Contract extends AppModel{
public $belongsTo = array('Tenant');
public $hasMany = array('Debt');
}
class Debt extends AppModel{
public $belongsTo = array('Contract');
}
http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html
http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#creating-custom-find-types

Related

associated data & displayField cakephp

I have shipments, orders and users. When I try and set up a new shipment, the Order displayField is showing up correctly as the label in my select dropdown. The User though is only showing the actual id of the user instead of the displayField.
What am I doing wrong? I'm using admin scaffolding. Is that the problem?
class Shipment extends ShipmentsAppModel {
public $belongsTo = array('Order', 'User');
}
class Order extends AppModel {
public $belongsTo = array('User');
public $name = 'Order';
public $displayField = 'title';
}
class User extends UsersAppModel {
public $displayField = 'email';
}
Seeing, UsersAppModel extends by User. It should AppModel according to CakePHP convention. Order is Extending AppModel and its working as u expect.
Try to use AppModel instead of UsersAppModel. The $displayField inherits from AppModel automatically, its a magic variable, defined in CakePHP core with default id field. Re-using that variable that variable in our model we just re-write that value and here AppModel is the linker.
But, here I think UsersAppModel has no relation with CakePHP core model inheritance like AppModel and that is the point of issue.
So instead of
class User extends UsersAppModel {
public $displayField = 'email';
}
use
class User extends AppModel {
public $displayField = 'email';
}
First check your code syntax
it should be
class Shipment extends AppModel {}
and
class User extends AppModel{}

CakePHP: using a different users table

After setting up the simple Cakephp login concept I would like to let CakePHP use a different table to check the users and the login. I can't figure out how to change the table name within the Auth-component.
Below my basic Controller. How can I let Cakephp know it has to look into a different database table?
class AppController extends Controller {
public $components = array(
'Session',
'Auth'=>array(
'loginRedirect'=>array('controller'=>'users', 'action'=>'index'),
'logoutRedirect'=>array('controller'=>'users', 'action'=>'index'),
'authError'=>"You can't access that page",
'authorize'=>array('Controller')
)
);
public function isAuthorized($user) {
return true;
}
public function beforeFilter() {
//$this->Auth->allow('index', 'view');
$this->set('siteCategory', 'home');
$this->set('logged_in', $this->Auth->loggedIn());
$this->set('current_user', $this->Auth->user());
}
}
Best Solution:
This is something that's done in the User model with the useTable property.
I.e. in app/Model/User.php you should have something like this:
class User extends AppModel {
public $useTable = 'table_name';
//... rest of Model stuff here
}
Alternative:
Alternatively you can specify a different model to be used for the user, although I don't think that's what you're asking for. If I'm wrong there though, just set the userModel value like this:
public $components = array(
'Auth'=>array(
'authenticate'=>array(
'Form' => array('userModel' => 'ADifferentUserModel')
)));

CakePHP belongsTo relationship not saving

I have models 'PatientCase' and 'Procedure'. A case can have one/multiple procedures.
class PatientCase extends AppModel {
public $hasMany = 'Procedure';
}
class Procedure extends AppModel {
public $belongsTo = array(
'PatientCase' => array(
'className' => 'PatientCase'
)
);
}
I'm explicitly setting a value in my patientCasesController
$this->request->data["Procedure"]["side"] = 'left';
When i saveAll my patientCase, the case is saved correctly, and a new record is saved in the procedure table, with the corresponding patientCase id, however, no other data is saved in the record.
Can anyone see where i'm going wrong?
Your comment nailed it - save() only saves the main model, while saveAll() saves the main model and any associated models.
save() [details]
saveAll() [details]
Update:
Because it's "hasMany", you probably want:
$this->request->data["Procedure"][0]["side"] = 'left';
(notice the [0])

Cakephp belongsTo relationship - accessing related Model

I have a consultant table that has a foreign key 'specialty_id' which is linked to a 'specilaties' table.
class Consultant extends AppModel {
public $belongsTo = array(
'Specialty' => array(
'className' => 'Specialty',
'conditions' => array('Specialty.active' => 1)
)
);
}
class Specialty extends AppModel {
public $hasOne = 'Consultant';
}
I think this is right, however, i am unable to get a list of specialties from the consultant controller
("Call to a member function find() on a non-object ")
$this->set('specialties', $this->Specialty->find('all'));
Where abouts am i going wrong?
Thank you
Remember you are in the controller, not in the model. Try this:
$this->set('specialties', $this->Consultant->Specialty->find('all'));
If you are using Model in other controller then, first load that model and then run query:
$this->loadModel('Specialty');

How to use models without database on CakePHP and have associations?

I've got the field country_id in one of my models and instead of creating a countries table which contains a list of countries that doesn't change, what's the best approach to this?
I'm thinking about using a model without a database table but I don't know how to implement this.
Please help. Thanks in advance!
you can totaly use the no table syntax:
class ModelWithoutTable extends AppModel
{
var $useTable = false;
}
to have this Country Model tableless, but you need to mock a data source (i.e. XML,YAML,PHP Array and etc) for the countries data.
Hope this helps.
I would suggest using ArraySource from the community-maintained CakePHP Datasources plugin:
CakePHP 1.3.x - see master branch
CakePHP 2.x - see 2.0 branch
Download the entire plugin and extract the contents to app/plugins/datasources.
Define a connection to the datasource in app/config/database.php:
public $array = array('datasource' => 'Datasources.array');
This should allow you to emulate a table by defining records in your model:
class Country extends AppModel {
public $useDbConfig = 'array';
public $records = array(
array('id' => 1, 'name' => 'Test record')
);
}
As alternative, if there's no other data attached to the country besides, basically, an id of what country it is, you can probably keep it within the same model without association. Something along the lines of:
class MyModel extends AppModel {
public static $countries = array(
'Africa', 'America', ..., 'Zululand'
);
public $validate = array(
'country' => array(
'rule' => array('inList', self::$countries),
...
)
)
}

Resources