Access pivotParent in Laravel - laravel

I have 3 tables :
langs : id (PK) , langname
lang_sector : lang_id (FK) , sector_id (FK) , sectorname ....
sectors : id (PK)
Here are the relations in Lang model
public function sectors(){
return $this->belongsToMany('App\Sector')
->withPivot('sectname','sectshortname','sectdescription','sectshortdescription')
->whereNull('lang_sector.deleted_at')
->withTimestamps();
}
Here are the relations in Sector model
public function langs(){
return $this->belongsToMany('App\Lang')
->withPivot('sectname','sectshortname','sectdescription','sectshortdescription')
->whereNull('lang_sector.deleted_at')
->withTimestamps();
}
I create an index method
public function index() {
$countLang = Lang::count();
$countSector = Sector::count();
$admins = Admin::all();
for ($i=1; $i<=$countLang; $i++) {
$langs = Lang::find($i);
$sectors[$i] = $langs->sectors()->get();
}
return view('admin.sectors.index', compact('admins', 'sectors', 'langs', 'countLang', 'countSector'));
}
In my front I have to reach for each sector, the langname which is in the lang table ... When I use the dd() method in the view
#foreach ($sectors as $sector)
#for($i=0; $i < $countSector; $i++)
{{ dd($sector[$i]->pivot) }}
#endfor
#endforeach
I obtain those result (abstract) :
Pivot {#684 ▼
+pivotParent: Lang {#636 ▼
#table: "langs"
#fillable: array:2 [▼
0 => "langname"
1 => "langisocode"
]
....
#attributes: array:6 [▼
"id" => 1
"langname" => "Français"
"langisocode" => "fr-FR"
"created_at" => "2018-02-06 08:19:24"
"updated_at" => "2018-02-07 18:56:21"
"deleted_at" => null
...
]
#original: array:6 [▼
"id" => 1
"langname" => "Français"
...
]
....
}
#foreignKey: "lang_id"
#relatedKey: "sector_id"
#table: "lang_sector"
#primaryKey: "id"
....
#attributes: array:8 [▼
"lang_id" => 1
"sector_id" => 1
"sectname" => "Technologies de l'information et de la Communication"
"sectshortname" => "TIC"
"sectdescription" => "description TIC"
"sectshortdescription" => "description TIC courte"
"created_at" => "2018-02-07 21:41:10"
"updated_at" => "2018-02-07 21:41:10"
]
....
}
It means that i can surelly reach the langs table and its columns... The question is "how can i do it" ...
Thanks for your answer

I see a logic problem
When the ids are continuously, it will work well
+-----+------------+
| id | langname |
| 1 | esp |
| 2 | esp2 |
| 3 | esp3 |
+-----+------------+
$ countLang = Lang :: count (); //3
The for route from 1 to 3
for ($i=1; $i<=$countLang; $i++) {
$langs = Lang::find($i);
$sectors[$i] = $langs->sectors()->get();
}
Here is the error, look at the id's
$countLang = Lang :: count (); //3
+-----+------------+
| id | langname |
| 1 | esp |
| 3 | esp2 |
| 4 | esp3 |
+-----+------------+
The for will never arrive at id = 4, because in the Lang::count(); is 3
Lang :: find (1) ok
Lang :: find (2) error
Lang :: find (3) ok
Read the documentation
https://laravel.com/docs/5.5/eloquent-relationships

You could use
$sector->pivot->fieldName;

Finally i rewrote my sql request ... What i want to diplay is the result of this request :
SELECT
sectors.*,
lang_sector.*,
langs.*
FROM sectors
INNER JOIN lang_sector ON sectors.id = lang_sector.sector_id
INNER JOIN langs ON lang_sector.lang_id = langs.id;
So i decided to use query builder :
$sectors = DB::table('sectors')
->join('lang_sector','sectors.id','=','lang_sector.sector_id')
->join('langs','lang_sector.lang_id','=','langs.id')
->select('langs.*', 'lang_sector.*', 'sectors.*')
->get();
Then in my view i don't have to use any pivot stuff
and just have to write this way :
#foreach($sectors as $sector)
{{ $sector->anyfieldfromrequest }}
#endforeach
Thanks for your answers... Mainly Samuel Loza who shows me the problems encountered by my first request

Related

foreach count only one result in form

