Return result from pivot table - sql

I have multiple campaigns, that can be assigned to multiple users. Basically, they have belongsToMany relation both ways.
I would like to print out the results on the page, that only belongs to that specific user, based on the pivot table.
Models:
User model:
public function campaign()
{
return $this->belongsToMany(Campaign::class, 'campaign_user');
}
Campaign model:
public function users()
{
return $this->belongsToMany(Gift::class, 'campaign_user');
}
Migration of pivot table:
public function up()
{
Schema::create('campaign_user', function (Blueprint $table) {
$table->foreignId('user_id')->constrained()->onDelete('cascade');;
$table->foreignId('campaign_id')->constrained()->onDelete('cascade');
});
}
Incorrect Controller:
public function index(Request $request)
{
$data = Campaign::withCount('gifts');
$data->where('user_id', $request->user()->id)->get();
return view('subscribes.index', ['data' => $data]);
}
Basically, all I need, is to return specific campaigns, that the client has subscribed only, based on the pivot table/user id. Thus, editing this Controller.
I still face lots of issues with Eloquent models and pivot tables, and I would be very thankful, for any assistance in regards to it.

This will make more sense if you rename the relationship campaign() to it's plural campaigns() on your User model.
Once you have the relationships set up, you can access campaigns for the user straight from the user object.
$user = $request->user();
$data = $user->campaigns;
Note also, if your user is authenticated, you can access them easily like:
$user = auth()->user();
So your index method in your controller would be
public function index(Request $request)
{
$user = $request->user();
$data = $user->campaigns;
return view('subscribes.index', ['data' => $data]);
}

Related

How to get the default $id from another table using laravel model relationship?

I am facing the problem whereby I don't know the syntax of letting the id of my property model equals to property_id value in property_doc table.
In PropertyDoc model
public function property()
{
return $this->belongsTo(Properties::class, 'property_id');
}
In Properties model
public function property_id()
{
return $this->hasMany(PropertyDoc::class, 'property_id');
}
In PropertyController
public function StoreInfoProperty(Request $request)
{
$propertyInfo = new PropertyDoc;
$propertyInfo->property_id = $property_id;
}
I am stuck at retrieving the default id value in properties database to be equal to the property_id in property_docs database. Thank you.
You should change the naming of the relationship, see my example below:
In Properties model
public function propertyDocs()
{
return $this->hasMany(PropertyDoc::class, 'property_id', 'id');
}
In PropertyDoc model
public function property()
{
return $this->belongsTo(Properties::class, 'property_id', 'id');
}
In controller
public function StoreInfoProperty(Request $request)
{
$propertyDoc = PropertyDoc::with(['property'])->where('...logic here');
$property_id = $propertyDoc->property->id;
}
hope can help you and happy coding !

Laravel Convert Mysql query to Eloquent

