Laravel 5.1 Delete relationships - php

My models relationship is oneToMany eg: PatientToSample
Patient_Model:
class Patient_Model extends Model implements Jsonable{
use SoftDeletes;
protected $table = 'patients';
public function samples(){
return $this->hasMany('App\Models\Sample_Model','code','patient_id');
}
}
Sample_Model :
class Sample_Model extends Model{
use SoftDeletes;
protected $table = 'samples';
public function patient(){
return $this->belongsTo('App\Models\Patient_Model','patient_id','code');
}
}
I think use the function delete Patient and Sample
public function delete(Request $request){
$patient = Patient_Model::withTrashed()
->where("id",$request->get("id"))
->delete();
return json_encode($patient);
}
But now only delete Patient....

This is one way to do it.
public function delete(Request $request){
$patient = Patient_Model::withTrashed()
->find($request->get("id"));
$patient->samples()->delete();
$patient->delete();
return json_encode($patient);
}
There is also a way to attach the relationship deletion to a delete event of the parent model, as discussed here.

Did you set constraints in migration?
Just write into Sample table migration row:
$table->foreign('patient_id')
->references('id')
->on('patients')
->onDelete('cascade');
For more info: Docs

Related

Problem with Laravel Eloquent - relation not working

I'am beginner in Laravel. I have project in Laravel 5.8.
I have User model:
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable;
use psCMS\Presenters\UserPresenter;
use scopeActiveTrait;
public static $roles = [];
public $dates = ['last_activity'];
// ...
public function scopeHistory()
{
return $this->hasMany('App\UserLoginHistory');
}
// ...
}
and UserLoginHistory:
class UserLoginHistory extends Model
{
protected $quarded = ['id'];
public $timestamps = false;
protected $fillable = ['user_id', 'date_time', 'ip'];
public function user()
{
return $this->belongsTo('App\User');
}
}
I want show user login history by this code:
User::history()->where('id', $idAdmin)->orderBy('id', 'desc')->paginate(25);
but it's not working.
This function not working - I haven't got results.
How can I fixed it?
First of all, you are defining your relationship as a scope (prefixing the relationship with the scope keyword). Try updating your model relationship to this:
public function history()
{
return $this->hasMany('App\UserLoginHistory');
}
Then, given your query, it seems that you want to get all the UserLoginHistory
records for a given User. You could accomplish this in two ways (at least).
From the UserLoginHistory model itself, constraining the query by the foreign key value:
$userId = auth()->id(); // get the user ID here.
$results = UserLoginHistory::where('user_id', $userId)->paginate(15);
// ^^^^^^^ your FK column name
From the User model using your defined relationship:
$userId = auth()->id(); // get the user ID here.
$results = User::find($userId)->history;
The downside of the second approach is that you'll need to paginate the results manually.
in your User model you should define your relation by this way :
public function history()
{
return $this->hasMany('App\UserLoginHistory');
}
then if you would like to select with history model you can do that with WhereHas() method :
User::whereHas(['history'=>function($q) use ($idAdmin) {
$q->where('id',$idAdmin)
}])->orderBy('id', 'desc')->paginate(25);
You must be do this changes
public function history()
{
return $this->hasMany('App\UserLoginHistory');
}
usage
$user = User::find($idAdmin);
$userHistories = $user->history()->latest()->paginate(25);
or get user with all history
User::with('history')->find($idAdmin);
// Post model
namespace App;
use App\User;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function categories()
{
return $this->belongsToMany('App\Category')->withTimestamps();
}
}
// Category model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
public function posts()
{
return $this->belongsToMany('App\Post')->withTimestamps();
}
}

How can I use soft deleted with relation

