Add field in a Gii form from another table - yii2

I have a table called child (id, name, sport_id), a table called sports (id, name), a table called parent (id, name) and a table called child_parent(id, child_id, parent_id).
I created the crud with Gii and I modified the child_parent to show not the id of the child and parent but the names, also made a dropdownlist for search and for the create form. But one thing I can't do is put an extra column on the index from called 'Sport', so I can filter childs/parents by sport. How can I do this?

Junction table is not necessary, you can use a self-referencing relation.
node ( id, parent_id, sport_id, name)
sport ( id, name )
With parent_id defaulting to NULL (root). If need be, you can add a rule or conditional visibility for fields that enforces children to have the same sport_id as the parent (unless its a root).
Now you can easily enable filtering by sport.
[
'attribute' => 'sport_id',
'filter' => Html::activeDropDownList(
$searchModel,
'sport_id',
ArrayHelper::map(Sport::find()->all(),'id','name'),
['prompt' => '']
),
'value' => function($model) {
return $model->sport->name;
}
],

Related

How to copy data with one value changed (Mysql)

I have table 'students' with 'ID, name, surname, <...>, class' columns.
I have students
1, Michael, Jordan, <...>, A
and
2, Dikembe, Mutombo, <...>, B
How can I duplicate the existing table data for all the students with class value set to B, but change the class to C.
IDs have auto_increment enabled.
EDIT: Also, is it possible to do this without explicitly typing all column names?
Here's how you do that:
INSERT INTO tableA
(name, username, ..., class)
SELECT name, username, ..., B
FROM tableA
So if you don't want to type all the columns names you could run the above query but with '*' so you copy all values, then get the ID of the first element and run an update query from that ID on wards to update the class value.
Or have look at something like this, which in my opinion sounds a lot more complicated than typing it all out.
Hope you find a solution mate.

using name column in belongsToMany relation instead of id

I have two Models one is Offer (for offers table) and other is Brand (for brands table). There is a "many to many" relationship between these models.
I have a table offer_brands that maps the relation between these two tables. In this table, I have offer_id column that links this table to offers table and brand column that links this table to the brands table usind brand_name column in brands table.
In Brand Model I want a relation that return all the offers.
I know I can do it like
public function offers()
{
return $this->belongsToMany(Offer::class, 'offer_brands', 'offer_id', 'brand_id'); // But don't have brand_id column insted I have brand column that contains brand names
}
Also, I have tried
public function offers()
{
return $this->belongsToMany(Offer::class, 'offer_brands', 'offer_id', 'brand'); // But Eloquent compare this column with id column of brands table.
}
Just in case if someone still looking for an answer .. here's how you can solve this issue.
For example I have roles for users. and the pivot table (team_users) has the user_id. But instead of containing the role_id it contains role column which basically is the slug of the role in roles table.
I can specify the relation exactly like this:
public function roles()
{
return $this->belongsToMany('App\Role', 'team_users', 'user_id', 'role', 'id', 'slug');
}
Basically App\Role is the relation model.
team_users is the pivot table name.
user_id is the foreign pivot key (So in team_users there will be a column called user_id)
role is the related pivot key (So in team_users there will be a column called role)
id is the parent key (So in App\User Laravel will look for the row whose id column value equals the foreign pivot key user_id in the pivot table).
slug is the related key (So in App\Role Laravel will look for the row whose slug column value equals role column in the pivot table)
The correct definition:
return $this->belongsToMany(Offer::class, 'offer_brands', 'brand', 'offer_id');
But it's a good idea to use naming conventions. You could name the table brand_offer and foreign keys as offer_id and brand_id. In this case, the relationship would look like this:
return $this->belongsToMany(Offer::class);
Learn more about Laravel naming conventions in my best practices repo.

Insert from another table and also insert new value

