Laravel Eloquent Advance Querying - laravel

I have 5 different tables as projects, systems, attachments, tasks, users on Laravel I haven't assign a relationship for each table what I am trying to do is linking each table using ID.
$objFetch = Task::addSelect(
[
'project_id' => Project::select('title')->whereColumn('project_id', 'projects.id'),
'tester_id' => User::select('name')->whereColumn('tester_id', 'users.id'),
'system_id' => System::select('name')->whereColumn('system_id', 'systems.id'),
'assigned_id' => User::select('name')->whereColumn('assigned_id', 'users.id'),
],
)->paginate(20);
This return the expected output as
{
"id": 1,
"document_auto_id": 101,
"document_type": null,
"document_name": "Tasks",
"file_name": "Task_394_1622175671_195.png",
"file_extention": "png",
"file_size": "105383",
"note": null,
"created_at": "2021-05-28T04:21:11.000000Z",
"updated_at": "2021-05-28T04:21:11.000000Z"
},
Question is there any solutions to get the attachments for each tasks?
Laravel Eloquent answer is highly appreciated instead of Query building

DB tables are often related to one another. therefore we can use table ID to get the output. the error occurs because I have not defined it on the Model. THE PROBLEM WAS SOLVED AS I DO FOLLOWING STEPS
MODEL
class Task extends Model
{
use HasFactory;
protected $fillable = [
'title',
'priority',
'project_id',
'system_id',
'tester_id',
'assigned_id',
'description',
'status',
];
protected $casts = [
'attachments' => 'array',
];
public function Attachment()
{
return $this->hasMany(Attachment::class, 'document_auto_id');
}
public function Project()
{
return $this->hasOne(Project::class, 'id', 'project_id');
}
public function System()
{
return $this->hasOne(System::class, 'id', 'system_id');
}
public function assignedTo()
{
return $this->hasOne(User::class, 'id','assigned_id');
}
public function testerTo()
{
return $this->hasOne(User::class, 'id','tester_id');
}
}
FETCHING DATA WITH RELEVANT TABLES
$objFetch1 = Task::with(
'testerTo',
'assignedTo',
'System',
'Project',
'Attachment'
)->get();

Related

Laravel - How to consume and refresh external api into db using Guzzle

I am having this model in my Laravel-5.8 project:
Employee
class Employee extends Model
{
protected $table = 'employees';
protected $primaryKey = 'id';
protected $fillable = [
'staff_code',
'first_name',
'last_name',
'department_id',
];
public function department()
{
return $this->belongsTo('App\Department','department_id');
}
}
That is,:
App\Employee
Also I have an external api that comes in form of JSON get request.
https://api.employees.net/allemployees
I have viewed it with postman get request and I have something like this:
{
"ID": "1",
"StaffCode": "STC001",
"FirstName": "Japheth",
"LastName": "Shalom",
"DepartmentCode": "dep2",
},
{
"ID": "2",
"StaffCode": "STC002",
"FirstName": "Ahitophel",
"last_name": "Nedum",
"DepartmentCode": "dep1",
},
{
"ID": "3",
"StaffCode": "STC003",
"FirstName": "Joash",
"FirstName": "Nathan",
"DepartmentCode": "dep2",
},
and so on... this continues
Already I have created this function:
use App\Employee;
use App\Department;
public function index()
{
$client = new GuzzleHttp\Client();
$res = $client->request('GET','https://api.employees.net/allemployees');
$clientdatas = json_decode($res, true);
...
}
Apart from the id and staff_code that are UNIQUE, any of the others fields too can change from the source.
Since any of the fields can change at any time. How do I refresh the entire db, save new data and update changes?
Thank you
I could do something like this:
use App\Employee;
use App\Department;
public function index()
{
$client = new GuzzleHttp\Client();
$res = $client->request('GET','https://api.employees.net/allemployees');
$clientdatas = json_decode($res->getBody()->getContents(), true);
foreach($clientdatas as $clientdata)
{
$employee = Employee::firstOrNew(['id' => $clientdata['ID']]);
$employee->staff_code = $clientdata['StaffCode'];
$employee->first_name = $clientdata['FirstName'];
$employee->last_name = $clientdata['LastName'];
$employee->save();
}
}
Every time you will make an API call, create an instance of the employee model, or get the associated model if the ID exists. Then assign the new values and save your model. This way, you will be able to either create or update the models in a single loop without any complexities.
Don't know will it work or not but the logic you can keep.. In the other answer he is querying under a loop which is bad!
Hope It will Help you a little bit
public function index() {
$client = new GuzzleHttp\Client();
$res = $client->request('GET','https://api.employees.net/allemployees');
$clientdatas = json_decode($res->getBody()->getContents(), true);
// create a blank array for insert
$insert_arr = [];
foreach($clientdatas as $clientdata) {
$make_array = [
'id' => $clientdata['ID'],
'staff_code' => $clientdata['StaffCode'],
'first_name' => $clientdata['FirstName'],
.
.
];
array_push($insert_arr, $make_array);
// Now the the $insert_arr will ready for insert
}
// Here you have to check its duplicate or not
$exist_in_db = Employee::all('id')->toArray(); // get the id array from db
// do the stuff for unset the duplicate
$final_id = array_map(function($value) {
return $value['id'];
}, $team_id);
unset($exist_in_db);
if(count($final_id) > 0){
foreach ($insert_arr as $key => $value) {
if (in_array($value['id'], $final_id)) {
unset($insert_arr[$key]);
} else {
array_push($final_id, $value['id']);
}
}
}
// finally insert it here
if (count($insert_arr) > 0) {
Employee::insert($insert_arr);
}
}
Let me know its helpful or not!

