How to save inherited objects in cakephp - cakephp

I have implemented inheritance in cakephp . I have two models Person and Employee. Employee inherits Person
Person: id, name, age, address
Employee: id, person_id
when i do $this->Employee->savAll($this->request->data), Person and Employee are saving but the person_id is not getting set in database, Its being filled by NULL, Is there any way to save the inherited objects properly at one shot, The models are shown below
Class Person extends AppModel{
var $name="Person";
}
App::import('model', 'Person')
Class Employee extends Person{
var $name="Employee";
public $actsAs = array( 'Inherit' );
}

From the Saving Your Data docs,
The saveAll function is just a wrapper around the saveMany and saveAssociated methods
You are saving neither many of one model, nor associated models. You will need to save the parent model, retrieve the ID, and use that to save the inheriting model.

Related

Eloquent relation with where condition on model attribute

I have two models Student and StudentRevision with Student model having hasMany relation with StudentRevision model. I have defined a hasMany relation in Student as
public function revisions()
{
return $this->hasMany(
'StudentRevision',
'sid'
);
}
I have a field in students table (Student model) which references current revision of student from student_revisions table.
The table structure is something like this.
students sid srid name ....
student_revisions srid sid batch ....
Now i want to define hasOne relation with StudentRevision model which references current revision linked with Student. Currently I have defined this relation as:
public function current()
{
return $this->hasOne(
'StudentRevision',
'sid'
)
->where('srid', $this->srid);
}
But the problem with this relation is, that $this->srid is not available during query building process and can be only there after the actual model is available.
Please help how to overcome this.
I don't think you can define it as relation. But what you can do is this:
public function current(){
return $this->revisions()->where('srid', $this->srid)->get();
}
This way you can access it by $student->current(). You can even go a bit further and make it more relationship like:
public function current(){
return $this->revisions()->where('srid', $this->srid);
}
public function getCurrent(){
return $this->current()->get();
}
protected $appends = array('current');
Here we define an accessor for our attribute. Laravel Docs (scroll down to the bottom)
We can then use it like this:
$student->current; // retrieves the model
$student->current(); // retrieves an instance of the query builder

cakephp changes when changing the name of the database table

I work in cakephp, I have a database table named 'movements' I want the named 'movements_bags' what changes need to be made​​:
- The model
-the controller
-folder view
To use a table with a name that is outside the CakePHP table naming convention (e.g. Movement model has table names movements, but you want to use the table named movements_bags) you simply specify which table name to use in your model with the $useTable property:
class Movement extends AppModel {
var $useTable = 'movements_bags'; // default would be movements
// ...
}
I prefer Scrowler answer, but if you are not happy with this answer you can try bellow code.
change controller name to MovementsBagsController.
And change controller class name
class MovementsBagsController extends AppController {
}
Change your model name to MovementsBag
and change model class name
class MovementsBag extends AppModel {
}
change view folder to MovementsBags
I think that will work fine now.

Cakephp inheritance of model associations

If I create a Model Car with some associations:
hasOne Driver
hasMany Wheel
And then create a Model Truck extending Car with
class Truck extends Car { ... }
is it normal that the associations from Car are not inherited from Truck?
What are the possibilities to inherit model associations?
Thanks in advance!
Inheritance is PHP related; your custom classes will behave the same way regardless of anything in cakephp. Class inheritance in CakePHP is completely depended on How your classes are written. Inheritance is an important part of cakephp; the framework is very much object oriented.
Are you including the classes properly using App::uses() to load your car class into truck?
The only way your Truck class will not inherit from the Car class is if you have defined the properties in the Truck class.
class Car extends AppModel {
public $hasOne = array('Driver', ...);
}
class Truck extends Car {
public $hasOne = array(); // now you have no hasOne relations
}

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.

CakePHP Unit belongsTo Complex, but not all Unit has Complex?

