Laravel 3 tables on belongsToMany relation - laravel

Based on the official Laravel documentation I found that :
$books = App\Book::with('author.contacts')->get();
In this case, imagine we have a structure like this :
books
books_authors
authors
contacts
books_authors_contacts
That's just an hypotetic case but I would like some more information : what about if I would like to retrieve all authors contacts for this specific book, imagining that for a specific book multiples authors could have multiple contacts (such contacts are linked through both authors and books as the entity books_authors_contacts says)
Is it possible to retrieve it through Laravel with eager loading with a belongsToMany relation?
By using the example below, it would just retrieve all of the contacts of an author no matter the book is.
Thanks you in advance!

There is tricks to gain this functionality in a very complex fashion, see this post. In a more practical sense, when these cases arrive in a professional environment, you often end up doing a method that aggregates this data. This can be done in multiple ways, this is an approach i feel is fairly easy and readable.
public class Book
{
public function contacts()
{
$contacts = new Collection();
$this->authors->each(function(Author $author) use($contacts) {
$contacts->concat($author->contacts);
})
return $contacts;
}
}
Offcourse for the eager loading, you have to remember to include the whole structure. For more Laravel approach contacts can be made as a Eloquent Mutator.
$book = App\Book::with('authors.contacts')->find(1);
$contacts = $book->authors();

Related

Laravel relationships (one to many)

I am new to Laravel and maybe somebody can give me an example for this.
I have two tables - Auhors and Books and two views - authors.index and books.index.
I know how to display all the books related to author in authors.index, but the question is, how to display all authors related books in books.index view?
My models and BookController:
Authors
Books
BooksController
You need to use the opposite function belongsTo into your Books model.
public function authors() {
return $this->belongsTo(Authors::class, 'author_id', 'id');
}
You can find more info here

How to search for all associations in a relationship tree in Laravel?

I'm having a problem. I have tables that relate:
internal_clients->subsidiaries->departments->job_titles->users
I also have their respective models.
My doubt is:
How do I get all the data associated with users from the top of the tree (internal_clients)
?
I'm trying to follow the Laravel documentation using hasManyThrough.
However, in the documentation it explains only how to do it in a chain of three tables. They teach how to place an intermediate table (model) as the second parameter of the hasManyThrough method (BaseClasse::class, IntermediaryClass::class).
However, in my case that has several tables between users and internal_clients, how would I do this? What would be the intermediate table?
I would like to make a query that returns the user's internal_client, subsidiary, department and jobTitle (associated with users).
I'm trying to do it this way:
Model InternalClient
public function users()
{
return $this->hasManyThrough(User::class, InternalClient::class);
}
Controller UserController
public function allRelations($internalClientId)
{
$internalClient = InternalClient::find($internalClientId);
$users = $internalClient->users;
return response()->json($users, 201);
}
The InternalClient id arrives at the controller above.
When I access the route, the error below is returned:
In short: I would like to know if there is a way to get all the data (from all tables that are in this hierarchical tree) that are associated with the User.
I couldn't find an answer on the Stackoverflow PT-BR.
Thank you!

laravel 3 way pivot

I've one many to many relationship between Entities and Affiliated Tables,
basically an affiliated can attend to many entities(example, medical services, dentist offices). One Entity can be visited by one or many affiliated.
Additionaly , one or more benefits can be occupied by one affiliated in a particular entity. As shown in the image.
I want to be able to answer queries like, which benefits where used by the affiliated in a particular entity.
Should i create a new Model, how should i rewrite the many-to-many relationship for ORM.
Thanks in advance!
Don't need a Affiliated_has_Entities model.
You could write the relationships as below, remember to check for arguments and its order in the belognsToMany relationship (sorry for misspelled words)
Entities model
public function afilliateds(){
return $this->belongsToMany('Afilliated', 'Afilliated_has_Entities');
}
Afilliated model
public function entities(){
return $this->belongsToMany('Entities', 'Afilliated_has_Entities');
}
public function benefits(){
return $this->belongsToMany('Entities', 'Afilliated_has_Entities');
}
Benefits model
public function entites(){
return $this->belongsToMany('Entities', 'Afilliated_has_Entities');
}
And so on..
I hope it helps

Get a distinct list of all related model instances in Eloquent

