Laravel Eloquent Relationship 3 tables - eloquent

I am a newbie to Laravel 5.2 and am working on a legacy system and am a bit confused regarding eloquent and would appreciate someone giving me the code.
There are 3 tables:
cards
categories
cards2cat
cards can be part many categories which are kept in cards2cat table.
The cards2cat table has the following structure
id (primary key)
image (card)
category
What I want to do is to have a method in the Cards model called something like getCardsWithCategores which returned the cards info plus the names of the categories from the category table.
The categories table has a key of id and a field category.
Thanks!

Go to your Card2Cats model and add this:
public function categories()
{
return $this->hasOne('App\Categories','id','category');
}
public function cards()
{
return $this->hasOne('App\Cards','id','image');
}
For the query you do this:
$cards = Card2Cat::with('categories','cards')->get();
foreach ($cards as $key => $value) {
echo $value->id.', Card:'.$value->cards->name.', Category:'.$value->categories->category.'<br>';
//$value->cards gives you all column of cards and you can do
//$value->cards->colName
// same goes for $value->categories
}
Make sure the spelling of your classes and table column names are correct before running the code :D

Related

how to get foreign key set in relationship of Laravel 9

I'm using Larave 9 to build a complicated web application.
I'm trying to get foreign key already set in relationship of a model to make another dynamic join query for some other data.
This is an example to make a dynamic query after getting foreign keys from many models:
foreach ($joinFunc as $table => $jQ){
$relTbl = $jQ['related'];
$k = $jQ['oKey'];
$fk = $jQ['fKey'];
$q->leftJoin($table, $table. '.' . $k, $relTbl. '.' .$fk);
}
My relationship in model is:
public function autopays()
{
return $this->hasMany(ClientAutoPay::class, 'client_id', 'id');
}
I want to get client_id set in the relationship
$q = Client::query()->with('autopays');
dump(
$q->first()->autopays()->getRelated()->getKeyName(),
$q->first()->autopays()->getRelated()->getForeignKey(),
);
but the result id:
"id"
"client_auto_pay_id"
what I need is to get client_id instead of client_auto_pay_id. Any help :(
I found a solution to check if the relationship has an instance ($q->whereHas()) which gave me the table name and if no instance found then I didn't pass it to dynamic joining query loop.
One thing I had to pass manually from the controller to my function and that is array of each table joining ownKeys and foreignKeys.
Now my dynamic dataTable by Livewire component is working awesome 👍

Laravel 5.3 Eloquent Relationship 1-1 Query

Hi guys how could I query a data from my database with one-to-one relationship on eloquent model?
I want to query the menus with specific category id.
For example I only want to query the meals with "Breakfast Category".
Menu Model:
public function menucat()
{
return $this->hasOne('App\MenuCat', 'menu_cat_id', 'id');
}
Menu_Cat Model
public function menus()
{
return $this->belongsTo('App\Menu', 'menu_cat_id', 'menu_cat_id');
}
Database Table:
menus Table
id | menu_cat_id | menuName
menu_cat Table
menu_cat_id | menuCatName
I find it easy using the Query builder but I would like to use the eloquent to query out the data I need.
Thanks in Advance!
in the documentation you have that
return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
you need to inverse menu_cat_id and id like that
return $this->hasOne('App\MenuCat', 'id', 'menu_cat_id');

Querying Laravel Relationship

I am trying to get one query work since morning and not able to get it working I have two tables photographers and reviews please have a look at structure and then I will ask the question at the bottom :
Reviews table :
id int(10) unsigned -> primary key
review text
user_id int(10) unsigned foreign key to users table
user_name varchar(64)
photographer_id int(10) unsigned foreign key to photographers table
Photographers table :
id int(10) unsigned -> primary key
name text
brand text
description text
photo text
logo text
featured varchar(255)
Photographers model :
class Photographer extends Model
{
public function reviews()
{
return $this->hasMany('\App\Review');
}
}
Reviews Model :
class Review extends Model
{
public function photographers()
{
return $this->belongsTo('\App\Photographer');
}
}
My logic to query the records
$response = Photographer::with(['reviews' => function($q)
{
$q->selectRaw('max(id) as id, review, user_id, user_name, photographer_id');
}])
->where('featured', '=', 'Yes')
->get();
The question is : I want to fetch all the photographers who have at least one review in the review table, also I want to fetch only one review which is the most latest, I may have more than one review for a photographer but I want only one.
I would add another relationship method to your Photogrpaher class:
public function latestReview()
{
return $this->hasOne('App\Review')->latest();
}
Then you can call:
Photographer::has('latestReview')->with('latestReview')->get();
Notes:
The latest() method on the query builder is a shortcut for orderBy('created_at', 'desc'). You can override the column it uses by passing an argument - ->latest('updated_at')
The with method loads in the latest review.
The has method only queries photographers that have at least one item of the specified relationship
Have a look at Has Queries in Eloquent. If you want to customise the has query further, the whereHas method would be very useful
If you're interested
You can add query methods to the result of a relationship method. The relationship objects have a query builder object that they pass any methods that do not exist on themselves to, so you can use the relationships as a query builder for that relationship.
The advantage of adding query scopes / parameters within a relationship method on an Eloquent ORM model is that they are :
cacheable (see dynamic properties)
eager/lazy-loadable
has-queryable
What you need is best accomplished by a scoped query on your reviews relation.
Add this to your Review model:
use Illuminate\Database\Query\Builder;
use Illuminate\Database\Eloquent\Model;
class Review extends Model {
public function scopeLatest(Builder $query) {
// note: you can use the timestamp date for the last edited review,
// or use "id" instead. Both should work, but have different uses.
return $query->orderBy("updated_at", "desc")->first();
}
}
Then just query as such:
$photographers = Photographer::has("reviews");
foreach ($photographers as $photographer) {
var_dump($photographer->reviews()->latest());
}

Select custom columns from Laravel belongsToMany relation

Im trying to select only specific attributes on the many-to-many relation users, just like in one-to-one. But using select() on belongsToMany() seem to be ignored and i'm still getting all the User attributes.
class Computer extends Eloquent {
public function users() {
return $this->belongsToMany("User")->select("email");
}
public function admin() {
return $this->hasOne("User")->select("email");
}
}
Computer::with("users")->get();
Is there a way of filtering only specified columns from related entity with belongsToMany()?
Yes, you actually can.
Computer::with("users")->get(array('column_name1','column_name2',...));
Be careful though if you have the same column name for both tables linked by your pivot table. In this case, you need to specify the table name in dot notation, tableName.columnName. For example if both users and computer has a column name id, you need to do :
Computer::with("users")->get(array('users.id','column_name2',...));
According to Taylor Otwell it is not currently possible: https://github.com/laravel/laravel/issues/2679
I have tried to use a lists('user.email') at the end of the query but I can't make it work.
Computer::with(["users" => function($query){
$query->select('column1','column2','...');
}])->get();

Order Zend_Db_Table rowset by reference column

i know i can define relationships through _referenceMap, i know that i con join selects trough
$db->select()
But what i need is to fetch rowset in model extending Zend_Db_Table_Abstract and then order it by value of referenced column from another table.
Is there some workaround to do that?
edit:
heres is the example:
first table:
table bugs columns id, bugname, authorid
second table:
table authors columns id, authorname
I have a model Model_Bugs extends Zend_Db_Table_Abstract
I want to make something like this:
$model->fetchAll($model->select()->order('authorname ASC'))
This means, that i need to join tables and sort by a column, which is not in the model table.
thanks for help
Jan
I would add a method in Model_Bugs like so:
public function fetchBugsByAuthorname() {
$bugTable = $this;
$bugTableName = $this->info('name');
$authorsTable = new Model_Authors();
$authorsTableName = $authorsTable->info('name');
$select = $bugTable->select()
->setIntegrityCheck(false)
->from($bugTable, array('id', 'bugname', 'authorid'))
->join($authorsTableName,
"$bugTableName.authorid = $authorsTableName.id",
array("authorname"))
->order("$authorsTableName.authorname asc");
$result = $bugTable->fetchAll($select);
return $result;
}
But to do this you have to turn off ZF's table integrity checking (setIntegrityCheck(false) above), which means you won't be able to directly call save() on the resulting rows. But if it's for a read-only purpose, it will work.
If you needed to save rowsets back to the database, you may have to first select the author ID's from Model_Authors in the order you want them, and then re-order your Model_Bugs query accordingly. It's messier but it can work.