Laravel: Check if Models have same relation - laravel

I have models: Partido and Coalicion related in a many to many relationship.
I need to know when two or more Coalicion has the same Partido related.
Hope I have explained myself.
Edit 1:
Model:
class Coalicion extends Model
{
public function partidos()
{
return $this->belongsToMany(Partido::class);
}
}
Let's say users selected some elements from a select input and I grabbed them in an array and send them to the controller.
...
public function example(Request $request)
{
$coaliciones = $request->coaliciones;
foreach ($coaliciones as $c) {
$coalicion = Coalicion::find($c);
# Here we have a list of Coalicion model in a loop
# Let's say the first iteration I can see the relationship
dump($c->partidos);
}
}
This for example give me the following answer at the browser:
Collection {#1 ▼
#items: array:2 [▼
0 => Partido {#271 ▶} #This is Partido with id 1
1 => Partido {#268 ▶}
]
}
Collection {#2 ▼
#items: array:3 [▼
0 => Partido {#279 ▶}
1 => Partido {#280 ▶}
2 => Partido {#283 ▶} #This is Partido with id 1
]
}
I need to know when the item 0 of the first Collection and the item 2 of the second Collection are the same.

I kinda found a way but I don't know if it's the correct or best approach.
In Coalicion model I add the following function:
public function partidosId()
{
return $this->partidos->pluck('id');
}
With this I can get only the id's from the relations, then in the controller I created an empty array() and fill it with all my ids with a foreach loop, then, finishing up I evaluated if the id's in the now filled array are unique, if the unique values are less than the length of the array then some models have the same relation (I don't know which but It's a start), e.g.:
public function example(Request $request)
{
$coaliciones = $request->coaliciones;
$allItems = [];
foreach ($coaliciones as $c) {
$coalicion = Coalicion::find($c);
$allItems = array_merge($allItems, $coalicion->partidosId()->toArray());
}
if (count(array_unique($allItems))<count($allItems)) {
dd("Duplicates");
}else{
dd("Uniques");
}
}
If anyone find a better way or a way to know which are the ones with the duplicate relation please let me know

Related

Sort an Eloquent model

Table for MyModel is like below
id name parent_id
--------------------------
1 parent1 null
2 p1-c1 1
3 parent2 null
4 p1-c1-g1 2
5 p2-c1 3
6 p1-c1-g1-f1 4
7 parent3 null
8 p1-c2 1
9 p3-c1 7
10 p1-c2-c1 8
How order with eloquent or raw DB query without getting all rows like below
Collection {#499 ▼
#items: array:22 [▼
0 => MyModel {#524 ▶} // parent1
1 => MyModel {#525 ▶} // p1-c1
2 => MyModel {#526 ▶} // p1-c1-g1
3 => MyModel {#527 ▶} // p1-c1-g1-f1
4 => MyModel {#528 ▶} // p1-c2
5 => MyModel {#529 ▶} // p1-c2-c1
6 => MyModel {#530 ▶} // parent2
7 => MyModel {#531 ▶} // p2-c1
8 => MyModel {#532 ▶} // parent3
9 => MyModel {#533 ▶} // p3-c1
]
}
for a better view and understanding
parent1
p1-c1
p1-c1-g1
p1-c1-g1-f1
p1-c2
p1-c2-c1
parent2
p2-c1
parent3
p3-c1
use Recursive relationship to same table
For example if model name is MyModel then the relationship will be
public function child(){
return $this->hasMany(MyModel::class,'parent_id','id');
}
public function recursiveChild(){
return $this->child()->with('recursiveChild');
}
So in your controller
MyModel::with(['recursiveChild'])->get();
What is your actual code, what are you trying to accomplish with this?
Collections are your friend in Laravel.
You can do a groupBy or using a With if you have a table that's related... your question is really too ambiguous.
You can get fairly complex with many chained Where orWhere with limits and groupBy
What I do see is that you need to have is not only the parent in the db but you also need a sort order on the children. Another thought is do you need a Grandparent, Parent, child? In that case you're going to have to have columns for all of those to know who they belong to when building your collection or doing just a straight eloquent pull.
My guess is this is for a menu or something you have here. Again ambiguity, so totally guessing.
EDIT
I've done this kind of thing in several apps...
You're table is going to look something like this:
id, name, menu_type, url, page_id, parent_id, sidebar, order, depth, role, created_at, updated_at, deleted_at
So in your model your going to want to do a relationship:
public function parent()
{
return $this->belongsTo('App\Models\Menus', 'parent_id');
}
public function children()
{
return $this->hasMany('App\Models\Menus', 'parent_id')->orderBy('order', 'asc');
}
Then what I've done is use this as a trait so it's available wherever I need to use it.
The trait is a little more complex than you are asking but it points you in the direction.
public function PrimaryMenu($pageid , $namespace, $user) {
// Get all primary menu items.
$appspace = "\App\Models\\".$namespace."\\Menus";
$roles = $user->roles->pluck('name');
$pmenus = $appspace::with('children')->where([['menu_type', '=', 'primary'],['parent_id','=', NULL]])->
where(function ($q) use($pageid) {
$q->where('page_id', '=', $pageid)->orWhere('page_id', NULL);
})->
where(function ($q2) use($roles) {
$q2->whereIn('role', $roles)->orWhere('role', '=', NULL);
})->
get();
return $pmenus;
}
You can see I'm checking a type of menu (this can be anything as long as you have something to group them by category) in this case primary, then I check for the page and see if we should include a row or not on the page then I check for any roles the user might have that we should include items.
Then in your controller it's just a matter of using the trait at the top:
use App\Traits\CommonTrait;
Now all of those traits are available to use in your controller. So you just call the function you need:
$pmenus = $this->PrimaryMenu($pageid, $namespace, $user);
You can see I'm sending along 3 variables to this as I have this set up for having many menus. Really the code translates to anything though that you want children associated with a parent.
The important bits are the model actions on relationships.
Thanks everyone, i used this package to achieve a sort like that.
https://github.com/lazychaser/laravel-nestedset#building-flat-tree

Laravel remove index element from get collection

I pull in data from the database via ->get(); and want to remove a certain element based on a condition in a foreach loop so i would need something like
foreach($datas as $data) {
$data->forget(this);
}
or i count the index or whatever, but I need to find a way to remove it because the ->forget() does only work on collection instances (not on eloquent collections as it seems) , any idea?
here is the format of my log:
[{"id":14,...},{"id":15,...}...]
so i get objects in an array.
and here is the dd();
Collection {#274 ▼
#items: array:4 [▼
0 => Data {#275 ▶}
1 => Data {#276 ▶}
2 => Data {#277 ▶}
3 => Data {#278 ▶}
]
}
edit: i know its better to select only needed elements in the first place but thats not possible or rather not wished for because I am putting the results through a long carbon related check and wish to do something depending on different scenarios.
edit 2:
I can remove with forget(1..2 and 3) but not with 0, it tells me undefined offset?
Maybe map is what your are looking for if you want to remove a specific property in the item:
$datas = $datas->map(function ($data) {
// modify $data here, unset unset($data->property);
return $data;
});
See documentation here
Or filter to remove the whole item:
$datas = $datas->filter(function ($data) {
return ($data->property == 'bar') ? true : false;
});
See documentation here

Cannot using where in eloquent

I'm using Eloquent ORM in Laravel. There is 2 model, User and Trans. User hasMany Trans, and Trans belongsTo User. The problem is when I'm using query where, it doesn't work.
I tried using ->get() in the last code, it still doesn't work. I tried using ->all() in the last code it still doesn't work. I tried whereIn, it still doesn't work.
User Model
public function trans()
{
return $this->hasMany('App\Trans', 'user_id');
}
Trans Model
public function user ()
{
return $this->belongsTo('App\User','user_id');
}
Controller
$trans = Auth::user()->trans->where('date', $date);
I want the output is based on query where the date is based on user input, when I delete ->where , it works and the output like this.
Collection {#797 ▼
#items: array:13 [▼
0 => Trans {#783 ▶}
1 => Trans {#784 ▶}
2 => Trans {#785 ▶}
3 => Trans {#786 ▶}
]
}
try to change like that
Auth::user()->trans->where('date', $date);
to
Auth::user()->trans()->where('date', $date)->get();
note : if you want to get only property then u get property without
pointer but if you want to used another method then must used(add)
pointer(->).

Laravel Paginator always returning full list on every page

I couldn't use the paginate()-method anymore cause I needed to add an extra attribute to every element in my collection.
The result is that I get the right pagination when rendering but it's always showing all elements on every page.
public function allPaginate($perPage)
{
$initialCollection = $this->model->orderBy('created_at', 'desc')->get();
// adding slug to my collection for every item
$initialCollection->each(function ($item) {
if(! isset($item->slug))
{
$slug = Str::slug($item->title);
$item->slug = $slug;
}
});
$result = new Paginator($initialCollection, count($initialCollection), $perPage);
$result->setPath(Request::url());
return $result;
}
Before i just used this:
$paginator = $this->model->orderBy('created_at', 'desc')->paginate($perPage);
I have 3 elements in my database and I want to show 2 per page. Here are the dumps of the two versions.
As it should be (with the ->paginate()) with 2 items in the collection
LengthAwarePaginator {#362 ▼
#total: 3
#lastPage: 2
#items: Collection {#364 ▼
#items: array:2 [▼
0 => News {#365 ▶}
1 => News {#366 ▶}
]
}
#perPage: 2
#currentPage: 1
#path: "http://jv.app/nl/nieuws/"
#query: []
#fragment: null
#pageName: "page"
}
As it is now (with new Paginator::make()) with 3 items in the collection
LengthAwarePaginator {#358 ▼
#total: 3
#lastPage: 2
#items: Collection {#368 ▼
#items: array:3 [▼
0 => News {#369 ▶}
1 => News {#370 ▶}
2 => News {#371 ▶}
]
}
#perPage: 2
#currentPage: 1
#path: "http://jv.app/nl/nieuws"
#query: []
#fragment: null
#pageName: "page"
}
What is the issue here?
Laravels Paginator class expects to be passed the records for the current page.
Firstly you will need to get the value for the current page. Then you will need to alter your query to only get the records for the current page:
// Get current page number
$page = 'Get this from the query string';
// Calculate the offset for current page
$offset = $perPage * ($page - 1);
// Get the records for the current page
$initialCollection = $this->model->orderBy('created_at', 'desc')->
skip($offset)->
take($perPage)->
get();
// Get total number of records in table
$totalRecords = $this->model->count();
// Paginate
$result = new Paginator($initialCollection, $totalRecords, $perPage);

Laravel 5 Eloquent hasMany relationship putting null into key field

I have an Artist model and an Item model.
class Artist extends Model {
protected $table = 'contactsdata';
protected $primaryKey = 'c_id';
public function artworks() {
return $this->hasMany('App\Item', 'c_id', 'c_id');
}
}
class Item extends Model {
protected $table = 'stock';
protected $primaryKey = 's_id';
}
In my ArtistsController I have this code:
public function show($id)
{
DB::enableQueryLog();
$artist = Artist::find($id);
$artworks = Artist::find($id)->artworks;
dd(DB::getQueryLog(), $artworks->toArray());
}
In the database there are many records qualifying to populate $artworks. But this is my dd() output:
array:2 [▼
0 => array:3 [▼
"query" => "select * from `contactsdata` where `contactsdata`.`c_id` = ? limit 1"
"bindings" => array:1 [▼
0 => "2242"
]
"time" => 2.59
]
1 => array:3 [▼
"query" => "select * from `stock` where `stock`.`c_id` is null"
"bindings" => []
"time" => 2.52
]
]
[]
For some reason the if field (c_id) is set to null for the second or relationship query. Any ideas? Help!
To achieve what you want, you should rather use here:
$artist = Artist::find($id);
$artworks = $artist->artworks;
instead of:
$artist = Artist::find($id);
$artworks = Artist::find($id)->artworks;
Thanks all. I have solved this myself. Eloquent relationship field names are case sensitive. For some reason my database table has all its fields (in its scheme) named in UPPER CASE. Once I changed the hasMany parameters to 'C_ID', 'C_ID' everything worked just fine.
So worth knowing that Eloquent relationship field names are CASE SENSITIVE.

Resources