I'm new to Laravel and I can write simple eloquent queries but have no idea how to convert this query to eloquent. Can anyone give any idea, is it possible to convert this to eloquent or I have to write raw query?
"Select categories.id, categories.name, Sum(likes.liked) as liked
FROM categories, likes
WHERE likes.material_id IN (SELECT category_material.material_id
FROM category_material
WHERE category_material.category_id = categories.id)
GROUP BY categories.id";
Here my Models
class Material extends Model
{
public function categories(){
return $this->belongsToMany(Category::class,'category_material');
}
public function likes(){
return $this->hasMany(Like::class);
}
////////////////////////////////////////////////////////////
class Like extends Model
{
protected $table = 'likes';
public function user(){
return $this->belongsTo(User::class);
}
public function material(){
return $this->belongsTo(Material::class);
}
//////////////////////////////////////////////////////
class Category extends Model
{
public function materials(){
return $this->belongsToMany(Material::class,'category_material');
}
You can define a likes relationship in your Category model like so:
public function likes()
{
return $this->belongsToMany(Like::class, 'category_material', 'category_id', 'material_id', 'id', 'material_id');
}
Then to achieve what you're after with Eloquent you can use a mixture of has() and withCount, however, we're going to modify the withCount call to return a sum() instead:
$catrgories = Category::has('likes')->withCount([
'likes as liked' => function ($query) {
$query->select(DB::raw('SUM(likes.liked)'));
},
])->get();
If you're wanting to return categories that don't have any likes you can remove the has() method, and introduce the COALESCE() function to your raw query:
$catrgories = Category::withCount([
'likes as liked' => function ($query) {
$query->select(DB::raw('COALESCE(SUM(likes.liked), 0)'));
},
])->get();
Alternatively, you could simply load the necessary relationships and then use that fact that Eloquent returns collection to get the value after you've retrieved the results from the database:
$categories = Category::with('materials.likes')->get()->map(function ($item) {
$item->setAttribute('liked', $item->materials->map(function ($item) {
return $item->likes->map->sum('liked')->sum();
})->first());
$item->unsetRelation('materials');
return $item;
});
This would mean that you don't have to add the custom relationship.

Recursive relationship with scope

A user has a sponsor:
public function sponsor()
{
return $this->belongsTo(User::class, 'sponsor_id');
}
A user has referrals:
public function referrals()
{
return $this->hasMany(User::class, 'sponsor_id');
}
A user is considered capped when they have 2 or more referrals:
public function activeReferrals()
{
return $this->referrals()->whereActive(true);
}
public function isCapped()
{
return $this->activeReferrals()->count() >= 2;
}
A user can give points. By default, the sponsor will receive them, but if the sponsor is capped, I want the points to go to a sponsor's referral that is NOT capped. If all the referrals are capped, then it does the same thing with the level below (the referral's referrals).
If I go user by user making database calls for each one, it's gonna take a long time. How can I write a scope that makes recursive calls until it finds the first active referral in the tree that's not capped?
This is what I'm trying to do:
Please give this a try... I believe this will work for you :)
public function scopeNotCappedActiveReferrals($query, $count) {
return $query->withCount(['referrals' => function($q) {
$q->where('active', true);
}])->where('referrals_count', '<', $count);
}
For the second part...
// Finally you can call it with
public function allReferrals() {
$users = User::notCappedActiveReferrals(2)->get();
$allUsers = $this->findNotCappedActiveReferralsRecurrsively($users);
}
// Do not place this function in the model,
// place it in your Controller or Service or Repo or blahblah...
// Also, not tested... but should work :)
protected function findNotCappedActiveReferralsRecurrsively($users) {
if(!count($user)) {
return $users;
}
foreach($users as $user) {
$moreUsers = $user->notCappedActiveReferrals(2)->get();
return $users->merge($this->findNotCappedActiveReferralsRecurrsively($moreUsers));
}
}
Hope this is what you need :)

How to create a row for user in another related table when the user is created in laravel?

I need to create a row in a related table. This is a hasOne and belongsTo relationships.
A user hasOne profile
A profile belongsTo user
I want to create a profile row once the user has been created.
public function store(UserRequest $request)
{
$user= new User();
User::create($request->all());
Profile::create([
'user_id' => $user->user_id,
]);
return redirect()->route('users.index')
}
you can use events(observer) in laravel for doing your work when User created in any where of your project.
https://laravel.com/docs/5.3/eloquent#observers
Use Model Observers.
You can declare an observer to created event, and create the profile there.
public function creating($model)
{
// Create your related profile.
// Note that profile relationship must be defined at your model class
$model->profile()->create();
return true;
}
This observer may be created either on a Model Observer Class, or declared on model boot.
Try like this:
public function store(UserRequest $request)
{
$user = User::create($request->all());
$user->profile()->create([]);
return redirect()->route('users.index')
}
You have to have hasOne relation method in user's class:
public function profile()
{
return $this->hasOne(Profile::class);
}
This for update is not working; Is there a solution
public function update(Request $request, $id)
{
$input = $request->all();
$employee = Employee::findorfail($id);
$update = $employee->update($input);
$employee->personaldetail()->update(['employee_id' => $employee->employees_id,]);
return redirect()->route('employees.index')->with('message','Employee has been updated');
}

Eloquent relationship with a where clause

I need to do a where condition on the code field from my intermediate table. My two models are;
class Agreement extends Eloquent {
protected $table = 'agreements';
public function clients(){
return $this->belongsToMany('Client', 'client_agreements')->withPivot('start_date', 'expire_date', 'code');
}
}
And;
class Client extends Eloquent {
public function agreements(){
return $this->belongsToMany('Agreement', 'client_agreements')->withPivot('start_date', 'expire_date', 'id', 'code');
}
}
My controller is currently;
public function show($code, $client_id)
{
//
$client = Client::with('agreements')->find($client_id);
$client_agreement = $client->agreements;
}
I think I need to expand the $client->agreements; code to include a where condition on the $code. I have tried so many different combinations but just keep returning the same Call to undefined method error.
I've tried things like;
$client_agreement = $client->agreements->where('code', '=', $code);
$client_agreement = $client->agreements->code->find($code);
$client_agreement = $client->agreements->pivot->code->find($code);
I always get the same error. I'm not that great on objects so maybe I'm looking at this all wrong. How is it done?
You need to access ->relation() not ->relation (which is dynamic property call):
$client_agreement = $client->agreements()
->wherePivot('code', '=', $code)
->first();