I have two Eloquent models (say: Books and Authors) which have a one-to-many-relation (one Author can have many Books, each Book has exactly one Author). The database also contains Authors which have no Book at all. I would like to retrieve a list of all Authors which have a Book - whitout having duplicate authors.
Currently I loop over all Book instances and add the Author to the list if it is not yet in the list:
$books = Books::all();
$list = [];
foreach ($books as $book) {
if (! in_array($book->author, $list) ) {
array_push($list, $book->author);
}
}
I wonder whether there is a smarter way to get this, i.e. a way, which reuduces the number of database queries.
I would like to retrieve a list of all Authors which have a Book - whitout having duplicate authors
Use the has() method:
$authorsWithBooks = Author::has('books')->get();
$books = Books::with('author')->get();

Laravel - Retrieve the inverse of a many-to-many polymorphic relation (with pagination)

after some digging I still could not find any solid way to retrieve the inverse of a many-to-many polymorphic relation that allows mixed models results.
Please consider the following:
I have several models that can be "tagged". While it is trivial to retrieve for example $item->tags, $article->tags and the inverse with $tag->articles and $tag->items I have no easy way to do something like $tag->taggables to return both articles and items in the same collection. Things get even bumpier as I need to use pagination/simple pagination to the query.
I have tried a few workarounds but the best I could put together still looks crappy and limited. Basically:
I queried the DB once per "taggable";
put all in a single big collection;
passed the collection to a phpleague/fractal transformer (my API uses it) that returns different json values depending on the parsed models.
The limits of this approach is that building a pagination is a nightmare and fractal "include" options can't be used out of the box.
Can anyone help me? I'm currently using Laravel 5.1.
There is not much magic in my current code. Faking and simplifying it to make it short:
From the api controller:
$tag = Tag::findOrDie($tid);
$articles = $tag->cms_articles()->get();
$categories = $tag->cms_categories()->get();
$items = $tag->items()->simplePaginate($itemsperpage);
$taggables = Collection::make($articles)->merge($categories);
// Push items one by one as pagination would dirt the collection struct.
foreach ($items as $item) {
$taggables->push($item);
}
return $this->respondWithCollection($taggables, new TaggableTransformer);
Note: using simplePaginate() is there only because I would like all articles and categories to be shown on first page load while the number of items are so many that need pagination.
From the Transformer class:
public function transform($taggable)
{
switch (get_class($taggable)) {
case 'App\Item':
$transformer = new ItemTransformer;
break;
case 'App\CmsArticle':
$transformer = new CmsArticleTransformer;
break;
case 'App\CmsCategory':
$transformer = new CmsCategoryTransformer;
break;
}
return $transformer->transform($taggable);
}
Please consider that the other transformers are simply returning arrays of data about the models they correlate with. If you use Fractal you would easily spot that nested "included" models would not be applied.
Nothing fancy for the Tag model:
class Tag extends Model
{
protected $morphClass = 'Tag';
protected $fillable = array('name', 'language_id');
public function cms_articles() {
return $this->morphedByMany('App\CmsArticle', 'taggable');
}
public function cms_categories() {
return $this->morphedByMany('App\CmsCategory', 'taggable');
}
public function items() {
return $this->morphedByMany('App\Item', 'taggable');
}
// Would love something like this to return inverse relation!! :'(
public function taggables() {
return $this->morphTo();
}
}
I am also considering the option to do 3 separate calls to the API to retrieve articles, categories and items in three steps. While in this particular scenario this might make sense after all, I would still need to deal with this particular inverse relation headache with another part of my project: notifications. In this particular case, notifications would have to relate to many different actions/models and I would have to retrieve them all in batches (paginated) and sorted by model creation date...
Hope this all makes sense. I wonder if a completely different approach to the whole inverse "polymorphic" matter would help.
Kind regards,
Federico
Ah yes. I was down your path not all that long ago. I had the same nightmare of dealing with resolving the inverse of the relationship of polymorphic relationships.
Unfortunately polymorphic relationships haven't been given much attention in the Laravel ecosystem. From afar they look like unicorns and rainbows but soon you're fighting things like this.
Can you post an example of a $thing->taggable for a better picture? Think it may be solvable with a dynamic trait + accessor magic.

Resources