I have two tables, one of them is 'user_flag' and the other is 'playlist_data'.
I want to take all 'object_id' column entries of 'user_flag' and place them into the respective 'object_id' column of 'playlist_data', but only if those entries have '3' as the 'user' entry, and that they do not already exist (no duplicate 'object_id's!).
I tried to learn how to do it and this is what I found:
INSERT INTO playlist_data (object_id)
SELECT object_id FROM user_flag
WHERE user='3';
ON DUPLICATE KEY UPDATE object_id=object_id
Will this work properly?
But I'm also trying to do more at the same time, and I can't seem to find an answer:
1) I want to also insert new data with this. I want all of the newly inserted entries to also contain '5' in the 'filetype' column of 'playlist_data'.
Do I just
INSERT INTO playlist_data (filtype)
VALUES (5)
in the middle of all of this?
2) Both tables also have an 'id' column, will it automatically generate a new id followed from the latest 'id' of 'playlist_data'?
As in for example, I'm transferring from 'user_flag' an entry with the 'id' of '150', while the highest 'id' in 'playlist_data' is '63', will the inserted one by '64', or do I need to define that somehow?
Just add the value in the SELECT:
INSERT INTO playlist_data (object_id, filtype)
SELECT object_id, 5
FROM user_flag
WHERE user = 3
ON DUPLICATE KEY UPDATE object_id = VALUES(object_id);
Notes:
I am guessing that the id columns are numbers. Hence, I removed the single quotes.
I use VALUES(object_id) in the ON DUPLICATE KEY UPDATE.
It is important to have the semicolon only at the very end of the statement.

Insert ignore multiple columns data unique

Im curious if there is a way to insert into MySQL and avoid duplicates. I know there are three primary ways of accomplishing it. Either Replace, insert ignore or insert on duplicate key. I believe that each of these rely on a unique primary key which for me is a auto increment id field. This id field does not have any value for my particular inserting needs instead i want to check if a few fields contain the same value if not dont insure
ex:
INSERT INTO table (name, team, email) VALUES (:n, :t, :e)
if i had three data sets like so
1) array (":n" => "john doe", ":t" => 1, ":e" => john#doe.com);
2) array (":n" => "Jane doe", ":t" => 1, ":e" => john#doe.com);
3) array (":n" => "john doe", ":t" => 1, ":e" => john1#doe.com);
4) array (":n" => "john doe", ":t" => 2, ":e" => john1#doe.com);
Assuming there are no values in the table
1, 3 and 4 would be inserted but 2 would not as the team and email are not unique
I am aware i could create a fourth column and add the email and team to it and create a unique value and use this however i would prefer not to do so as it is redundant data .
Thanks
You can create an UNIQUE constrain
ALTER TABLE `tableName` ADD UNIQUE `unique_idx`(`name`, `team`, `email`);
If the id field has no value for you, don't bother with it. The desired behavior you're describing is that of a composite key, so make a composite key.
First, scrap the one that exists and is of no value...
ALTER TABLE YourTableName DROP PRIMARY KEY;
Then create the new composite one...
ALTER TABLE YourTableName ADD PRIMARY KEY (name, team, email);
You can try using DUAL
INSERT INTO table (name, team, email)
SELECT :n, :t, :e
FROM DUAL
WHERE :t NOT IN (SELECT team FROM table WHERE email = :e)

entity framework 4 many to many update

I have 3 tables -
User (Id, Name)
Roles (Id, Name)
UserRoles (UserId, RoleId)
I think they are self explanatory. How do I update an entry (UserId and RoleId) in UserRoles?
context.User.Roles gives me the list of roles but how do I update them?
Thank you.
From your comment:
context.User.Roles gives me the list
of roles. I can do a for-each and
update the Id, but how do I update the
corresponding UserId foreach RoleId in
that table?
First of all, you should NOT update the Id's.
Secondly, since you are using EF, you should try to think in terms of objects (or entities), rather than "DB-many-to-many-mapping-tables". Every User entity has a collection of Roles. If you remove a Role from the User.Roles collection and call context.SaveChanges(), the corresponding entry will be deleted from the UserRoles tabele. Similarly, when you add a Role object to the User.Roles collection, and save changes, a new entry will be created in the UserRoles table.
The following sample might be useful for clarity:
var user = context.Users.Include("Roles").Where(u => u.Name == "User1").FirstOrDefault();
user.Roles.Remove(user.Roles.Where(r => r.Name == "Admin").FirstOrDefault());
context.SaveChanges();
(null-reference checks omitted for simplicity).