Base table or view not found: 1146 Table 'pht.location_id' doesn't exist

I have no table in my database in this name (location_id) but it gives me the error.
"message": "SQLSTATE[42S02]: Base table or view not found: 1146 Table
'pht.location_id' doesn't exist (SQL: select locations.*,
location_id.location_trails_id as pivot_location_trails_id,
location_id.location_id as pivot_location_id from locations
inner join location_id on locations.id =
location_id.location_id where location_id.location_trails_id
in (11, 13, 15, 16, 121, 123, 124, 181))",
I cannot find how to resolve it. Please Help me To resolve this issue. Thanks In advance.
Here is the code of my controller.
public function get($id)
{
$locations = LocationTrails::whereTrailId($id)->with('locations')->orderBy('ordered','ASC')->get();
dd($locations);
// $locations = Trail::findOrFail($id)->locations()->paginate($this->perPage);
// dd($locations);
$tdata = [];
foreach($locations->items() as $location) {
$hints = $location->hints;
$hintsData = [];
foreach($hints as $hint) {
$hintsData[] = [
'title' => $hint->title,
'hint_text' => $hint->hint_text,
'hint_solution_text' => $hint->hint_solution_text,
'hint_image_path' => $hint->hint_image_path,
'hint_video_path' => $hint->hint_video_path,
'complexity_order' => $hint->complexity_order
];
}
$tdata[] = [
'id' => $location->id,
'title' => $location->title,
'radius' => $location->radius,
'latitude' => $location->latitude,
'longitude' => $location->longitude,
'rewards_points' => $location->rewards_points,
'location_info_link' => $location->location_info_link,
'hints' => $hintsData
];
}
$data = [];
$data['data'] = $tdata;
$data['meta']['paginator'] = $this->getPaginatorInfo($locations);
return $data;
}
Here is my model of location
class Location extends Model
{
protected $table = 'locations';
protected $fillable = [
'title', 'radius', 'latitude', 'longitude', 'rewards_points', 'location_info_link', 'location_order'
];
/********************* RELATIONS *********************/
public function trails()
{
return $this->belongsToMany(Trail::class);
}
public function hints()
{
return $this->hasMany(LocationHint::class);
}
public function location_trails()
{
return $this->belongsTo(LocationTrails::class,'location_id');
}
Here is my locationtrail model:
class LocationTrails extends Model
{
protected $table = 'location_trail';
protected $fillable = [
'location_id', 'trail_id', 'ordered', 'created_at', 'updated_at',
];
/********************* RELATIONS *********************/
public function trails()
{
return $this->belongsToMany(Trail::class,'trail_id');
}
public function locations()
{
return $this->belongsToMany(Location::class,'location_id');
}
problem is in your LocationTrails model. You define your method like $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id'); so, laravel think location_id is a table name and the error thrown.
If it is one to many relationship.
public function locations()
{
return $this->hasMany(Location::class,'location_id');
}
If it is many to many relationship then you can see this.
https://laravel.com/docs/5.8/eloquent-relationships#many-to-many
same for your trails() method.
public function trails()
{
return $this->hasMany(Trail::class,'trail_id');
}

Eloquent does not add foreign key from relation

I could not find an answer to my problem and I hope I can describe it properly. I do hope to be able to provide all necessary information.
Bottom line: Why does the relations parent ID not get injected on creating a new database entry through the parent model.
I have an Occasions model which holds a collection of pictures. Within the addPicture ($name, $filepath) method the exception is thrown. As pointed out rhough code-comments
Occasion.php
// namespace + use directives omitted
class Occasion extends Model
{
use Sluggable;
protected $fillable = [ 'name', 'root-folder', 'path' ];
public function sluggable ()
{
return [
'slug' => [
'source' => [ 'root-folder', 'name', ],
],
];
}
public function pictures ()
{
return $this->hasMany(picture::class);
}
public function addPicture ($name, $filepath)
{
$thumbname = $this->getThumbFilename($filepath);
dump($this,$this->pictures()); // dump to check my data
$pic = Picture::create(compact('name', 'thumbname'));
// this line is never reached
$pic->createThumb($filepath);
}
...
}
Picture.php:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Spatie\Glide\GlideImage;
class Picture extends Model
{
protected $fillable = [ 'name', 'thumbname' ];
public function createThumb ($filepath)
{
$this->ppath = storage_path('app') . "/" . $filepath;
$this->tpath = storage_path('app/public/thumbs') . "/" . $this->getfilename($filepath);
GlideImage::create($this->ppath)->modify([ 'w' => 100, 'h' => 100, 'fit' => 'max' ])->save($this->tpath);
$this->save();
}
public function occasion ()
{
return $this->belongsTo(Occasion::class);
}
/* public function slideshow ()
{
return $this->belongsToMany(Slideshow::class);
}*/
private function getfilename ($path)
{
$tmp = array_slice(explode('/', $path), -3);
return str_replace(" ", "-", implode("-", $tmp));
}
}
The result of dump($this->pictures()); shows the relation and the columns used:
HasMany {#206 ▼
#foreignKey: "pictures.occasion_id"
#localKey: "id"
#query: Builder {#205 ▶}
#parent: Occasion {#215 ▶}
#related: Picture {#210 ▶}
}
But I'm getting an error message telling me that my occasion_id (in pictures table) is missing a default value. Looking at the built query the occasion_id is indeed missing. What I can't figure out is why said ID does not get injected as I am creating the new picture instance through an occasion-object.
QueryException
SQLSTATE[HY000]: General error: 1364 Field 'occasion_id' doesn't have a default value (SQL: insert into `pictures` (`name`, `thumbname`, `updated_at`, `created_at`) values (IMG_0015.JPG, 2006-PVanlage-06-IMG_0015.JPG, 2017-09-12 19:34:07, 2017-09-12 19:34:07))
I hope that all necessary information is provided.
First you need to add "occasion_id" to fillable array in App\Picture model. Secondly, you need to create occasion object first, then pass the ID addPicture to create picture object, see below
public Picture extends Model{
public $fillable = ['name', 'filepath', 'occasion_id'];
public function occasion(){
$this->belongsTo(App\Occassion::class);
}
}
public function addPicture ($name, $filepath, $occasion_id)
{
$thumbname = $this->getThumbFilename($filepath);
dump($this,$this->pictures()); // dump to check my data
$pic = Picture::create(compact('name', 'thumbname', 'occasion_id'));
// this line is never reached
$pic->createThumb($filepath);
}
There's a smarter way to do this, but this should work.

Yii2- get from related table name to add to Sluggable

Yii2. How can i get data from the related table and add it to Sluggable behavior.
In the example below, I want for every book add slug-title like "Book House, author Greenberg".
class Books extends \yii\db\ActiveRecord
{
public function behaviors()
{
return [
[
'class' => SluggableBehavior::className(),
'attribute' => "Book" . $this->name . ", author " . $this->getAuthor->name,
//'slugAttribute' => 'slug',
],
];
}
public function getAuthor()
{
return $this->hasOne(Author::className(), ['id' => 'author_id']);
}
}
Simply use a callback for the sluggable behavior like so:
public function behaviors()
{
return [
[
'class'=>SluggableBehavior::className(),
'value'=>function ($event) {
$parts = ['Book', $this->name, 'author', $this->author->name];
return Inflector::slug(implode('-', $parts));
},
],
];
}
My example will output a slug like this: book-house-author-greenberg which is more best practice for slugs than your version. Anyway...if you still prefer the way you described above, simply change the return value.
The doc for the feature used in my example is here.

Laravel 4.1 remove pivot attributes from response

I am using laravel 4.1 to build an api. I have pivot a table which is working fine. But the response comes with pivot attributes which i don't want. as you will see in my example i have to two tables name: trips and users. I don't want to see pivot table attributes in my response. Here is the example:
[
{
"id": 140,
"name_first": "hasan",
"name_last": "hasibul",
"profile_image": "/assets/images/default-profile-img.png",
"created_at": "2013-09-18 08:19:50",
"last_login": "2013-12-26 11:28:44",
"status": "active",
"last_update": "2013-10-15 13:40:47",
"google_refresh_token": null,
"is_admin": 1,
"updated_at": null,
"pivot": {
"trip_id": 200,
"user_id": 140
}
}
This is my User Model:
public function trips(){
return $this->belongsToMany('Trip');
}
This is my trip model:
public function users(){
return $this->belongsToMany('User');
}
This is my controller:
public function index($tripId)
{
$userCollection = Trip::find($tripId)->users;
return $userCollection;
}
This is my route:
//get all the users belongs to the trip
Route::get('trips/{tripId}/users', array(
'as' => 'trips/users/index',
'uses' => 'TripUserController#index'
));
is there any way i can remove pivot attributes using laravel or i have to use php ?
Use the $hidden property of the model, you can add attributes or relations to it and the pivot is basicly acts as a relation.
class Foo extends Eloquent
{
protected $hidden = array('pivot');
public function bars()
{
return $this->belongsToMany('Bar');
}
}
If you want to remove just any one column from the response, then you can try something like this:
In you Model:
public function toArray()
{
$attributes = $this->attributesToArray();
$attributes = array_merge($attributes, $this->relationsToArray());
unset($attributes['pivot']['user_id']);
return $attributes;
}
This way you will get only attribute required.
You can add it to your "hidden" array. At Model page
protected $hidden = [
'pivot'
];
As mentioned above you can remove the pivot attribute from the response, by adding the following to the related model.
protected $hidden = [
'pivot'
];
Moreover, in case you want to select specific fields from the pivot to be displayed in the related user object you can add this to your controller using Laravel 5.8. This works also when you hide the pivot information with the above code snippet.
public function index(Trip $trip)
{
return $trip->users()->select(['trip_id'])->paginate();
}
and you will receive something objects where the trip_id is added to the user object.
{
"data": [
{
"id": 140,
"trip_id": 200,
"name_first": "hasan",
"name_last": "hasibul",
"profile_image": "/assets/images/default-profile-img.png",
"created_at": "2013-09-18 08:19:50",
"last_login": "2013-12-26 11:28:44",
"status": "active",
"last_update": "2013-10-15 13:40:47",
"google_refresh_token": null,
"is_admin": 1,
"updated_at": null,
"pivot": {
"trip_id": 200,
"user_id": 140
}
}
]
}

Resources