Specify selected columns in Eloquent model class rather than querybuilder - php

Whenever I use an eloquent model, it will select *, unless I specify it in a querybuilder object. However, I want to specify allowed fields in the class. This would be useful for ensuring the correct user level gets the details they are entitled to, so it property live with the class.
I want to be able to do it as a member variable, like $with:
/**
* #property mixed id
*/
class Attribute extends Model
{
protected $fillable = ["id", "business_id", "attribute_name"];
protected $with = ["attributeDetail", "business"];
protected $selectedFieldsThatMeanSelectStarDoesntHappen = ["id", "business_id", "attribute_name"];
}
So any query using the above class will do SELECT id, business_id, attribute_name whenever the class is used, and not SELECT *.
Does the above functionality exist? The closest I can get is with a global scope:
class Attribute extends Model
{
/**
* The "booted" method of the model.
*
* #return void
*/
protected static function booted()
{
static::addGlobalScope('selectFields', function (Builder $builder) {
$builder->select("id", "business_id", "attribute_name");
});
}
}

You can try it:
Create a new builder and a trait to use this new builder:
class BuilderWithSpecifiedColumns extends Builder
{
public $selectedColumns = [];
public function __construct(ConnectionInterface $connection, Grammar $grammar = null, Processor $processor = null, array $selectedColumns = ['*'])
{
parent::__construct($connection, $grammar, $processor);
$this->selectedColumns = $selectedColumns;
}
/**
* #param string[] $columns
* #return \Illuminate\Support\Collection
*/
public function get($columns = ['*'])
{
return parent::get($this->selectedColumns ? $this->selectedColumns : $columns);
}
}
trait HasSelectedColumns
{
protected function newBaseQueryBuilder()
{
$connection = $this->getConnection();
return new BuilderWithSpecifiedColumns(
$connection,
$connection->getQueryGrammar(),
$connection->getPostProcessor(),
$this->selectedFieldsThatMeanSelectStarDoesntHappen,
);
}
}
Use above trait
/**
* #property mixed id
*/
class Attribute extends Model
{
use HasSelectedColumns;
protected $fillable = ["id", "business_id", "attribute_name"];
protected $with = ["attributeDetail", "business"];
protected $selectedFieldsThatMeanSelectStarDoesntHappen = ["id", "business_id", "attribute_name"];
}

Related

How to delete data using Eloquent query?

