Insert array on multiple rows - laravel

I have a multiple select:
Form::select('color', array('1' => 'Red', '2' => 'Blue', '3' => 'Green', ... ), null, array('multiple'));
How can I insert these values into a table on separate rows, like this:
id | user_id | color
----------------------------
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 1 | 4
5 | 2 | 1
6 | 2 | 3
In the above example, user with an id of 1 selected 4 different values in the select and each was inserted on a separate row.
I have this working in this way:
foreach (Input::get('tags') as $key => $value)
{
$user_color = new UserColor;
$user_color->user_id = $user->id;
$user_color->color = $key;
$user_color->save();
}
Is there a better way of doing this? It seems odd using a foreach loop when it feels like Laravel should have some sort of built-in method of inserting multiple values on multiple rows.

As Laravel doc provided,
You may also use the sync method to attach related models. The sync
method accepts an array of IDs to place on the pivot table. After this
operation is complete, only the IDs in the array will be on the
intermediate table for the model:
In this case,
$colors = Input::get('tags');
$user->colors()->sync($colors);
Please make sure to set relation in your User model :
public function colors()
{
return $this->belongsToMany('Color');
}
You can also use attach method when you parameter is not array. To more clear, Here is difference between attach and sync.

Related

In Laravel I'm attempting to get the info from a table with a pivot

I currently have 3 tables:
medias, colors, media_colors
media_colors is the pivot table I'm trying to use it contains
media_id | color_id
------------------
1 | 1
in colors table I have
id | front
----------
1 | color
My model for medias contains:
public function mediaColors()
{
return $this->belongsToMany(Color::class, 'media_colors');
}
In a controller I attempt to query front like so:
$m = Media::find($estimate->media_id);
dd($m->mediaColors[0]->pivot->front);
This returns null. How would I be able to access this?
You can access the colors directly from the relation collection as marked in the comment.
$m = Media::find($estimate->media_id);
foreach($m->mediaColors as $color) {
//you can access all the colors here
$fronts[] = $color->front;
}
//or if you only want the first one (if it exists)
$m->mediaColors[0]->front
one easier way to get just the first value if you only need that
$m = Media::find($estimate->media_id);
$front = $m->mediaColors()->value('front');
// this will return null if no relation found without triggering an exception

Eloquent query adding a new field depending on a pivot table

I'm trying to make some query with Eloquent but cannot get the result I really want. Using Laravel 6.
I have the next tables:
Table Users:
id | user
============
1 | Andy
Table Colors:
id | color
============
1 | red
2 | blue
3 | white
4 | green
5 | black
Table user_colors:
id | user_id | color_id
==========================
1 | 1 | 1
1 | 1 | 4
What I want is something to get all the colors, but mark as active the ones in the pivot. Something like this:
id | color | active
====================
1 | red | 1
2 | blue
3 | white
4 | green | 1
5 | black
Any idea?
This should return a collection of Color objects with the one's associated with the given user given a property of active set to true
$user_colors = User::find(1)->colors;
$colors = Colors::all()->transform(function ($color) use ($user_colors) {
if ($user_colors->contain($color)) {
$color->active = true;
}
return $color;
});
Whilst this should achieve the result you need, without knowing the context in which you want to use it, it may be inefficient.
There are several ways to achieve this task. One of them could be to use appends in models.
Appends are attributes that you can dynamically add to your model class.
E.g. you can edit your Color model like this:
class Color extends Model {
// Your code...
protected $appends = ['active'];
public function getActiveAttribute() {
$is_active = UserColor::whereColorId($this->id)->first();
if (!is_null($is_active)) return true; // Or 1, up to you
return false; // Or 0, up to you
}
}
If you use this method, you can access to $color->active attribute.
Note that this is only one of the different methods that you can use to do this task.
Reference: Laravel Appends Documentation

pivot table with multiple columns in Eloquent

