In my Laravel-5.8, I have these three (3) models:
Parameter
class Parameter extends Model
{
protected $table = 'parameters';
protected $primaryKey = 'id';
protected $fillable = [
'max_score',
'min_score',
'identity_id',
];
public function identity()
{
return $this->belongsTo('App\Models\Identity','identity_id');
}
}
Identity
class Identity extends Model
{
protected $table = 'identity';
protected $fillable = [
'id',
'name',
];
public function goals()
{
return $this->hasMany('App\Models\Goal');
}
public function parameter()
{
return $this->hasOne(Parameter::class, 'identity_id');
}
}
Goal
class Goal extends Model
{
protected $table = 'goals';
protected $fillable = [
'id',
'identity_id',
'title',
];
public function identity()
{
return $this->belongsTo('App\Models\Identity','identity_id');
}
}
From the model, Identity has a foreign key (identity_id) in Parameter, also Identity has foreign key (identity_id) in Goal.
I have this controller in Identity:
public function destroy($id)
{
try
{
$identity = Identity::findOrFail($id);
$identity->delete();
Session::flash('success', 'Record deleted successfully.');
return redirect()->back();
}
catch (Exception $exception) {
Session::flash('error', 'Record delete failed!.');
return redirect()->back();
}
}
I want the user to delete Identity Record based on these conditions:
As the user tries to delete Identity, the application should check Parameter table and also delete the record where identity_id foreign key exist.
Secondly, if record with identity_id exists in Goal table, the application should prevent the delete.
How do I adjust public function destroy($id) to achieve this?
you can add a function like "deleteAll()" in your 'Identify' Model and delete parameter using relation like this:
class Identity extends Model
{
protected $table = 'identity';
protected $fillable = [
'id',
'name',
];
public function goals()
{
return $this->hasMany('App\Models\Goal');
}
public function parameter()
{
return $this->hasOne(Parameter::class, 'identity_id');
}
public function deleteAll(){
if(!$this->goals){
$this->parameter->delete();
return parent::delete();
}
return;
}
}
First in your migrations in the identity you need to do like
$table->foreign('identity_id')->references('id')->on('parameters')->onDelete('cascade');
So when you delete the Identity the related Parameter will be deleted automatically on database level.
To prevent delete (your mentioned 2 case), you need to check like this
$identity = Identity::with('goals')->findOrFail($id);
if($identity->goals){
// you can throw some error here
}
Related
I am trying to update the database record but Laravel update() function is not working. I have fillable array in the model. but still, it is not working.
The Property Model:
class Property extends Model
{
use HasFactory;
protected $table = 'properties';
protected $primaryKey = 'proID';
public $timestamps = false;
protected $fillable = [ 'proID', 'ProStatus', 'ProPurpose', 'ProType', 'SubType', 'basePrice', 'unitPrice', 'Width', 'Length', 'LandArea','PropertyNumber', 'water', 'electricity', 'gas', 'severage', 'fk_Street', 'createdBy', 'delete'];
public function streets(){
return $this->belongsTo(Street::class,'fk_Street');
}
public function hasInstallments(){
return $this->hasMany(Installments::class,'proID');
}
The PropertyController:
public function destroy($id)
{
$property = Property::find($id);
$property->delete = true;
if($property->save()){
return response()->json(['success'=>true]);
}
}
the $property->update() always returns true but record does not update in database.
The method update() is for mass update wich require an array of attributes and bypass mutators.
public function destroy($id)
{
$property = Property::find($id);
$property->update(['delete' => 1]);
}
You might want to use save() instead
public function destroy($id)
{
$property = Property::find($id);
$property->delete = 1;
$property->save();
}
Both will update the record, you'll need to implement your method's return logic on top of this code but as for updating the record, I think you get the idea.
Your property table primary key is "proID"
public function destroy($id)
{
$property = Property::where('proID', $id)->first();
if($property->update(['delete' => 1])) {
return response()->json(['success' => true]);
}
}
i have use laravel and i have this models and relationship between tables
Customers table
class Customers extends Model
{
public $primaryKey = 'id';
protected $fillable = [
'contr_nom',
'contr_cog',
'benef_nom',
'benef_cog',
'email',
'polizza',
'targa',
'iban',
'int_iban',
'cliente',
];
public function claims()
{
return $this->hasMany(Claims::class);
}
public function refunds()
{
return $this->hasManyThrough(Refunds::class, Claims::class);
}
}
claims table
class Claims extends Model
{
public $primaryKey = 'id';
protected $fillable = [
'dossier',
'date_cla',
];
public function refunds()
{
return $this->hasMany(Refunds::class);
}
public function customers()
{
return $this->belongsTo(Customers::class,'customers_id');
}
}
refunds table
class Refunds extends Model
{
public $primaryKey = 'id';
protected $fillable = [
'date_ref',
'status_ref',
'disactive',
'num_pre',
'date_liq',
];
public function services()
{
return $this->belongsToMany(Services::class)
->withPivot(['services_id','services_amount','services_status']);
}
public function claims()
{
return $this->belongsTo(Claims::class,'claims_id');
}
}
in controller i did this function
public function addDateLiq2(Request $request){
$date_liq = request("date_liq");
$refunds = Refunds::whereNotNull('num_pre')->get();
foreach ($refunds as $refund) {
$status_ref= $refund->status_ref;
if ($status_ref == 5){
//send mail
//I need to retrieve mail field from customers table
}
$refund->date_liq = $date_liq;
$refund->save();
if(!$refund->save()){
App::abort(500, 'Error');
}
}
return Response::json(array('success' => 'Date salvate massivamente correttamente!'), 200);
}
that add a date in all records where num_pre is not null.
OK i wanted also send a mail but mail field is in Customer parent table....how can i access it?
Thx
Ok i seem i found a way with this in function addDateLiq2
$data = Claims::with(array('customers'=>function($query){
$query->select('id','email');
}))
->whereHas('refunds', function($query) use($claims_id) {
$query->where('claims_id', $claims_id);
})
->first();
In my Laravel-5.8 project, I have these models
HrGradeLevel
class HrGradeLevel extends Model
{
protected $table = 'hr_grade_levels';
protected $fillable = [
'grade_level_code',
'grade_level_name',
'description',
];
public function designation(){
return $this->hasMany('App\Models\Hr\HrDesignation');
}
public function employee(){
return $this->hasMany('App\Models\Hr\HrEmployee');
}
}
HrDesignation
class HrDesignation extends Model
{
protected $table = 'hr_designations';
protected $fillable = [
'designation_name',
'grade_level_id',
];
protected $casts = [];
public function gradelevel()
{
return $this->belongsTo('App\Models\Hr\HrGradeLevel','grade_level_id');
}
}
HrEmployee
class HrEmployee extends Model
{
protected $table = 'hr_employees';
protected $fillable = [
'first_name',
'last_name',
'grade_level_id',
];
protected $casts = [];
public function gradelevel()
{
return $this->belongsTo('App\Models\Hr\HrGradeLevel','grade_level_id');
}
}
HrDesignation and HrEmployee has foreign key grade_level_id that is derived from HrGradeLevel
HrGradeLevelController
public function destroy(Request $request, $id)
{
$grade = HrGradeLevel::find($id);
$grade->delete();
Session::flash('success', 'Grade Level deleted successfully.');
return redirect()->route('hr.grade_level.index');
}
From the Controller above, the user can delete HrGradeLevel row.
Using Laravel, before the user is allowed to delete I want the application to check HrDesignation and HrEmployee, if any of them have data in grade_level_id, I want the application to display a message and it shouldn't allow delete.
How do I achieve this?
Thank you.
You have 2 options:
Use foreign key constraints on your migrations and MySQL will prevent deleting a record if foreign key is used on other tables/records by default:
public function destroy(Request $request, $id)
{
$grade = HrGradeLevel::find($id);
try {
$grade->delete();
}
catch (\Illuminate\Database\QueryException $e) {
if ($e->getCode() == 23000)
{
//SQLSTATE[23000]: Integrity constraint violation
abort('Resource cannot be deleted due to existence of related resources.');
}
}
Session::flash('success', 'Grade Level deleted successfully.');
return redirect()->route('hr.grade_level.index');
}
Check existence of your relationships before deleting:
public function destroy(Request $request, $id)
{
$grade = HrGradeLevel::find($id);
if ($grade->designation()->exists()
|| $grade->employee()->exists())
{
abort('Resource cannot be deleted due to existence of related resources.');
}
$grade->delete();
Session::flash('success', 'Grade Level deleted successfully.');
return redirect()->route('hr.grade_level.index');
}
I have 2 models. The User model, and the relationship works correctly, I use tinker, and I can see the application that is associated with the user.
User::find(4)->application
However, the application will not return the user - in tinker I get null, whats worse, if I try to access rep in tinker, I get Bad Method Exception Call
Application::find(8)->user
is null
Note: I have an id column in users which I "find" users. and there is "ucid" column in users that I have defined as the primaryKey in Application.
Application Model:
class Application extends Model
{
protected $data = [
'data' => 'array'
];
protected $primaryKey = 'ucid';
protected $fillable = [
'ucid', 'data'
];
public function user()
{
return $this->belongsTo(User::class,'ucid');
}
public function rep()
{
return 'Test';
}
}
User Model
class User extends Authenticatable
{
public function application()
{
return $this->hasOne(Application::class,'ucid');
}
}
What am I missing?
Can you try this? Let me know if it works..
Application Model
class Application extends Model
{
protected $data = [
'data' => 'array'
];
protected $primaryKey = 'ucid';
protected $fillable = [
'ucid', 'data'
];
public function user()
{
return $this->hasOne(User::class, 'ucid');
}
public function rep()
{
return 'Test';
}
}
User Model
class User extends Authenticatable
{
public function application()
{
return $this->belongsTo(Application::class, 'ucid', 'ucid');
}
}
As you see I switched hasOne and belongsTo in your models.
Also.. third argument on hasOne of Application Model is not required since value from $primaryKey will be used since its defined, however you have to specify the third argument in belongsTo of User model
I have a API and its taking long time to get all the info and its because I'm only hidding some data but I want to omit not to hidde. I found select() method to chose wich data send and reduce the time to query all information I really need.
Im trying to use select just after the relation just like this, just to retrieve only name from OPR_User table:
public function creatorUser() {
return $this->belongsTo('Knotion\OPR_User', 'idCreatorUser', 'idUser')->select('name');
}
but is not working
This is my Model code
<?php
namespace Knotion;
use Illuminate\Database\Eloquent\Model;
class CTL_Resource extends Model {
protected $table = "CTL_Resource";
protected $primaryKey = "idResource";
public $incrementing = false;
public $timestamps = false;
public static $snakeAttributes = false;
protected $hidden = [
'coachVisibility', 'thumbnail',
'studentVisibility', 'isHTML','studentIndex', 'coachIndex',
'isURL', 'source', 'path', 'status', 'updateTime', 'isfolder',
'parentResource', 'idModifierUser', 'idResourceType', 'idCreatorUser', 'idCreationCountry'
];
protected $fillable = ['idResourceType','productionKey', 'idCreatorUser', 'idModifierUser', 'idCreationCountry', 'title', 'description', 'URL', 'fileName', 'extension', 'minimumAge', 'maximumAge', 'productionKey'];
public function creatorUser() {
return $this->belongsTo('Knotion\OPR_User', 'idCreatorUser', 'idUser');
}
public function creationCountry() {
return $this->belongsTo('Knotion\CTL_Country', 'idCreationCountry', 'idCountry');
}
public function resourceType() {
return $this->belongsTo('Knotion\CTL_ResourceType', 'idResourceType', 'idResourceType');
}
public function quickTags() {
return $this->belongsToMany('Knotion\CTL_QuickTag', 'CTL_Resource_has_QuickTags', 'idResource','idQuickTag');
}
public function tags() {
return $this->belongsToMany('Knotion\CTL_Tag','CTL_Resource_has_Tags', 'idResource', 'idTag');
}
public function relatedTo() {
return $this->belongsToMany('Knotion\CTL_RelatedTo', 'CTL_Resource_has_RelatedTo', 'idResource', 'idRelatedTo');
}
}
this is my relation model code (just in case needed):
<?php
namespace Knotion;
use Illuminate\Database\Eloquent\Model;
class OPR_User extends Model {
protected $table = "OPR_User";
protected $primaryKey = "idUser";
public $incrementing = false;
public $timestamps = false;
public static $snakeAttributes = false;
protected $hidden = ['firstName', 'secondName', 'firstSurName', 'secondSurName', 'password', 'picture', 'status', 'createTime', 'updateTime', 'idUserType', 'email'];
public function resources() {
return $this->hasMany('Knotion\CTL_Resource', 'idResource');
}
public function userType() {
return $this->belongsTo('Knotion\CTL_UserType', 'idUserType', 'idUserType');
}
}
and this is my Controller code:
public function index(Request $request) {
$resources = CTL_Resource::all();
$resources->resourceType->select('name');
return $resources->load('creatorUser', 'creationCountry', 'resourceType', 'tags', 'quickTags', 'relatedTo');
}
When you add the ->select after the ->belongsTo it's no longer an actual relationship type, it's a query builder. You need to add the select afterwards before you call the ->load.
To fix the problem I had to include the id also in the relation, something like this:
public function resources() {
return $this->hasMany('Knotion\CTL_Resource', 'idResource')->select('idResource', 'name');
}