I can not delete a row using a simple eloquent query. Even when I am using eloquent can not get the data from DB. I am getting null. But, in DB query method at least I am getting data but can not delete then. Following is my code:
DB::transaction(function () use ($lead, $comment, $request) {
$lead->save();
$lead->comments()->save($comment);
if ($request->deleteAppointment) {
$calendarEvent = DB::table('calendar_events')->where('id', $request->appointmentId)->first(); // I am getting data here.
$calendarEvent = CalendarEvent::find($request->appointmentId); // But, here I am getting null, don't know why!
if ($calendarEvent != null) {
$calendarEvent->delete();
}
}
My goal is to get the data using Eloquent and then Delete from database.
update:
My Database Table
CalendarEvent.php model
class CalendarEvent extends Model
{
use SoftDeletes;
/**
* #var array
*/
protected $casts = [
'event_begin' => 'datetime',
'event_end' => 'datetime',
'options' => 'array',
];
/**
* #var array
*/
protected $guarded = [
'id',
];
/**
* #return mixed
*/
public function users()
{
return $this->morphedByMany(User::class, 'eventable');
}
/**
* #return mixed
*/
public function attendees()
{
return $this->morphedByMany(User::class, 'eventable')->withPivotValue('role', 'atendee');
}
/**
* #return mixed
*/
public function companies()
{
return $this->morphedByMany(Company::class, 'eventable')->withPivotValue('role', 'company');
}
/**
* #return mixed
*/
public function invitees()
{
return $this->morphedByMany(User::class, 'eventable')->withPivotValue('role', 'invitee');
}
/**
* #return mixed
*/
public function leads()
{
return $this->morphedByMany(Lead::class, 'eventable')->withPivotValue('role', 'lead');
}
}
Why not just:
CalendarEvent::where('id', $request->appointmentId)->delete();
Also, check the deleted_at column. If that is not null, then the select will return null, unless you add the ->withTrashed() method.
When using Eloquent objects, the SoftDelete trait is used, when using DB:: directly, then the SoftDelete trait is not used.

In Laravel 5.3 Eloquent how to retrieve 3rd table data with where condition

I have 3 Models(each associated with a table separately) which associated with each other I have attached the table structure below
Models are,
Doctor Model associated with doctor_profile_master
<?php
namespace App\TblModels;
use Illuminate\Database\Eloquent\Model;
class Doctor extends Model
{
/**
* #var string
*/
protected $table = 'DOCTOR_PROFILE_MASTER';
/**
* #var string
*/
protected $primaryKey = 'doctor_profile_master_id';
/**
* #var array
*/
protected $fillable = ['doctor_id', 'user_master_id', 'doctor_first_name', 'doctor_last_name', 'doctor_isactive'];
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function hospitalDoctorAssociateMasters(){
return $this->hasMany('App\TblModels\HospitalDoctorAssociateMaster','doctor_profile_master_id');
}
}
HospitalDoctorAssociateMaster Model associated with hospital_doctor_associate_master
<?php
namespace App\TblModels;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
class HospitalDoctorAssociateMaster extends Model
{
/**
* #var string
*/
protected $table = 'HOSPITAL_DOCTOR_ASSOCIATE_MASTER';
/**
* #var string
*/
protected $primaryKey = 'hospital_doctor_associate_master_id';
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function doctor(){
return $this->belongsTo('App\TblModels\Doctor','doctor_profile_master_id');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function hospital(){
return $this->belongsTo('App\TblModels\Hospital','hospital_profile_master_id');
}
}
HospitalDoctorRecurringSchedule Model associated with hospital_doctor_recurring_schedule
<?php
namespace App\TblModels;
use Illuminate\Database\Eloquent\Model;
class HospitalDoctorRecurringSchedule extends Model
{
/**
* #var string
*/
protected $table = 'HOSPITAL_DOCTOR_RECURRING_SCH_MASTER';
/**
* #var string
*/
protected $primaryKey = 'hospital_doctor_recurring_sch_master_id';
public function hospitalDoctorAssociateMaster(){
return $this->belongsTo('App\TblModels\HospitalDoctorAssociateMaster','hospital_doctor_associate_master_id');
}
}
Thing i want to do is,
How to retrieve the hospital_doctor_recurring_sch_master table data using specific doctor_id(doctor_profile_master)
I tried some methods but cant able to retrieve those values.
Thanks in advance.
You could use something like this:
$hospitalDoctors = HospitalDoctorRecurringSchedule::with(['hospitalDoctorAssociateMaster', 'hospitalDoctorAssociateMaster.doctor', 'hospitalDoctorAssociateMaster.hospital'])->all();
To search by fields in related tables:
$hospitalDoctors = HospitalDoctorRecurringSchedule::with([
'hospitalDoctorAssociateMaster',
'hospitalDoctorAssociateMaster.doctor',
'hospitalDoctorAssociateMaster.hospital'])
->whereHas('hospitalDoctorAssociateMaster.doctor', function ($query) use ($doctorId) {
$query->where('doctor_id', '=', $doctorId);
})
->all();
For hospitalDoctorAssociateMaster.hospital:
Define Hospital Model and try

Laravel pass value to model

Right now I try this query with eloquent:
'MentorId' => $employee->intern(true)->mentor(true)->MentorId,
And in my employee and intern model I've got this:
Intern
/**
* #return mixed
*/
public function intern($withTrashed = false)
{
if($withTrashed == true)
{
return $this->belongsTo(internModel::class, 'InternId')->withTrashed();
}
return $this->belongsTo(internModel::class,'InternId');
}
Mentor
/**
* #return mixed
*/
public function mentor($withTrashed = false)
{
if($withTrashed == true)
{
return $this->belongsTo(mentorModel::class, 'MentorId')->withTrashed();
}
return $this->belongsTo(mentorModel::class,'MentorId');
}
But it crashes:
BadMethodCallException in Builder.php line 2148:
Call to undefined method Illuminate\Database\Query\Builder::mentor()
How could I fix this?
--EDIT--
Employee
<?php
namespace App\src\employee;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\src\department\Department as departmentModel;
use App\src\employee\Employee as employeeModel;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\src\intern\Intern as internModel;
use App\src\mentor\Mentor as mentorModel;
use App\src\employee\Role as roleModel;
class Employee extends Authenticatable
{
use SoftDeletes;
use EmployeeServiceTrait;
/**
* table name
*/
protected $table = 'employee';
/**
* Mass assignment fields
*/
protected $fillable = ['RoleId', 'DepartmentId', 'InternId', 'FirstName', 'LastName', 'Bio','api_token', 'email', 'LinkedIn', 'password', 'Address', 'Zip', 'City', 'ProfilePicture', 'BirthDate', 'StartDate', 'EndDate', 'Suspended','LinkedIn'];
/**
* Primarykey
*/
protected $primaryKey = 'EmployeeId';
/**
* Deleted_at
*/
protected $dates = ['deleted_at'];
/**
* #return mixed
*/
public function role()
{
return $this->belongsTo(roleModel::class,'RoleId');
}
/**
* #return mixed
*/
public function intern($withTrashed = false)
{
if($withTrashed == true)
{
return $this->belongsTo(internModel::class, 'InternId')->withTrashed();
}
return $this->belongsTo(internModel::class,'InternId');
}
/**
* #return mixed
*/
public function department()
{
return $this->belongsTo(departmentModel::class,'DepartmentId');
}
/**
* #return mixed
*/
public function mentor()
{
return $this->belongsTo(mentorModel::class,'MentorId');
}
/**
* #return mixed
*/
public function employees()
{
return $this->hasManyThrough(employeeModel::class,departmentModel::class,'CompanyId','DepartmentId');
}
/**
* #param $role
* #return bool
*/
public function hasRole($role)
{
if(strtolower($this->role->RoleName) == strtolower($role))
{
return true;
}
return false;
}
}
The problem you have is that any Eloquent relationship object is actually an instance of Relation. This means when you create relationships you actually return a collection (instance of Builder); Hense your error:
BadMethodCallException in Builder.php line 2148:
Call to undefined method Illuminate\Database\Query\Builder::mentor()
The simple solution, without any modification to your code would be something like:
'MentorId' => $employee->intern(true)->first()->mentor(true)->first()->MentorId;
However, you could use overloading like the following:
'MentorId' => $employee->intern->mentor->MentorId;
Although this will NOT include your withTrashed. You can however tweak your relationship to something like:
public function intern($withTrashed = false)
{
$relation = $this->belongsTo(internModel::class, 'InternId');
if($withTrashed == true)
{
return $relation->withTrashed()->first();
}
return $relation->first();
}
But I wouldn't advise this because later on if you try using things like WhereHas you will get errors. That said, another way would be to do something along the following lines:
public function intern()
{
return $this->belongsTo(internModel::class, 'InternId');
}
Then get trashed like:
'MentorId' => $employee->intern()->withTrashed()->first()->mentor()->withTrashed()->first()->MentorId;
Try as below as per laravel guide. Keep in mind that parent model must have hasOne/hasMany method and child model must have belongsTo method.
Intern
/**
* #return mixed
*/
public function intern($withTrashed = false)
{
if($withTrashed == true)
{
return $this->hasOne('App\Intern', 'InternId')->withTrashed();
}
return $this->hasOne('App\Intern','InternId');
}
Employee
/**
* #return mixed
*/
public function intern($withTrashed = false)
{
if($withTrashed == true)
{
return $this->belongsTo('App\Intern', 'InternId')->withTrashed();
}
return $this->belongsTo('App\Intern','InternId');
}
Note: Same for all other models.

How to get department name of a module in Laravel models

I am trying to get the department that a module is part of in laravel like:
This is my Faculty class:
<?php
class Faculty extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'faculty';
public $timestamps = false;
/**
* Whitelisted model properties for mass assignment.
*
* #var array
*/
protected $primaryKey='facultyid';
protected $fillable = array('facultyname', 'facultyshort');
public function departments()
{
return $this->hasMany('Departments', 'facultyid');
}
}
This is my Departments class
<?php
class Departments extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'departments';
public $timestamps = false;
/**
* Whitelisted model properties for mass assignment.
*
* #var array
*/
protected $primaryKey='departmentid';
protected $foreignKey='facultyid';
protected $fillable = array('departmentname', 'departmenthead', 'facultyid');
public function modules()
{
return $this->hasMany('Modules', 'departmentid');
}
public function faculty()
{
return $this->belongsTo('Faculty', 'facultyid');
}
}
and finally this is my modules class:
<?php
class Modules extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'modules';
protected $foreignKey='departmentid';
public $timestamps = false;
/**
* Whitelisted model properties for mass assignment.
*
* #var array
*/
protected $primaryKey='mid';
protected $fillable = array('mfulltitle', 'mshorttitle', 'mcode',
'mcrn', 'mfieldofstudy', 'mcoordinator','mlevel',
'mcredits', 'melective', 'departmentid');
public function department()
{
return $this->belongsTo('Departments', 'departmentid');
}
public function classes()
{
return $this->hasMany('Classes', 'moduleid')->orderBy('classid', 'ASC');
}
}
I have tried doing something like this:
#foreach(Modules::where('melective', '=', 1)->get() as $mod)
{{$mod->mshorttitle}} belongs to department: {{ $mod->department->departmentname }}
#endforeach
But it does not work, does anyone have any idea on how to do this?
==============================
SOLUTION
After a bit of work i figured it out
in Department class i added the following function:
public function name()
{
return $this->departmentname;
}
and i changed the code to the following:
#foreach(Modules::where('melective', '=', 1)->get() as $mod)
{{$mod->mshorttitle}} belongs to department: {{ $mod->department->name() }}
#endforeach