I use eloquent with soft delete .I'm getting error because of my query still select data that already use softdelete here is my model
User Model
class User extends Authenticatable
{
use Notifiable, HasRoles, SoftDeletes;
protected $guard_name = 'web';
protected $fillable = [
'username', 'password'
];
protected $dates = ['deleted_at'];
}
for example I've 100 user and I deleted 1 user with softdelete . then I try to
$a = User::all();
dd($a);
I get 99 user . It works! but after I use it relation It doest work here what I do
This is my Parent table and Model
table
|id|user_id|parent_id|
Note : user_id and parent_id are FK in user.id table
class Parent extends Model
{
protected $table = 'parent';
public function user()
{
return $this->belongsTo('App\User');
}
}
$getParent = Parent::with('user')->get();
when I dd($getParent); why I still get null data from user_id that I already use soft deleted ?
UPDATE model User : after I put whereNull I still getting user that I alredy soft deleted
public function user()
{
return $this->belongsTo('App\User')->whereNull('users.deleted_at');
}
https://laravel.com/docs/5.7/eloquent#querying-soft-deleted-models
...
public function customerAddress()
{
return $this->hasOne(Addresses::class, "id", "id_address")->withTrashed();
}
...
Ok, here's what I think is going on...
With soft delete the ondelete event doesn't work (meaning that related models is not deleted). I'm not sure if that changed in later versions of Laravel, but I don't think so. Also deleting User would still not affect the parent model, since you haven't defined the relationship between User and Parent (in the User model), only between Parent and User.
Try defining the relationship in User and then override the boot() function, that sits in the Model class. (This is untested code, but something like this should do the job)
class User extends Authenticatable
{
use Notifiable, HasRoles, SoftDeletes;
protected $guard_name = 'web';
protected $fillable = [
'username', 'password'
];
protected $dates = ['deleted_at'];
// Override Model boot function
protected static function boot()
{
parent::boot();
static::deleting(function ($users) {
foreach ($users->parents()->get() as $parent) {
$parent->delete();
}
});
}
// Define relationship with parent model
public function parents()
{
$this->hasMany('App\Parent');
}
}
You can put a constraint on the Eager Load:
public function groups()
{
return $this
->belongsToMany('Group')
->whereNull('group_user.deleted_at') // Table `group_user` has column `deleted_at`
->withTimestamps(); // Table `group_user` has columns: `created_at`, `updated_at`
}
Instead of HARD deleting the relationship using:
User::find(1)->groups()->detach();
You should use something like this to SOFT delete instead:
DB::table('group_user')
->where('user_id', $user_id)
->where('group_id', $group_id)
->update(array('deleted_at' => DB::raw('NOW()')));

Handling mapping table in laravel eloquent

