How to create relations in YII for 3 DB tables - php

I have 3 DB tables tbl_categories, tbl_items, tbl_items_categories like this:
tbl_categories fields: id (category id - primary key), name (category's name)
tbl_items fields: id (item id - primary key), name (item name)
tbl_items_categories fields: id (primary key), item_id (id field value from tbl_items), category_id (id field value from tbl_category)
Please note that one item can be in multiple categories (tbl_items_categories is being used for this purpose)
I have created 3 models (in YII) - categories, items, itemMultiCategories for these tables.
Can anyone please let me know how to create relations in YII for following purpose:
If I have an item id, I should be able to get all its category names (good to have category ids)
If I have category id, I should get all item names in that category (good to have item ids as well)
Thanks in advance.

You are not creating relations in Yii, you are doing it in the database.
Take a look at this answer.
After you created the relations, go into the gii (http://yourhost.com/?r=gii), and create all the models again. Don't forget to check the checkbox for relation creation.

What you have here is a many to many relationship bridged by an associative table (tbl_items_categories). This should be easily handled by Yii's many to many relational active record.
http://www.yiiframework.com/doc/guide/1.1/en/database.arr
For instance, to have a relationship in your items model that gets you all categories, you could do something like this:
public function relations()
{
return array(
'categories' => array(self::MANY_MANY, 'categories','tbl_items_categories(item_id, category_id)'),
);
}
The foreign key, tbl_items_categories(item_id, category_id), is just the name of your associative table with the table fields that will match your linked tables, in parentheses. Your fields should be listed in order, such that the field that will link to the primary key of the current model is listed first. My understanding is if you want to get items by category, the foreign key in the relationship in your category model will look like this: tbl_items_categories(category_id, item_id).
A note on your associative table:
You might consider removing the "id" field, since the combination of item_id and category_id is probably unique. Also, because the table only needs to be referenced in these relationship declarations, you probably don't need to set up a separate model for it.

Related

Change value of primary key on other table

I have question about changing value in child table automatically if value of table mother change value.
I have two tables are brand(mother) and cat(child).
I add foreign key is brand_id in table cat related to primary key id in table brand.
If I change brand_name from brand table, I also want brand_name in table cat changed automatically. Is it possible? and how can I do it.
Thank you so much.
Brand:
Cat:
You could create a custom trigger on the brand table which before update would perform the necessary updates on the cat table.
Here is a link to the documentation for MySQL triggers:
https://dev.mysql.com/doc/refman/8.0/en/create-trigger.html
UPDATE:
As commented by #kerbholz, proper data modeling would suggest that the brand name column shouldn't exist in the cat column as it creates duplication of data. If this is purely for your client to see the data, perhaps building them a custom view using properly modeled tables is a better solution.
Link to appropriate documentation:
https://dev.mysql.com/doc/refman/8.0/en/create-view.html

How to stop auto sorting in laravel pivot table of many to many realtion

I have a author table and a publication table. Both are related to each other in a many to many relation. When I'm inserting the publications the authors of the publications are inserted in the pivot table by the order of authors id. But I need to insert it by the order i'm selecting the authors in the front-end. Whatever the order of the authors in the front end is it is getting ordered by the author's id in the pivot table. How can i stop this automatic ordering
You can't add rows in a specific order into a pivot table, because it doesn't really make sense.
Let's consider an users table:
The first user you enter will have the id 1
The second will be assigned to the id 2
And so on...
So you can enter the users in a specific order and retrieve them by their id.
However, in a standard pivot table, the primary key is composed by two columns, in your case the author_id and publication_id. Nothing new is created here, you just associate the primary key of two existing rows in two differents tables in order to achieve one - and unique - composed primary key.
If i explained well (and i hope so :p), you should understand why saying
But I need to insert it by the order i'm selecting the authors in the front-end.
doesn't really make sense.
But, don't worry, it is still possible to achieve your goal here.
Instead of using a pivot table, you can use a normal table with an id. This way, the order of insertion will be preserved. It will work but that's not very nice.
A better approach would be to add an additional column to the pivot table. A column like position. This column could be incremented for each author you insert. Then, you can order the table by the position column, by simply adding ->orderBy('position') to your relationship or every queries that needs to.
Here is an example to illustrate what i said above:
foreach($authors as $position => $author)
{
$publication->authors()->attach($author, ['position' => $position]);
}
If $authors contains the authors in the order you selected them on the front-end, they will be added accordingly.
If you need to sync instead of attach, that's also possible, it's just a little bit more verbose:
$syncData = $authors->mapWithKeys(function($author, $position){
return [$author->id => ['position' => $position]];
});
$publication->authors()->sync($syncData);
Don't forget that you can add false as a second parameter on the sync method so it'll only add new authors.
After that, just change your authors relationship in your Publication model like this:
public function authors(){
return $this->belongsToMany(Author::class)->orderBy('position');
}
Or everywhere you need to:
$publication->authors()->orderBy('position')->get();
I hope it helps !

how to define many to many relationship in laravel models?

I have two master tables. i.e, users and tasks. Primary key column names are in_user_id for users table and in_task_id for tasks table.
There is relational table users_tasks (to see a task are assigned to which users and a user is assigned with which tasks). Foreign key columns are in_task_id and in_worker_id in users_tasks table.
I want to define relationship of users and tasks (many-to-many) into both models. I have read this doc. But in my case, primary key column is in_user_id in users table. But foreign key column name is in_worker_id in users_tasks table.
So I don't know that how to handle fourth parameter in relationship function (return $this->belongsToMany('App\User', 'users_tasks', 'in_task_id', ?); in Task Model file). Either in_user_id or in_worker_id or something need to define more. If anyone knows the solution, it will be appreciated.
From laravel eloquent documentation on many-to-many relationships
In addition to customizing the name of the joining table, you may also customize the column names of the keys on the table by passing additional arguments to the belongsToMany method. The third argument is the foreign key name of the model on which you are defining the relationship, while the fourth argument is the foreign key name of the model that you are joining to:
In your case it would be :
return $this->belongsToMany('App\User', 'users_tasks', 'in_task_id', 'in_worker_id');
Now this assumes a few things:
Your user and task model are working properly (since you have non-conventional identifiers you've defined them in your models).
Not sure if its still the case but in previous versions of Laravel, your pivot table (in this case users_tasks) also needs it's own identifier column, typically an auto-incremented id.
Try this
$this->belongsToMany('App\User, 'users_tasks', 'in_worker_id ',
'in_user_id ');
params -> model, relation table, foreignkey, primary key
And also relation tables should be in the alphabetical order. (best way)
It must be tasks_users

ATK4: No unique column in table

How do you implement a model based off of a database table that has no single column primary key? The table has a composite primary key but no unique column. I want to create a model with this table as its primary table, but as far as I can tell the model requires a unique id field.
The table holds custom field values for services and consists of the following 3 columns: field_id, service_id, value. I need to be able to reference all of the custom field values that exist for a service and also to reference all of the services linked to a particular value.
The two main problems I'm having are..
1) Constructing a model based on the custom fields values table which has no unique column
2) Accomplishing a join with two 'ON' conditions. For example:
services JOIN fields ON
services.id = field.service_id
JOIN values ON
field.id = values.field_id AND
values.service_id = services.id
1) See my and Romans answers in following question some days ago: Junction Table with mutiple primary keys
2) That's simple - you should add next join not to model itself, but to previous "join"
$j_fields = $services_model->join('fields');
$j_values = $j_fields->join('values'); // $j_fields here not $services_model
You an also define second condition (values.service_id=services.id) somehow, but to tell the truth I don't have working example ready to post. You have to use $model->dsql->andExpr() as far as I remember.
I guess you can make it using addCondition (moving that condition to WHERE) or by using DSQL, too.

Resolving many to many relationship MYSQL database

I have 3 tables,
users(id) , userproduct (user_id,product_id) and product (id).
When a user adds a product their user_id and the product_id is saved in USERPRODUCT table.
Now at the same time another user can save a product (kind of like "set as favorite") for this I need to save the user_id of the user who saved it and the product_id of the product. This will create another table (call it favorites) however this table is also a resolve to the many to many relationship between "users" table and "product" table.
the question: is it possible for this, to have 2 tables resolving a many to many relationship or is there any other way to solve my issue.
if it is possible how will one be draw this in the ER diagram
it depends on what you want.
you may use only one table and design your relations with boolean fields
USERS(id)
PRODUCTS(id)
USERPROD(userid, productid, isbought, isfavorite, isowned)
or you may use one many-to-many support table for every relation is up to you
maybe you want another field "owner" in PRODUCTS table to store the user id. this is a one-to-one relation
What you want to do is actually describe the kind of relation between user and product: a favorite, or he 'owns' it.
Just add another field to the userproduct-table defining the relation: favorite or owned

Categories