Let say I have 3 tables: Book, Author and BookAuthor.
Book has id, name
Author has id, name
BookAuthor has id, book_id, author_id
I want to find all books of an author, and I know author_id. Can anyone show me how to do this with Doctrine Query Language?
I think there are few ways:
1
In action:
$this->books= Doctrine::getTable('BookAuthor')->getBookAuthor($author_id);
In model:
public function getBookAuthor($author_id)
{
$q = $this->createQuery('a')
->Where('a.author_id=?',$author_id)
->addORDERBY ('created_at DESC');
return $q->execute();
}
2
Sometime for example you have some parameter in book table, for example book can be active or not.
In action:
$this->books= Doctrine::getTable('Book')->getBookAuthor($author_id);
In model:
public function getBookAuthor($author_id)
{
$q = $this->createQuery('a')
->andWhere('a.active=1')
->leftJoin('a.BookAuthor o')
->andWhere('o.author_id=?',$author_id)
->addORDERBY ('created_at DESC');
return $q->execute();
}
Related
I know the title of my question is really weird! I hope I can clarify it with explanations. I have three models, Book, Auther, and AutherType. My tables structure :
table books:
id
title
1
book1
2
book2
table authors:
id
name
1
Bob
2
Sara
table author_types:
id
title
1
writer
2
translator
Each Book can have multiple Authors with a type. The pivot table of this relationship is something like that:
book_id
author_id
author_type_id
1
1
1
1
2
2
2
2
1
Also, I have authors(general relation) and writers(partial relation) relationship in my Book model:
public function authors()
{
return $this->belongsToMany('App\Models\Author', 'author_book', 'book_id')->withPivot('author_type_id');
}
public function writers()
{
return $this->belongsToMany('App\Models\Author', 'author_book', 'book_id')
->wherHas('authorType', function($q){
$q->where('title', 'writer');
})
->withPivot('author_type_id');
}
My question is that, how can I fetch all specific type of a book? For example, all writers of a book. In this case, the writer of the book1 is Bob. But my writers relation cannot satisfy this. The output of $book->writers for the book1 contains Bob and Sara. Because Sara has writer role for another book!
While there is no ability to write queries on complex pivots (belongsToMany relations), we have two choices:
First(which is the simplest one): get the writer type id and pass it through the relation, like:
public function writers()
{
$writer_id = AuthorType::where('title', 'writer')->first()->id;
return $this->authors()->wherePivot('author_type_id', $writer_id);
}
Second (The heavy choice), write a new method in Author model that gives the author types for a specific book and then in Book model filter authors according there types for this book:
in Author.php:
public function authorTypes()
{
return $this->belongsToMany('App\Models\AuthorType', 'author_book');
}
public function authorTypesForBook($book_id){
return $this->authorTypes()->wherePivot('book_id', '=' , $book_id);
}
and in Book.php:
public function writers()
{
$authors = $this->belongsToMany('App\Models\Author', 'author_book')->withPivot('author_type_id')->get();
$book_id = $this->id;
return $authors->filter(function ($item) use ($book_id){
return $item->authorTypesForBook($book_id)->get()->contains(function($value){
return $value->title == 'writer';
});
});
}
Hope this would help.
I have 3 DB table.
shows
show_genres
show_show_genre
In my show model, i have:
public function genres()
{
return $this->belongsToMany('App\ShowGenre');
}
So when i do:
$show=Show::find(1);
$show->genres give me collection with all genres that have show_id in shows_genres db.
I have also ShowGenre model where is all genres i have and i use.
Becouse i want to use sync for my genres, that names need to be in database.
But how can i find all shows that have genre id.
I couldn't find any way to get that list. Please help, thanks.
Edit:
You should do this other way around:
Have a model for Genre
your relationship method in Genre model should be
public function shows()
{
return $this->belongsToMany('App\Show', 'shows_genres');
}
belongsToMany accepts two parameters, model and pivot table name if not a standard name.
Your solution:
//Get genre 'strict'
//where could be followed by column name example:whereSlug, whereName
$strictGenre = Genre::whereName('strict')->first();
if($strictGenre)
{
//get shows of this genre
$strictShows = $strictGenre->shows;
}
Read manytomany relationships:
https://laravel.com/docs/6.x/eloquent-relationships#many-to-many
You may use
$show->genres()
->wherePivot('column', value)
->get();
By default Pivot table name must be singular : show_genre (without
plural s)
See docs
Assuming you have this relationship in your genres model
public function shows()
{
return $this->belongsToMany('App\Show', 'shows_genres', 'genre_id', 'show_id');
}
Then you can directly get all shows by genres id like this
$shows = Genre::find($id)->shows;
So I have two tables Animals and Adoptions
The animal table holds [animalID, name, DOB]
Adoptions hold [id, animalID, userID, approved]
I need to write a statement which would match the animalID in both the tables and would return the name and DOB of the animal where approved is 0.
I have hardly any previous experience with either mySQL or Laravel so my assumption would be that the SQL query would look like this:
SELECT animalName, DOB
FROM animal
INNER JOIN
Adoption ON adoption.animalID = animal.animalID
WHERE
Adoption.approved = 0
Currently I am returning all of the animals in the table. So I need to add the join and do the checking to see if the animalID in the adoptions table has a value of 0
public function available ()
{
//JOIN ANIMAL AND ADOPTION TABLES
//RETURN ALL ANIMALS WHERE APPROVED = 0
$animalQuery = Animal::all();
return view('/available', array('animals'=>$animalQuery));
}
public function available ()
{
//JOIN ANIMAL AND ADOPTION TABLES
//RETURN ALL ANIMALS WHERE APPROVED = 0
$animalQuery = Animal::select('animals.id','animals.name', 'animals.DOB')
->join('adoptions', 'adoptions.animalid', '=', 'animals.id')
->where('adoptions.approved', 0)
->get();
return view('/available', array('animals'=>$animalQuery));
}
This is my answer which worked for me
First of all, you would need two models. An Animal model and an Adoption model. Laravel uses models to access your database table.
Using the Animal model you could create a query like this:
\App\Animal::with('adoption')->select('name','dob')->get();
Then inside your Animal model, you would need to create the relationship between the animal and adoption:
public function adoption()
{
return $this->hasOne('App\Animal', 'animalID', 'animalID');
}
This would be one way to get an animal, with the adoption information.
I really recommend reading through the Laravel documentation for relationships and eloquent, and possibly read up on some SQL.
https://laravel.com/docs/5.8/eloquent
https://laravel.com/docs/5.8/eloquent-relationships
Assuming you have an Adoption model, and adoption relation on your Animal model, you can do the following:
$animals = Animal::select('animalName`, `DOB`)
->with(['adoption' => function($query) {
$query->where('approved', false);
})->get();
Not sure how clear is the question title, I will try to elaborate:
Tables:
repairs (Model: Repair):
id
id_supplier
id_store
suppliers (Model: Supplier):
id
store (Model: Store):
id
Relations:
Repair:
public function supplier() {
return $this->belongsTo('App\Supplier', 'id_supplier');
}
Supplier:
public function repairs() {
return $this->hasMany('App\Repair', 'id_supplier');
}
Store:
public function repairs() {
return $this->hasMany('App\Repair', 'id_store');
}
What i need from here is to get the collection of all suppliers a given store worked with, through the repairs that were made there, so my first thought it was hasManyThrough, but no ideia what to pass as 4ยบ parameter:
Store:
public function suppliers() {
return $this->hasManyThrough('App\Supplier', 'App\Repair', 'id_supplier', '<NO IDEIA WHAT'S HERE>');
}
What am I missing? Is this the right way?
I think you can't use HasManyThrough here. Try something like this in your code:
$store = Store::with('repairs.supplier')->find($id_store);//eager load
$repairs = $store->repairs->pluck('supplier');//get array of suppliers id
$suppliers = (new Collection($repairs))->unique();//get unique collection of suppliers (without duplicates)
where $id_store is id of store which suppliers you want to get
I have a quick question on how to define the below relationship
I have a USER that can belong to Many Councils, Many Schools and Many Businesses.
Now I know I can have a pivot table for all the above something like
council_user
school_user
business_user
This means I can pull out of the DB all councils a user belongs to, all businesses etc
To save me doing this is there a better approach that having 3 pivot tables, could I use Many To Many Polymorphic Relations and do it that way, if so does any one know how that would look as a table structure?
I feel it would be something like...
business
id - integer
name - string
council
id - integer
name - string
school
id - integer
name - string
userables
user_id - integer
userable_id - integer
userable_type - string
If so do I remove the userable_is and userable_type from my USER table and have this extra userables table?
Does any one know how this works, have I totally misunderstood what Polymorphic Relations does?
In Many to Many polymorphic relationship, you should have userables table along with users table. and userable_id and userable_type should be in userables table not in users table.
userables table:
user_id userable_id userable_type
1 1 App\Business
1 2 App\School
...
Business, School and Council Model:
public function users()
{
return $this->morphToMany('App\User', 'userable');
}
User Model:
public function businesses()
{
return $this->morphedByMany('App\User', 'userable');
}
public function schools()
{
return $this->morphedByMany('App\User', 'userable');
}
public function councils()
{
return $this->morphedByMany('App\User', 'userable');
}
then, this gives all the businesses of user with user_id 1.
$users=User::find(1);
foreach($user->businesses as $business)
{
print_r($business->name);
}
See Many to many polymorphic relation in doc.