Fetch the data of parent model into static::saving() boot function - laravel

I want to use data from the parent model to run the saving() function in the child model
Previously, I inserted a computed data to the table in model "Loan" but now I need to insert it into a child model "InterestAmount"
Loan.php
use Illuminate\Database\Eloquent\Model;
class Loan extends Model
{
protected $fillable ['amount','interest','status','duration','member_id','loan_type_id','interest_type_id','loan_payment_type_id'];
//protected $appends = 'interest_amount
protected static function boot()
{
parent::boot();
static::saving(function($model) {
$model->interest_amount = ($model->amount/100 )* $model->interest;
});
}
public function interest_amount()
{
return $this->hasMany(InterestAmount::class,'loan_id','id');
}
}
I want to remove the saving function from Loan.php and use as below.
Interest.php
use Illuminate\Database\Eloquent\Model;
class InterestAmount extends Model
{
public function loan()
{
$this->belongsTo(Loan::class,'loan_id','id');
}
protected static function boot()
{
parent::boot();
static::saving(function($model) {
$model->interest_amount = ($model->amount/100 )* $model->interest;
});
}
}
How do I fetch "amount" and "interest" in this function?

The $model variable inside InterestAmount model refers to an InterestAmount object :
static::saving(function($model){
$model->interest_amount = ($model->loan->amount/100 )* $model->loan->interest;
});
Then you need to get the related loan using your relationship method loan() then get the properties amount/interest.
NOTE: As #namelivia's comment says you're missing the return in the loan() method:
public function loan()
{
return $this->belongsTo(Loan::class,'loan_id','id');
}

Related

How to add information to a pivot table in laravel?