laravel 4 pivot table save not working

I am having trouble saving(creating new row) with extra data to a pivot table.
I am having to use a legacy db schema (that is still working on a live site). I am currently redoing the site in Laravel.
<?php namespace Carepilot\Repositories\Organizations;
use Carepilot\Repositories\EloquentRepositoryAbstract;
/*
* This class is the Eloquent Implementation of the Organization Repository
*/
class OrganizationRepositoryEloquent extends EloquentRepositoryAbstract implements OrganizationRepositoryInterface {
/*
* Define Eloquent Organization Type Relation.
*
*/
public function orgtypes()
{
return $this->belongsToMany('Carepilot\Repositories\OrganizationTypes\OrganizationTypesRepositoryEloquent', 'organizations_orgtypes', 'organization_id', 'orgtype_id')
->withPivot('objectstate_id');
}
}
<?php namespace Carepilot\Repositories\OrganizationTypes;
use Carepilot\Repositories\EloquentRepositoryAbstract;
/*
* This class is the Eloquent Implementation of the Organization Repository
*/
class OrganizationTypesRepositoryEloquent extends EloquentRepositoryAbstract implements OrganizationTypesRepositoryInterface {
protected $table = 'orgtypes';
/*
* Define Eloquent Organization Type Relation.
*
*/
public function organizations()
{
return $this->belongsToMany('Carepilot\Repositories\Organizations\OrganizationRepositoryEloquent', 'organizations_orgtypes', 'organization_id', 'orgtype_id')
->withPivot('objectstate_id');
}
}
Here in the Orgaizations controller I try to save a new organization but get an error in the pivot table.
<?php
use \Carepilot\Repositories\Organizations\OrganizationRepositoryInterface;
use \Carepilot\Repositories\Procedures\ProcedureRepositoryInterface;
use \Carepilot\Helpers\StatesHelper;
class OrganizationsController extends BaseController {
/**
* Organization Repository
*
* #var organization_repo
*/
protected $organization_repo;
protected $procedures;
protected $states;
public function __construct(OrganizationRepositoryInterface $organization_repo,
ProcedureRepositoryInterface $procedures,
StatesHelper $states)
{
$this->organization_repo = $organization_repo;
$this->procedures = $procedures;
$this->states = $states;
}
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
return View::make('organizations.index');
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
$supportedStates = ['' => 'Choose'] + $this->states->supportedStates();
$procedures = $this->procedures->getDropDown();
return View::make('organizations.create', compact('supportedStates', 'procedures'));
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
$input = Input::all();
// validation here
$new_organization = $this->organization_repo->create(array_only($input, ['organization_name']));
$input['objectstate_id'] = 27;
$input['orgtype_id'] = 1;
$new_organization->orgtypes->pivot->create(array_only($input, ['objectstate_id', 'orgtype_id']));
$new_organization->addresses()->create(array_only($input, ['street1', 'zip', 'city', 'state_code']));
$input['objectstate_id'] = 4;
$new_organization->users()->create(array_only($input, ['first_name', 'last_name', 'email', 'password', 'objectstate_id']));
return "completed";
}
This returns "Undefined property: Illuminate\Database\Eloquent\Collection::$pivot” because the pivot has not been created yet. What am I missing?
I found that the 'attach' method does what I want with something like
$new_organization->orgtypes()->attach(1, ['objectstate_id' => '27']);

Categories