Here's my scenario:
I have a Event model and a Stage model, a event can have multiple stages and a stage could be assigned to multiple events. So Many-to-many. The thing is, a stage has a sort_order, and that sort_order could be different in each event. That's why I added the sort_order into the pivot table instead in, for example, the stage table.
table: events_stages
| event_id | stage_id | sort_order |
------------------------------------
| 1 | 1 | 1 |
| 1 | 2 | 2 |
| 1 | 5 | 3 |
The thing is when I'm going to relate the Stage with the events its in,
I'm doing something like in the StageController:
sending a post with events: [1,2,3] and sort_order: [1,1,2]
$relatedEvents = array();
foreach ($request->events as $key => $event)
{
$relatedEvents[] = array(
'event_id' => $relatedEventId,
'sort_order' => $request->sort_order[$key]
);
}
$stage->events()->sync(
$relatedEvents
);
but rely simply in the order of the post, doesn't seem like a really good idea.
Does anyone have a nicer solution?
Thanks!
Sometimes is better to create another model (and use it as a pivot) rather than use pivot table itself. You have more control. I'm not sure what exactly you want to achieve.

laravel Eloquent relationship using Distinct

I need show data with relationship using DISTINCT.
This is my sql data :
table pochettes
id |
49 |
table journees
id | formateurs_id | pochettes_id
1 | 3 | 49
2 | 4 | 49
3 | 3 | 49
table formateurs
id |
3 |
4 |
model Pochette
public function Journees()
{
return $this->hasMany('App\Journee','pochettes_id');
}
model Journee
public function Formateurs()
{
return $this->belongsTo('App\Formateur', 'formateurs_id');
}
I am used this code to show data with distinct formateurs because a Formateur can have many Journee in the same Pochette :
$pochette = Pochette::find(49);
foreach ($pochette->Journees->distinct('formateurs_id') as $formateur) {
echo $formateur->formateurs_id;
echo "<br>";
}
But this code dosn't work, I have this error message
**BadMethodCallException in Macroable.php line 81:
Method distinct does not exist.**
I would show this result :
3
4
not :
3
4
3
When you access an Eloquent relationship like a property, you will get an Eloquent Collection. However, distinct() is a Query Builder method and you need access to the Query Builder instance before returning the Collection. If you add () to the end of the relationship, you gain access to the Query Builder instance and can chain those Query Builder methods. In your case, you are actually looking for the groupBy() method and not distinct(). Don't forget to end the query with get().
foreach ($pochette->Journees()->groupBy('formateurs_id')->get() as $formateur) {
echo $formateur->id ;
echo "<br>";
}

Declarating a variable based on hashes

I have two databases: one is old and deprecated; the other one is new, working. Both of them have a table called brands.
In the deprecated database, the brands table is something like the following:
id | name
1 | Playstation 1
2 | Playstation 2
3 | Playstation 3
4 | Playstation 4
5 | Xbox
6 | Xbox 360
7 | Xbox One
In the new one, this is the brands table:
id | name
1 | Xbox
2 | Xbox 360
3 | Xbox One
4 | Playstation 1
5 | Playstation 2
6 | Playstation 3
7 | Playstation 4
In practice, the scenario is more complex, but the example I gave represents well. So, there's also a products table:
id | name | brand_id | created_at | updated_at
I want to import products from the old database to the new one, but the brands aren't matching by id as you saw. Then, I want to do something like this:
brand_id 1 on old_database == brand_id 4 on new_database
To be more specific, is kind of a dictionary without ifs.
This is what I've done:
if query.brand == 1
brand_id == 4
elsif query.brand == 2
brand_id = 5
end
But this isn't what I really want. Yes, it works, but I want to do something simpler. I think hashes are exactly what I'm looking for. Any suggestions?
You could declare a hash like this:
brand_map = {1 => 4, 2 => 5} # add other entries as needed
and then lookup the new id like this:
brand_id = brand_map[1]
=> 4
Yes, it seems that a hash is what you want. For example,
id_map = { 1=>4, 2=>5, ... } # old id => new id
then for a record id, name, write it to the new database as id_map(id), name.

Resources