I am looking at YII for the first day, and i'm having some problems trying to work out the relations between some tables.
my table structure is as follows:
Pets:
pet_id
pet_name
....
Pet_Owner_Link
pet_id
owner_id
Owner:
owner_id
owner_name
How would I go about getting all of the pets that belong to an owner? Really struggling to get my head around the AR relations at the moment.
Per this comment by DD.Jarod on the Yii AR documentation page: http://www.yiiframework.com/doc/guide/1.1/en/database.arr#c970
"If you declare a many to many relationship, the order of keys inside the jointable declaration must be 'my_id, other_id':
class Post extends CActiveRecord
{
public function relations()
{
return array(
'categories'=>array(self::MANY_MANY, 'Category',
'tbl_post_category(post_id, category_id)'),
);
}
}
class Category extends CActiveRecord
{
public function relations()
{
return array(
'Posts'=>array(self::MANY_MANY, 'Post',
'tbl_post_category(category_id, post_id)'),
);
}
}
So your code would look like:
class Owner extends CActiveRecord
{
public function relations()
{
return array(
'pets'=>array(self::MANY_MANY, 'Pet',
'tbl_post_category(pet_id, owner_id)'),
);
}
}
class Pet extends CActiveRecord
{
public function relations()
{
return array(
'owners'=>array(self::MANY_MANY, 'Post',
'tbl_post_category(owner_id, pet_id)'),
);
}
}
Your problem may be that your primary keys for Pet and Owner by default should be id (not pet_id / owner_id). Yii may be getting confused if you don't clarify that your primary keys don't match the default naming convention / aren't setup as primary keys in the database. You can specify what your primary key is in a model like this:
public function primaryKey()
{
return 'owner_id';
}
Finally, you would retrive the information like this:
$owner = Owner::model()->findByPk((int)$id);
foreach($owner->pets as $pet)
{
print $pet->name;
}
I know this is not exactly what you ask, but this is how I do it.
Add this item in your relations() return in Owner model :
'all_pets'=>array(self::HAS_MANY, 'Pet_Owner_Link','owner_id'),
Add this item in your relations() return in Pet_Owner_Link model :
'pet'=>array(self::BELONGS_TO, 'Pet', 'pet_id'),
Then get a pet like this
$owner->all_pets[$i]->pet;
Related
I have two tables, work_order and project. On the project records, there is a work_order_id field. There is no project_id on the work_order records. Do I need to add one?
Or is there a way to define these relationships using hasOne/belongsTo?
I've tried:
class WorkOrder extends \Phalcon\Mvc\Model {
public function initialize() {
$this->hasOne('id', Project::class, 'work_order_id');
}
}
class Project extends \Phalcon\Mvc\Model {
public function initialize() {
$this->hasOne('work_order_id', WorkOrder::class, 'id');
}
}
I can retrieve the WorkOrder from the project like so: $project->workOrder, but I cannot retrieve a Project from a WorkOrder using $workOrder->project. I want a bidirectional relationship.
How do I do this?
Try adding the alias parameter, since the implicit retrieval might try to use the class name and it wouldn't support namespaces in your models.
I found it quite bogus in phalcon 1/2/3 to work with hasOne. I've been using belongsTo since then until I re-wrote the pre-post-save part of the phalcon relationship manager for my personal needs. Keep in mind that belongsTo will be saved before the main model you are working with, other types of relationships will be created/updated after the main record is saved. I choose to use "belongsTo" or "hasOne" depending on the order that I want the records and their relationships to be saved.
class WorkOrder extends \Phalcon\Mvc\Model {
public function initialize() {
$this->belongsTo('project_id', Project::class, 'id', ['alias' => 'Project']);
}
}
class Project extends \Phalcon\Mvc\Model {
public function initialize() {
$this->hasOne('id', WorkOrder::class, 'project_id', ['alias' => 'WorkOrder']);
$this->hasMany('id', WorkOrder::class, 'project_id', ['alias' => 'WorkOrderList']);
}
}
Implicit retrieval should start with a ucfirst camelized string of your class name, or using a get.
$workOrder = WorkOrder::findFirst();
$project = $workOrder->Project;
$project = $workOrder->getProject(['deleted <> 1']);
$workOrderList = $project->WorkOrderList;
$workOrder = $project->WorkOrder;
$workOrder = $project->getWorkOrder(['deleted <> 1', 'order' => 'projectId desc']);
So I have two Laravel/Eloquent models, and I want to add one more field to one of them.
Model 'Car' gets data from table 'cars' and has fields 'id', 'model', 'color' and 'price'. Model 'Person' has fields 'id', 'name' and 'car_id', which is foreign key from 'cars' table. I want model 'Person' to have a field named 'car', which would contain car model from 'Car' model, depending on existing car_id. I've tried something like:
use App\Models\Car;
class Person extends Model {
protected $car = array(Car::find($this->car_id));
}
But that was unsuccessful (errors like 'syntax error, unexpected '(', expecting ')''). What could be the solution? Thanks!
You need to define One-To-Many relationship first. Then get car model for the person:
$carModel = Person::find($personId)->car->model;
Take a look at Eloquent Relationships. What you are trying to do is to create a relationship between Car and Person models. It is up to you if a person can own one or multiple cars. I am suggesting you to let a person have multiple cars.
So, the Person model should know that it has multiple cars:
class Person extends Model
{
public function cars()
{
return $this->hasMany(App\Car::class);
}
}
A car belongs to a person, so the model should know that:
class Car extends Model
{
public function person()
{
return $this->belongsTo(App\Person::class);
}
}
Of course, when creating the tables you should add the field person_id to the CARS table.
Well, what I needed was:
protected $appends = ['car'];
public function getTypeAttribute($car)
{
return Car::find($this->car_id)->model;
}
It was all about serialization and 'protected $appends', thank you all :)
That's not how its done.
The person can have a car (or many). Let's suppose that every person have one car in your database, your car table should have a nullable person_id column, and add this to your User model
public function car() {
return $this->hasOne('App\Role');
}
Now you can get the person and the his car information's like this
User::where('id',$id)->with('car')->get();
I hope you get the point here
I have 2 tables, categories(id, name) and products(id, categoryId, title, content) and my models look like this
class Category extends CActiveRecord {
public $id;
public $name;
public function tableName() { return 'categories'; }
public function relations() {
return array('products' => array(self::HAS_MANY, 'Product', 'categoryId'));
}
}
class Product extends CActiveRecord {
public $id;
public $title;
public $content;
public function tableName() { return 'products'; }
}
The problem is when I try to access the products like this
Category::model()->with('products')->findAll()
The relation "products" in active record class "Category" is specified with an invalid foreign key "categoryId". There is no such column in the table "categories".
I looked at the documentation with the User / Post example and don't understand why my example is not working. Can someone clear things up please? Thank you.
Make sure that product table has field called categoryId in order to save the primary key of category table
Try specifing categoryid instead of categoryId. The reason can be in lower_case_table_names mysql directive.
There are 2 simple tables (MyIsam):
Child:
id(PK),
name,
land_id(FK)
Land:
id(PK),
name
These are the both Models (excerpt):
Following changes has no effects, if I modify the Models and let create the crud-forms, there are no changes and die land_id is getting no data from land table:
Model Child.php (excerpt)
class Child extends CActiveRecord
{
...
public function relations()
{
return array(
'land_id'=>array(self::BELONGS_TO, 'Land', 'id'),
);
}
...
}
Model Land.php
class Land extends CActiveRecord
{
...
public function relations()
{
return array(
'id'=>array(self::HAS_MANY, 'Child', 'land_id'),
);
}
...
}
Where is my mistake ?
EDIT: Do I need some more work, to get a select box with the corresponding land list in the created insert form (via CRUD) ?
thank you..
MySQL’s MyISAM engine does not support foreign keys at all.
Use InnoDB!
I'm new to Laravel and ORMs in general, so this is probably a very basic concept that I'm missing. I have three tables that I'm trying to define a relation with using Laravel 4's Eloquent ORM. Here's the slimmed-down table definitions:
stores
id (PK)
name
postal_codes
id (PK)
postal_code
city
state
country
locations
id (PK)
store_id (FK => stores.id)
postal_code_id (FK => postal_codes.id)
*additional location-specific fields such as address, phone #, etc
The stores table has a one to many relationship with the locations table, so I can use $this->hasMany("Location") in the Stores model, and $this->belongsTo("Store") in the Location model.
My question is, how do I define the relation between locations and postal_codes in their respective models? The locations table has a many-to-one relationship with the postal_codes table. Ideally I want to be able to do something like this: $store->locations()->first()->city. Is this possible?
Aren't you looking for something like:
class Locations
{
public function city()
{
return $this->belongsTo('PostalCode');
}
}
So now you can call $store->locations()->first()->city. This will return a PostalCode model, if you want to return just the city:
public function getCity()
{
return $this->city()->city;
}
And then you call $store->locations()->first()->getCity().
You could go further and create a __get() magic method so it calls everything dynamically.
It sounds like you have a many-to-many relationship between Stores and Postal_Codes. This would be demonstrated this way in Laravel:
class Store extends Eloquent {
public function postal_codes() {
$this->belongsToMany('Postal_Code', 'location');
}
}
class Postal_Code extends Eloquent {
public function stores() {
$this->belongsToMany('Store', 'location');
}
}
For more info, try this link: Laravel Many-to-Many Relationships.
I believe you are looking for a polymorphic relation.
Modify your locations table to include id, imageable_id, imageable_type, and then whatever additional location information you need. The imageable_id field will contain the ID of whatever you are looking for in it's respective table and the imageable_type will be whatever the name of that model for that table is.
On your models...
Class Location extends Eloquent
{
public function imageable()
{
return $this->morphTo();
}
}
Class Store extends Eloquent
{
public function locations()
{
return $this->morphMany('Location','imageable');
}
}
Class PostalCode extends Eloquent
{
public $table = 'postal_codes';
public function locations()
{
return $this->morphMany('Location','imageable');
}
}
And now, it's possible to retrieve all of the locations for the stores or postal codes with something like
$store = Store::find(1);
foreach($store->locations as $location)
{
//
echo $location->city;
}
$postalCode = PostalCode::find(1);
foreach($postalCode->locations as $location)
{
//
echo $location->city;
}