I have a 'Complex' model which hasMany Unit. My model associations are correct, everything works, it's just that I am having trouble getting a different model/association working correctly and it has made me wonder if I need to set this model up differently.
See, not ALL Unit will have a Complex associated with it. Some Unit are houses, some Unit are hotel rooms, and some Unit are just rental companies.
Because Complexes haveMany Units I am tempted to leave it alone, but I am wondering if I shouldn't redefine the relationship as Complex belongingTo Unit. I am trying to not repeat myself in my database with adding in multiple instances of the same complex.
Here is my current Unit Model:
class Unit extends AppModel {
public $name='Unit';
public $belongsTo=array(
'User'=>array(
'className'=>'User',
'foreignKey'=>'user'
),
'Complex'=>array(
'className'=>'Complex',
'foreignKey'=>'complex_id'
)
);
public $hasOne=array(
'Location'=>array(
'className'=>'Location',
'foreignKey'=>'location_id'
)
);
}
and here is my current Complex model:
class Complex extends AppModel {
public $name='Complex';
public $hasMany=array('Unit');
public $hasOne=array(
'Location'=>array(
'className'=>'Location',
'foreignKey'=>'location_id'
)
);
}
By the way, 'Location' is the model I am having trouble with (the Location part of my array currently returns empty when I call my unit/complex information in my view, so I need to get my association right).
If the Unit is a condo with a complex, I want it to return the Location of Complex. If it is a house or hotel or rental company, I want it to return the Location of Unit. I have to do several of these associations (images, location, and so forth) so I want to get everything straight right up front.
Is my current relationship between Unit and Complex correct or do I need to define everything differently?
UPDATE Here is my controller logic:
$this->paginate['Unit']=array(
'limit'=>9,
'order' => 'RAND()',
'contain'=>array(
'User'=>array(
'email'),
'Complex'=>array(
'id','complex_name', 'realname', 'photo1','photo2','photo3','photo4','photo5'),
'Location'=>array(
'complex_id','address', 'city','state','zip','area_code','exchange','sln','lat','lon','website')
),
'conditions'=>array(
'Unit.type'=>array('condo', 'rentalco'),
'Unit.active'=>1)
);
$data = $this->paginate('Unit');
$this->set('allcondos', $data);
}
And you can see the result I get here:
I am not currently interested in displaying a view of all Complexes, but the index page logic does have ContainableBehavior limited to just Complex(as originally I was going to have views for various Complexes):
public function index() {
$this->Complex->Behaviors->attach('Containable');
$this->Complex->contain();
$c=$this->Complex->find('all');
$this->set('complexes', $c);
}
UPDATE I have it working now, for anyone who encounters this problem. I had to change Location to the root and make Complex belongTo Location. Here are my models updated:
class Location extends AppModel {
public $name='Location';
public $hasMany=array('Complex', 'Unit');
var $belongsTo=array(
'Restaurant'=>array (
'className'=>'Restaurant',
'foreignKey'=>'restaurant_id'
)
);
}
class Complex extends AppModel {
public $name='Complex';
public $hasMany=array('Unit');
public $hasOne=array('Image');
public $belongsTo=array(
'Location'=>array(
'className'=>'Location',
'foreignKey'=>'location_id'
)
);
}
class Unit extends AppModel {
public $name='Unit';
public $belongsTo=array(
'User'=>array(
'className'=>'User',
'foreignKey'=>'user'
),
'Complex'=>array(
'className'=>'Complex',
'foreignKey'=>'complex_id'
),
'Location'=>array (
'className'=>'Location',
'foreignKey'=>'location_id'
),
);
public $hasOne=array('Image');
}
Many thanks to Wylie for the help, this was a doozy!
http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html?containing-deeper-associations#containing-deeper-associations
When using ‘fields’ and ‘contain’ options - be careful to include all foreign keys that your query directly or indirectly requires. Please also note that because Containable must to be attached to all models used in containment, you may consider attaching it to your AppModel.
You can do that in your AppModel like this: public $actsAs = array('Containable');
You don't have to use Contain when you don't want to so it shouldn't get in the way.
When a model A has model B, you use the foreign key within model B. So your foreign key on the Location should be complex_id. Although, that shouldn't be so because not all units have a complex.
It seems to me you should make the Location the "root". So, Complex belongsTo Location and Unit belongsTo Complex and Location. Then Location hasOne/Many complex, etc. Either that or just put the address columns in the Unit/Complex tables.

Resources