Does Eloquent relation sync also remove? - laravel-4

When updating a model and I sync a relationship, if I don't pass in all the ids that already exist, will that relationship be removed?

You decide: sync has 2nd parameter that defaults to true and is responsible for detaching:
$model->relationship()->sync([1,2,3]);
$model->relationship()->sync([4,5,6]); // attached [4,5,6], detached [1,2,3]
$model->relationship()->getRelatedIds(); // [4,5,6]
// but:
$model->relationship()->sync([4,5,6], false); // attached [4,5,6], detached []
$model->relationship()->getRelatedIds(); // [1,2,3,4,5,6]

The answer is Yes it does. I could not find any documentation that in fact stated that.
lets say you have 2 tables: "authors" and "books", with a pivot table "book_authors".
when creating a new author:
$author_id =2;
$author->books()->sync(array(1,4,5,15));
Now you have a 4 entries in that pivot table "book_authors":
author_id book_id
2 1
2 4
2 5
2 15
Now update:
$author_id =2;
$author->books()->sync(array(1,15));
now "book_authors" is:
author_id book_id
2 1
2 15

Related

How to minimize "where()" on Laravel query builder. If all table columns are all the same values

Is there a way to minimize calling ->where() on laravel query builder?
Sample Table:
name
item1
item2
item 3
David
0
0
0
David
1
1
2
David
1
2
2
I want to remove a specific record with all the table columns containing 0 value without removing the other records.
My query is this.
DB::table('users')->where('name', 'David')
->where('item1', 0)
->where('item2', 0)
->where('item3', 0)
->delete();
Is there a way to minimize calling->where()? Just like in whereIn('columns',[1,2,3,4]) but in columns.
Pass an array of conditions to the where function. Each element of the array should be an array containing the three arguments typically passed to the where method:
$conditions=[
['name','=', 'David'],
['item1','=',0],
['item2','=', 0],
['item3','=', 0],
]
DB::table('users')->where($conditions)->delete();
Ref: https://laravel.com/docs/8.x/queries#where-clauses

Create an array to produce a hierarchical tree structure in laravel using eloquent ORM

I have a project with table structure:
There are professors on top
tb_professor
id name
1 david
2 mathew
3 tom
The second table is of guest lecturers. Here its bit complicated. If the guest lecturer is experienced, they can teach other guest lecture who doesnt have experience.The experienced guest lectures will be selected at first. Then freshers.
tb_guest_lec
id name fk_professor_id is_experienced trainee_id
1 sara 1 1 null
2 jasha 1 1 null
3 sam 1 0 null
4 william 1 0 1
5 luk 3 0 1
The last table is students table. Each guest lecures are assigned with students
tb_students
id name fk_gust_lec_id
1 liza 1
2 james 1
3 mason 2
Finally need a hierarchial tree structure. professors on top, underneith guest lectures, and at lowest level students(also a group of guest lecturers under experienced lectureers )
$res=array();
$gl=$res['guest_lec']= DB::table('tb_guest_lec')->where('fk_professor_id','1')->select(count('id'), *)->get()->toArray();
forech($gl as $g){
if($g['is_experienced']==1){
$res['freshers']= DB::table('tb_guest_lec')->select(count('id'), *)->where('trainee_id',$g['id'])->get();
}
$res['students']= DB::table('tb_students')->select(count('id'), *)->where('fk_gust_lec_id',$g['id'])->get();
}
var_dump($res);
In blade, by looping through the array can create a tree structure.
But can i do this in a simple way using eloquent?

Laravel eloquent deep count with relationship

I want to get count from deep table and the relationship is A->B->C->D and I want total count of D.
For example;
A: 3 Boss
B: 5 Managers
C: 8 Human Resources
D: 25 Employees
Imagine that every boss has managers and every manager has human resources and also every human resource has employees. How can I get total count every boss's employees' with Laravel. (For instance, first boss has 7 employees at the end.) Should I have to write hard sql code like joins or can I handle with eloquent?
By the way, my tables:
A: id, name
B: id, name
A and B has pivot table.
C: id, name
B and C has pivot table
D: id, name
C and D has pivot table
So far, I tried to:
$a = Boss::with("a.b.c.d")->where("id", 10)->first();
dd($a->b->c->d->count());
It just gave me d's count but I want to all of a's.
There is no native relationship for this case.
I created a HasManyThrough relationship with unlimited levels: Repository on GitHub
After the installation, you can use it like this:
class A extends Model {
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function d() {
return $this->hasManyDeep(D::class, ['a_b', B::class, 'b_c', C::class, 'c_d']);
}
}
$count = A::find($id)->d()->count();

Laravel - retrieve direct/indirect pivot table subscribers

I am having a hard time figuring this out in laravel; for a subscriber relationship we have 2 pivot tables:
A subscriber can subscribe to a question:
question_subscriber
id question_id subscriber_id
1 2 3
2 2 4
3 3 1
4 3 2
A subscriber can subscribe to a user:
user_subscriber
id user_id subscriber_id
1 1 6
2 1 7
3 2 1
Normal questions table with question owner:
questions
id question user_id
1 abc? 1
2 xyz? 1
3 123? 2
The pivot relationships are setup correctly in their models, and I can pull out with a foreach, subscribers for a question, $question->subscribersQuestion as $subscriber, or subscribers for a user, $user->subscribersUser as $subscriber:
But how can we pull out all subscribers that belong to a user (directly or indirectly (through a question they own))?
For example, these should be all retrieved subscribers for user 1:
6 // subscribed to directly
7 // subscribed to directly
3 // subscribed to through question
4 // subscribed to through question
Any idea on the most efficient way to do this in Laravel?
This will be the easiest way:
// assuming this setup:
User hasMany Question
User belongsToMany User (subscribers - direct)
Question belongsToMany User (subscribers - indirect)
// we don't need this, since we pass it by reference to the closure,
// but for clarity let's initialize this variable:
$indirectSubscribers = null;
$user = User::with(['questions.subscribers' => function ($q) use (&$indirectSubscribers) {
// get all indirect subscribers (cost of additional query)
$indirectSubscribers = $q->get()->unique();
}])->find($userId);
// merge with directs subscribers
$allSubscribers = $user->subscribers->merge($indirectSubscribers);

Relations between tables

I have 3 tables: A, B and C.
Table A is in relation (n:1) with B and with C.
Typically I store in A the B.Id (or the C.Id) and the table name.
e.g.
A.ParentId = 1
A.TableName = "B"
A.ParentId = 1
A.TableName = "C"
A.ParentId = 2
A.TableName = "B"
Is it a good solution? Are there any other solutions?
Why not 2 parentid columns?
A.ParentIdB = 1
A.ParentIdC = 3
Another possibility is to introduce another table Content (D) that serves as a "supertype" to Posts and Images. Then a row in Comments (A) would reference a primary key in Content as would each row in Posts (B) and Images (D). Any common fields in Posts and Images would be moved to Content (perhaps "title" or "date") and those original tables would then only contain information specific to a post or image (perhaps "body" or "resolution"). This would make it easier to perform joins than having the table names in a field, but it does mean that a real-world entity could be both a post and a comment (or indeed, be multiply a post or comment!). Really, though, it depends on the situation that you're trying to model.

Resources