I have a many:many relation between student and course.
Here are my models and my pivot table:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Student extends Model
{
use HasFactory;
protected $fillable = [
'name',
'surname',
'age',
'tdah',
'description',
'hobbies',
];
/* public function course(){
return $this->belongsTo(Course::class);
} */
public function data(){
return $this->hasMany(Datum::class, 'student_id', 'id');
}
public function configurations(){
return $this->hasMany(Configuration::class, 'student_id', 'id');
}
public function courses(){
return $this->belongsToMany(Course::class, 'course_student', 'student_id', 'course_id');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Course extends Model
{
use HasFactory;
protected $fillable = [
'name',
'academic_course_id',
'user_id',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function academicCourse()
{
return $this->belongsTo(AcademicCourse::class);
}
public function planification(){
return $this->hasOne(Planification::class, 'course_id', 'id');
}
public function subjects(){
return $this->hasMany(Subject::class, 'course_id', 'id');
}
/* public function students(){
return $this->hasMany(Student::class, 'course_id', 'id');
} */
public function students(){
return $this->belongsToMany(Student::class, 'course_student', 'course_id', 'student_id');
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('course_student', function (Blueprint $table) {
$table->id();
$table->foreignId('course_id')->constrained()->onDelete('cascade');
$table->foreignId('student_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('course_student');
}
};
I'd like to create a student that belongs to a group. I know how to create a student and a group, but I'd like to create a register for that student in my course_student pivot table. My StudentController method store is:
public function store(Request $request)
{
Student::create($request->all());
$courses = Course::all();
$academicCourses = AcademicCourse::all();
return view('course.index', compact('courses', 'academicCourses'));
}
It creates a new student but I don`t know how to create a new register for the pivot table.
I thought about doing something like:
course_student::create(request)
in my store method but I think it isn`t that way.
In Laravel you can do it by using attach function, Attach() function has two parameters :
1- the another foreign key in you case attach(course_id).
2-(this is optional) array for any another columns inside pivot table for example :
attach(course_id,['users_id'=>$usersId])
In your case you will create the records inside the pivot table (course_student) via the object from student model .
$student->courses()->attach($course_id);
note :
there is another method which does the opposite detach() but you need to use it carefully if you write it without any parameter it will remove all the records inside (course_student) that belong to the student object so specify the course that you want to remove it by that way :
$student->courses()->detach($course_id);
I hope that will help you ...
$student->courses()->attach($courseId);
https://laravel.com/docs/9.x/eloquent-relationships#updating-many-to-many-relationships
Edit :
You can use attach() method on the relationship. In your code it would look like this :
public function store(Request $request, Course $course) //add parameter course to know which course needs to be attached
{
$newStudent = Student::create($request->all()); // create() returns instance of created Student
$newStudent->courses()->attach($course->id);
$courses = Course::all();
$academicCourses = AcademicCourse::all();
return view('course.index', compact('courses', 'academicCourses'));
}

Blank object in Eloquent belongsTo()

I'm trying to display which one attribute (code) of Item. ServiceItem has Item as a foreign key. But I can't get the Item at all.
This one gives a blank object in blade template:
#foreach ($service->serviceItems as $serviceItem )
{{ json_encode($serviceItem->item()) }}
#endforeach
Here's my model declaration:
//ServiceItem model
class ServiceItem extends Model
{
use HasFactory;
public $fillable = ['service_id', 'item_id', 'values'];
public function service()
{
return $this->belongsTo(Service::class, 'foreign_key');
}
// this doesn't work
public function item()
{
return $this->belongsTo(Item::class, 'foreign_key');
}
}
// Service model
class Service extends Model
{
use HasFactory;
public $fillable = ['user_id', 'site_id', 'title', 'status', 'remarks', 'report', 'date'];
public function user()
{
return $this->belongsTo('\App\Models\User');
}
public function site()
{
return $this->belongsTo('\App\Models\Site');
}
public function serviceItems() {
return $this->hasMany('\App\Models\ServiceItem');
}
}
This is my controller:
public function index()
{
$services = Service::latest()->paginate(5);
return view('services.index', compact('services'))
->with('i', (request()->input('page', 1) - 1) * 5);
}
Please help me to display the code attribute in Item from Service!!! Thanks a lot!
I suppose you read the Laravel doc of model relationship definition. They referenced to put foreign key as the second parameter, not the foreign_key as word but your actual foreign key that reference the parent table. you have to change the model code.
class ServiceItem extends Model
{
use HasFactory;
public $fillable = ['service_id', 'item_id', 'values'];
public function service()
{
return $this->belongsTo(Service::class, 'service_id');
}
public function item()
{
return $this->belongsTo(Item::class, 'item_id');
}
}
and then $serviceItem->item should work as expected.

How to implement event/listeners with repository pattern in laravel 5.4

I can't make listeners trigger action update, create or delete when I user patter repository.
Addionally I have added my code in order to help my to solve my problem.
TicketController.php
namespace App\Http\Organizer\Controllers;
use App\Http\Controllers\Controller;
use App\Http\Events\Contracts\IEvent;
use App\Entities\Event;
class TicketController extends Controller
{
protected $IEvent;
public function __construct( IEvent $IEvent )
{
$this->IEvent = $IEvent;
}
public function checkFutbolType ($activityId)
{
// I need to listen this action here
$event = $this->IEvent->update(21927, ['title'=>'new title']);
}
}
My RepoEvent.php:
<?php
namespace App\Http\Events\Repositories;
use App\Http\Events\Contracts\IEvent
;
class RepoEvent implements IEvent
{
protected $model;
public function __construct($model)
{
$this->model = $model;
}
public function update($activityId, $params)
{
return $this->model->where('id', $activityId)->update($params);
}
}
My AppServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Entities\Event;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//event: creating
Event::creating(function (Event $event) {
return $event->creatingEvent();
});
//event: saving
Event::saving(function (Event $event) {
return $event->savingEvent();
});
//event: updating
Event::updating(function (Event $event) {
return $event->updatingEvent();
});
}
}
My interface IEvent.php:
<?php
namespace App\Http\Events\Contracts;
interface IEvent
{
public function update($activityId, $params);
}
My ServicesOrchestration.php:
<?php
namespace App\Http\Administration\Providers;
use App\Entities\Event;
use App\Http\Administration\Repositories\RepoEvent;
use Illuminate\Support\ServiceProvider;
class ServicesOrchestration extends ServiceProvider
{
public function boot()
{
}
public function register()
{
$this->app->bind('App\Http\Administration\Contracts\IEvent', function () {
return new RepoEvent(new Event());
});
}
}
My model Event.php
<?php
namespace App\Entities;
use Illuminate\Database\Eloquent\Model;
class Event extends Model
{
public function creatingUser() {
\Log::info('creating event');
}
public function savingUser() {
\Log::info('saving event');
}
public function updatingUser() {
\Log::info('updating event');
}
}
thanks in advance.thanks in advance.thanks in advance.thanks in advance.thanks in advance.thanks in advance
Here's the relevant snipped from the docs (scroll to mass updates):
When issuing a mass update via Eloquent, the saved and updated model events will not be fired for the updated models. This is because the models are never actually retrieved when issuing a mass update.
For your code to work you need to first retrieve the actual model instance like below:
public function update($activityId, $params)
{
$instance = $this->model->find($activityId);
$instance->fill($params);
$instance->save();
}
This will have an additional cost of doing two queries instead of one and only being able to update a single model at a time.
A sidenote: You're passing a model instance to the repository but what you actually want is to pass a query builder instance:
$this->app->bind('App\Http\Administration\Contracts\IEvent', function () {
return new RepoEvent(Event::query());
});

Laravel scout check if relation is not empty?

namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Laravel\Scout\Searchable;
class Event extends Model
{
protected $table = 'events';
public $timestamps = true;
use Searchable;
use SoftDeletes;
protected $dates = ['deleted_at'];
public function entities()
{
return $this->belongsTo('App\Entity', 'entity_id');
}
public function users()
{
return $this->belongsTo('App\User', 'id');
}
public function events()
{
return $this->belongsTo('App\DirtyEvent', 'id');
}
public function toSearchableArray()
{
$data = $this->toArray();
$data['entities'] = $this->entities->toArray();
return $data;
}
}
This is my model for Event, as you can see I am using toSearchableArray which is Laravel scout function to import 'relations' to algolia. However the problem is that sometimes it is empty. So for example
event id 1 has entity_id 1
but in another example
event id 2 has entity_id = null
How can I modify this function to check if the entities() relation is not empty before putting it into array?
if i understand u correctly this should help. if the relationship does not exist return an empty array and scout won't update the index
public function toSearchableArray()
{
if(is_null($this->entities)){
return [];
}
$this->entities
return $this->toArray();
}
please update foreign_key in relation as this
user_id as foreign_key instead of id
event_id as foreign_key instead of id
public function users()
{
return $this->belongsTo('App\User', 'user_id');
}
public function events()
{
return $this->belongsTo('App\DirtyEvent', 'event_id');
}
I think if load the relation before the toArray().
public function toSearchableArray()
{
$this->entities;
return $this->toArray();
}

Laravel 5.4 Eloquent calculated by sql field

how I can append atribute in model, that calculated by sql?
I have try this:
protected $appends = ['comment_qty'];
public function getCommentQtyAttribute()
{
return DB::raw("(select 1) as comment_qty");
}
It's not working
Define a mutator method setCommentQtyAttribute on your model, where comment_qty is your custom column name.
Look at the below...
class Comment extends Eloquent {
protected $table = 'comments';
protected $appends = array('comment_qty');
public function setCommentQtyAttribute()
{
return DB::raw("(select 1) as field");
}
}
For more information : Accessors and mutators
Another yet solution, add to model.
protected static function boot()
{
parent::boot(); // TODO: Change the autogenerated stub
static::addGlobalScope('any', function (Builder $builder) {
$builder->select(['*', DB::raw("'any' as any")]);
});
}

Resources