In my application, there will be multiple investors tagged for single purchase entry. So on loading a purchase entry, I should get all the investors associated.
In my controller,
return response()->json(GoldPurchase::with('investors')->get());
Mapping table schema,
Schema::create('gold_purchase_investor', function (Blueprint $table) {
$table->increments('id');
$table->integer('investor_id')->unsigned();
$table->integer('purchase_id')->unsigned();
$table->timestamps();
$table->foreign('investor_id')
->references('id')
->on('investors')
->onDelete('cascade');
$table->foreign('purchase_id')
->references('id')
->on('gold_purchases')
->onDelete('cascade');
});
Purchase model,
class GoldPurchase extends Model
{
public function investors() {
return $this->hasMany('App\GoldPurchaseInvestor');
}
}
Investor model,
class Investor extends Model
{
protected $fillable = ['name', 'address', 'mobile', 'email'];
public function purchases() {
return $this->hasMany('App\GoldPurchase');
}
}
PurchaseInvestor model,
class GoldPurchaseInvestor extends Model
{
protected $table = 'gold_purchase_investor';
public function purchase() {
return $this->belongsTo('App\GoldPurchase');
}
public function investor() {
return $this->belongsTo('App\Investor');
}
}
With this, I am getting error,
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'gold_purchase_investor.gold_purchase_id' in 'where clause' (SQL: select * from `gold_purchase_investor` where `gold_purchase_investor`.`gold_purchase_id` in (1))
You have to specify the custom foreign key:
public function investors() {
return $this->hasMany('App\GoldPurchaseInvestor', 'purchase_id');
}
But this is actually a case for a BelongsToMany relationship:
public function investors() {
return $this->belongsToMany('App\Investor', 'gold_purchase_investor', 'purchase_id');
}
From the Eloquent Relationship:
Remember, Eloquent will automatically determine the proper foreign key column on the Comment model. By convention, Eloquent will take the "snake case" name of the owning model and suffix it with _id. So, for this example, Eloquent will assume the foreign key on the Comment model is post_id.
$this->hasMany('App\Comment', 'foreign_key', 'local_key');
So try to write your foreign key and local key in the relationships
In your case I think it would be something like that:
class GoldPurchase extends Model`
{
public function investors() {
return $this->hasMany('App\GoldPurchaseInvestor', 'investor_id', 'id');
}
}
Use belongsToMany for many-to-many relationships.
GoldPurchase.php
class GoldPurchase extends Model{
public function investors() {
return $this->belongsToMany('App\Investor','gold_purchase_investor','purchase_id','investor_id');
}
}
Investor.php
class Investor extends Model{
protected $fillable = ['name', 'address', 'mobile', 'email'];
public function purchases() {
return $this->belongsToMany('App\GoldPurchase','gold_purchase_investor','investor_id','purchase_id');
}
}
You don't need a third model for pivot table at all.
GoldPurchaseInvestor is not at all needed.

Laravel 5.4 many to many relationships with foreign key

i'm using a data table with name auct_lots_full for my Lot.php model, where primary key is lot_id, in order everything to work i used Sofa/Eloquence extension, Mappable. So this is my model :
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Sofa\Eloquence\Eloquence;
use Sofa\Eloquence\Mappable;
class Lot extends Model
{
use Eloquence, Mappable;
protected $table = 'auct_lots_full';
protected $maps =[
'id' => 'lot_id',
];
public function scopeFilter($query, QueryFilter $filters)
{
return $filters->apply($query);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
}
But he problem is that in some cases it keeps looking for id column as primary key. For example in LotsController.php i have this problem here :
public function show($id)
{
$lot = Lot::find($id);
return view('lots.show')->withLot($lot);
}
But i fix this problem with this solution:
public function show($id)
{
$lot = Lot::where('lot_id', $id)->first();
return view('lots.show')->withLot($lot);
}
But i understand that is just a solution for only this function...
So the same problem i have in CommentsController.php:
public function show()
{
$comments = Comment::orderBy('id', 'desc')->paginate(30);
return view('comments.browse', compact('comments'));
}
And i don't know how to fix it. Could any one explain me why is this happening? Is there a better way than use an extension? How i can fix this error in CommentsCotroller.php ?
This is the Comment.php model:
<?php
namespace App;
class Comment extends Model
{
public function lot()
{
return $this->belongsTo(Lot::class);
}
public function User()
{
return $this->belongsTo(User::class);
}
}
There is a primaryKey variable in your Model file which is id by default.
/**
* The primary key for the model.
*
* #var string
*/
protected $primaryKey = 'id';
If you override this variable in Lot model file. So your primary key will be lot_id instead of id as in default. Simply add this;
protected $primaryKey = 'lot_id';
So actually i find a proper way to do it with out Sofa/Eloquence extension, using not only foreign key but also a local key in many to many relationship. So this is the new code:
so for Lot.php i did this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Lot extends Model
{
protected $table = 'auct_lots_full';
protected $primaryKey = 'lot_id';
public function scopeFilter($query, QueryFilter $filters)
{
return $filters->apply($query);
}
public function comments()
{
return $this->hasMany(Comment::class,'lot_id', 'lot_id');
}
}
Than i did same for the Comment.php model:
<?php
namespace App;
class Comment extends Model
{
public function lot()
{
return $this->belongsTo(Lot::class, 'lot_id', 'lot_id');
}
public function User()
{
return $this->belongsTo(User::class);
}
}
So what we see above, in Lot.php model, function comments i pass foreignKey: 'lot_id' in auct_lots_full table and localKey 'lot_id' in comments table witch refers to the auct_lots_full table. In Comment.php model wi did the same but in case instead of localKey it is ownerKey. Im a bad at explaining so i will attach some images to make sense.
Lot.php
Comment.php

One-To-One Eloquent Relationship functions

There is something I miss in the eloquent one-to-one relationship:
class MeetingTest extends Model
{
protected $table = 'meeting_tests';
public function meeting() {
return $this->belongsTo('App\Meeting','meeting_id','id');
}
public function observation() {
return $this->hasOne('App\Observation','meeting_test_id','id');
}
public function activity() {
return $this->hasOne('App\TestActivity','activity_id','id');
}
}
The Observation Class is
class Observation extends Model
{
protected $table = 'observations';
public function meetingTest() {
return $this->belongsTo('App\MeetingTest','meeting_test_id','id');
}
}
If I run php artisan tinker and
$mtn = App\MeetingTest::create();
$mtn->save();
$ob = App\Observation::create();
$ob->save;
$mtn->observation()->save($ob);
At this point inside the Observation record I can see the meeting_test_id filled with the correct id of the meetingTest, but if I try:
$mtn->observation
it gives me null; and in the Database there is no observation ID in the observation_id field;
this is the migration:
Schema::create('meeting_tests', function (Blueprint $table) {
$table->increments('id');
$table->integer('meeting_id')->unsigned();
$table->integer('observation_id')->unsigned()->nullable();
$table->integer('activity_id')->unsigned()->nullable();
$table->timestamps();
});
I don't understand what is not correct.
I can see observation_id and activity_id in your meeting_tests table, which makes records in this table the owned side of one-to-one/one-to-many relation. Therefore, both activity and observation relations in MeetingTest should return $this->belongsTo instead of $this->hasOne

Categories