I have this foreach
foreach ($categoryArr as $key => $value) {
foreach ($biciCorretta as $chiave => $valore) {
$biciSingola = $valore;
$contatoreqty =1;
if ($biciSingola->category_id = $key && $contatoreqty <= $value) {
if (!in_array($biciSingola,$biciSelezionata, true)) {
array_push($biciSelezionata, $biciSingola);
}
$contatoreqty ++;
}
}
echo "$contatoreqty <br>";
}
this is dd $categoryAarr:
array:1 [▼
1 => "1"
]
to be precise
array:1 [▼
1(category id) => "1"(quantity request)
]
this is the dd of $biciCorretta (are the bikes I have in that category):
array:2 [▼
0 => App\Models\Bike {#1461 ▶}
1 => App\Models\Bike {#1459 ▶}
]
if the category of the single bike is correct and the quantity ($ value) is less than or equal to the counter
push the bike into the array.
I expect there is only one bike in the $biciSelezionata array as the quantity required is only one
instead the result is the following:
array:2 [▼
0 => App\Models\Bike {#1461 ▶}
1 => App\Models\Bike {#1459 ▶}
]
there is a problem on your condition
if ($biciSingola->category_id = $key && $contatoreqty <= $value) {
The condition here must be ==
Write if ($biciSingola->category_id == $key && $contatoreqty <= $value) { instead
And its important where you initiate your $contatoreqty variable.
it will always be 1 if condition fails

Find child by ID from collection of parent laravel

I have Parent - Child relationship
Parent Model
public function child() {
return $this->hasMany(Child::class);
}
Child Model
public function parent() {
return $this->belongsTo(Parent::class);
}
App
I am getting the parent collection which I am using elsewhere
$this->parent = Parent::where('active', true)->with('child')->get()
The Problem
I have a on-click function where i'm getting just the ID of the child. So i'm trying to find the child in the parent collection.
public function click($id) {
$child = $this->parent->child()->find('id', $id)->first();
}
Error -
Method Illuminate\Database\Eloquent\Collection::child does not exist.
Is it possible to get the child from the existing collection, I know I could do another db query but really not wanting to make another query as I already have the data just there.
$this->parent->toArray()
array:2 [▼
0 => array:11 [▼
"id" => 1
"active" => 1
"name" => "Foo"
"child" => array:3 [▼
0 => array:3 [▼
"id" => 1
"parent_id" => 1
"name" => "S/M"
]
1 => array:3 [▼
"id" => 2
"parent_id" => 1
"name" => "L/XL"
]
2 => array:3 [▼
"id" => 3
"parent_id" => 1
"name" => "2XL"
]
]
]
You can use where condition to find using child id
$this->parent->where('child.id', $id)->first()
if you are looking to find parent id then
$this->parent->find($id)
you have hasmany data so
$this->parent->filter(function ($value)use($id){
return $value->child->find($id);
})->first();

Sum collection variables

i have the next collection:
It is grouped by zone and fundo and I need to sum all the sup_ha that each fundo contains
$transporFundo = $tansporCollect->groupBy(['zona','fundo']);
foreach ($transporFundo as $fundo) {
$supFundo = $fundo->sum('sup_ha');
dd($supFundo);
}
that is to say that for example of my collection for zona 1 and fundo 805 I would have to add the sup_ha field of the 364 records that are seen.
I tried to do it but I don't know how to access the field, as seen in my code I tried and it returns 0.
I hope you can help me, thanks
**
UPDATE
**
ok, remove the group by, for example show a collection like the following, the original has 700k of records
Illuminate\Support\Collection {#778646 ▼
#items: array:4 [▼
0 => array:3 [▼
"zona" => 1
"sup_ha" => 20
"fundo" => 805
]
1 => array:3 [▼
"zona" => 1
"sup_ha" => 10
"fundo" => 805
]
2 => array:3 [▼
"zona" => 2
"sup_ha" => 5
"fundo" => 800
]
3 => array:3 [▼
"zona" => 2
"sup_ha" => 10
"fundo" => 900
]
]
}
so, I need the sum of the sup_ha of equal fundo, like this:
fundo | sum
805 | 30
800 | 5
900 | 10
And I need the sum of the sup_ha of equal zona, like this:
zona | sum
1 | 30
2 | 15
Given this, that's why I had made a group by to calculate the sum of the fundo's. so now I don't know whether to think if it was right to do it like this
I hope you have clarified
Assuming your collection is assigned as $collection
$zonaArray = [];
$fundoArray = [];
$sum = 0;
foreach ($collection as $key => $t) {
if (!in_array($t['zona'], $zonaArray)) {
$zonaArray[$key]['zona'] = $t['zona'];
$zonaArray[$key]['sum'] = (float) $t['sup_ha'];
} else {
$zonaArray[$key]['sum'] = (float) $t['sup_ha'];
}
if (!in_array($t['fundo'], $fundoArray)) {
$fundoArray[$key]['fundo'] = $t['fundo'];
$fundoArray[$key]['sum'] = (float) $t['sup_ha'];
} else {
$fundoArray[$key]['sum'] = (float) $t['sup_ha'];
}
}
$checkzona = [];
$value = 0;
$finalZone = [];
$i = 0;
foreach ($zonaArray as $key => $val) {
if (in_array($val['zona'], $checkzona)) {
unset($finalZone[$i - 1]);
$val['sum'] = $value + (float) $val['sum'];
$finalZone[$i] = $val;
$i++;
} else {
$checkzona[] = $val['zona'];
$value = $val['sum'];
$finalZone[$i] = $val;
$i++;
}
}
Your zone wise sum output is looking like below.
array:2 [▼
1 => array:2 [▼
"zona" => 1
"sum" => 30.0
]
3 => array:2 [▼
"zona" => 2
"sum" => 15.0
]
]
For fundo sum:
$checkfundo = [];
$valuefundo = 0;
$finalFundo = [];
$k = 0;
foreach ($fundoArray as $key => $fundo) {
if (in_array($fundo['fundo'], $checkfundo)) {
unset($finalFundo[$k - 1]);
$fundo['sum'] = $valuefundo + (float) $fundo['sum'];
$finalFundo[$k] = $fundo;
$k++;
} else {
$checkfundo[] = $fundo['fundo'];
$valuefundo = $fundo['sum'];
$finalFundo[$k] = $fundo;
$k++;
}
}
Your fundo wise sum output is looking like below.
array:3 [▼
1 => array:2 [▼
"fundo" => 805
"sum" => 30.0
]
2 => array:2 [▼
"fundo" => 800
"sum" => 5.0
]
3 => array:2 [▼
"fundo" => 900
"sum" => 10.0
]
]
I hope it's working for you.
Assuming your collection is assigned to $collection.
so, I need the sum of the sup_ha of equal fundo.
High order functions
return $collection->groupBy('fundo')->map->sum('sup_ha');
Alternative
return $collection
->groupBy('fundo')
->transform(function (Collection $sub) {
return $sub->sum('sup_ha');
});
It prints
{
"805": 30,
"800": 5,
"900": 10
}
And I need the sum of the sup_ha of equal zona
High order functions
return $collection->groupBy('zona')->map->sum('sup_ha');
Alternative
return $collection
->groupBy('zona')
->transform(function (Collection $sub) {
return $sub->sum('sup_ha');
});
It prints
{
"1": 30,
"2": 15
}

use sync method for an array and also add extra pivot fields?

This is my input array
"events" => array:2 [▼
"special-date" => array:3 [▼
0 => "14-Nov-1979"
1 => "18-Apr-1981"
2 => "12-Nov-1978"
]
"event" => array:3 [▼
0 => "2"
1 => "3"
2 => "4"
]
]
This is my code
$User->events()->sync($request->events['event'], ['event_date' => $request->events['special-date']]);
here, $user is an instance of the user model
This is my user model realtion function
public function events()
{
return $this->belongsToMany('App\Models\Event', 'user_events', 'user_id', 'event_id')->withPivot('event_date');
}
and I got an error of event_date has no default value.
my table structure of a user_event table is
id,
user_id,
event_id,
event_date

Laravel 5.4: concat data from related table in pluck

I am writing an assignment system for radio newscasts. The data tables:
station
id | calls
---| -----
1 | cxri
newscast
id | name_input | for_station_id
---|------------|---------------
1 | am | 1
assignment
id | newscast_id | user_id
1 | 1 | 5
The controller for Assignment.edit is as follows:
if (! Gate::allows('assignment_edit'))
return abort(401);
}
$relations = [
'anchors' => \App\User::get()->pluck('name', 'id')->prepend('Please select', ''),
'casts' => \App\Newscast::get()->pluck('name_input', 'id')->prepend('Please select', ''),
];
return view('assignment.create', $relations);
The Newscasts model:
public function for_station()
{
return $this->belongsTo(Station::class, 'for_station_id')->withTrashed();
}
Right now I get
"casts" => Collection {#451 ▼
#items: array:2 [▼
"" => "Please select"
1 => "am"
]
}
I want
"casts" => Collection {#451 ▼
#items: array:2 [▼
"" => "Please select"
1 => "cxri-am"
]
}
How do I make that happen?
Or should I denormalize the data and make name_input 'cxri-am' instead of 'am'?
What I've tried:
Accepted answer in Laravel pluck fields from relations
'casts' => \App\Newscast::with('station')->get()->pluck('name_input', 'id'),
errors with
Call to undefined relationship [station] on model [App\Newscast]
I included the Newscast model above based on the discussion in Laravel: get/show data from related tables. Based on that discussion it appears to me the newscast should already be able to access the Station calls. But as shown above, the calls are not in $casts.
You are close with what you have tried. The with() function needs the name of the relation function, not the table, so this should work for getting the relation model loaded:
'casts' => \App\Newscast::with('for_station')->get(),
As for getting the data to concat the way you want, I would make an accessor on the Newscast model that will return the data you want:
function getNameInputStationAttribute() {
return $this->for_station->calls . "-" . $this->input_name;
}
You would then use this like:
'casts' => \App\Newscast::with('for_station')->get()->pluck('name_input_station', 'id')->prepend('Please select', ''),
If I could point out a few other things, the return code of 401 indicates Unauthenticated whereas 403 indicates Unauthorized which would be more applicable to the Gate returning false. Also, class functions should be cammel case, so your for_station function should be forStation or even just station.

Resources