How to attach image path on getting data from database using laravel - php

I am getting data from database and i have a field profile_pic and i am saving image name in my database my response looks like:
"basicInfo": {
"id": 205,
"first_name": "new name",
"middle_name": "middle",
"profile_pic": "3q4Vs8iHdY.png",
}
As you can see profile_pic i am getting image name and there folder public/profile_images where my images is storing and when i hit get Api I GOT following response with image name in profile_pic.
but i want to get full path in my response by attaching path from public/profile_images:
My code where I got this response
$userBasicInfo = $this->userBasicInfo->where('user_id', $user_id)->first();
This gets all data but i want to attach image path name in my profile_pic as well
How I can do that?
I am stuck here
class UserBasicInfo extends Model
{
use SoftDeletes;
const DELETED_AT = 'deletedAt';
protected $table = "user_basic_info";
protected $fillable = [
'first_name','city','state','zip','social_security','middle_name', 'last_name', 'profile_pic', 'date_of_birth', 'gender', 'area_id', 'user_id', 'created_by', 'updated_by', 'created_at', 'deletedAt','title','cell_no','address','work_phone','fax','extension','primary_facility','affiliated_facility','employed_by','emergency_phone','designation','department','employment_type','biography','hiring_date','from','to'
];
protected $hidden = ['deletedAt'];
function user() {
return $this->belongsTo('App\User', 'id', 'user_id');
}
public function getFromAttribute($value){
$createdAt= Carbon::parse($value);
return $createdAt->toIso8601String();
}
public function getToAttribute($value){
$createdAt= Carbon::parse($value);
return $createdAt->toIso8601String();
}
}
if (!empty($userBasicInfo->profile_pic)){
$deleteImage =$userBasicInfo->profile_pic;
unlink(public_path('profile_images').'/'.$deleteImage);
}

You can use accessor in your UserBasicInfo model :
public function getProfilePicAttribute($value)
{
return 'path/to/image' . $value;
}
Guide to Accessors from laravel documentation:
https://laravel.com/docs/5.8/eloquent-mutators#defining-an-accessor

Related

Laravel access to column object

I have a table, table name is bookings and here have a column e_provider. this column i direct fetch data by id and save all data in e_provider field
how can i access this e_provider data like $data->e_provider->name
here is code
[
{
"id": 2,
"e_provider": "{"id":11,"name":"Architect O'Reilly, Ratke and Miller","phone_number":"661.425.3559","mobile_number":"307.607.7472"}",
}
]
in laravel 8 and less try this
Defining A Accessors & Mutators
public function getEProviderAttribute(){
return json_decode($this->getAttributeValue('e_provider'));
}
public function setEProviderAttribute($value){
return json_encode($value);
}
For update value
$e_provider = $object->e_provider;
$e_provider->name = "new name";
$object->e_provider = $e_provider;
$object->save();
https://laravel.com/docs/8.x/eloquent-mutators#accessors-and-mutators
You can use $casts in your model
class BookingModel extends Model
{
protected $casts = [
'e_provider' => AsCollection::class,
];
}
Now you will be able to get the data by the following:
$bookingModel->e_provider->id
https://laravel.com/docs/9.x/eloquent-mutators#array-object-and-collection-casting
Another way if you don't want to use casts, you can define an accessor:
protected function eProvider(): Attribute
{
return Attribute::make(
get: fn ($value) => json_decode($value),
set: fn ($value) => json_encode($value),
);
}
https://laravel.com/docs/9.x/eloquent-mutators#defining-an-accessor

Laravel PUT relationship

Fiddling with Laravel and coming from Symfony, I'm trying to replicate some code.
I'm trying to PUT a Suggestion model (overwritting anything, even relationships) and wanted to know the proper way to overwrite the model.
Since tags attribute in fillable doesn't exist, I certainly get an error (Undefined column: 7 ERROR: column "tags" of relation "suggestions" does not exist).
Suggestions and tags both have their own tables and a pivot table that contains two foreign keys to both tables id.
Request & Response :
{
"id":2,
"content":"Magni.",
"tags":[{"id":13,"name":"MediumAquaMarine"}]
}
{
"id":2,
"content":"Magni.",
"tags":[{"id":10,"name":"Navy"},{"id":13,"name":"MediumAquaMarine"}]
}
public function update(Request $request, Suggestion $suggestion)
{
$validator = Validator::make($request->all(), [
'content' => 'required',
'tags.id' => 'numeric',
]);
if ($validator->fails()) {
return response()->json($validator->messages(), Response::HTTP_BAD_REQUEST);
}
$suggestion->fill($request->only($suggestion->getFillable()))->save();
return new SuggestionResource($suggestion);
}
class Suggestion extends Model
{
use HasFactory;
protected $fillable = ['content', 'tags'];
protected $with = ['tags'];
public function tags()
{
return $this->belongsToMany(Tag::class, 'suggestions_tags')->withTimestamps();
}
}
class Tag extends Model
{
use HasFactory;
protected $hidden = ['pivot'];
public function suggestions()
{
return $this->belongsToMany(Suggestion::class, 'suggestions_tags')->withTimestamps();
}
}
You could just pass an array of IDs for tags instead of the whole object.
Do:
"tags":[10, 13]
Instead of:
"tags":[{"id":10,"name":"Navy"},{"id":13,"name":"MediumAquaMarine"}]
Change the validation rules accordingly and then you can remove tags from $fillable and do something like:
$suggestion->update($request->validated());
$suggestion->tags()->sync($request->tags);

Laravel: Using belongsTo() add unexpected attributes to my Model

I'm writing a REST API using Lumen. I have for my example 2 models User and Post. Post model use the method belongsTo to get the User model which created this post. My goal was to define an accessor so I can get the author's username of the post just like that Post::find($id)->author. So according to the doc I do this:
Post.php :
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $table = 'posts';
protected $appends = ['author'];
protected $fillable = [
'title',
'description'
];
protected $hidden = [
'user_id',
'created_at',
'updated_at'
];
public function user()
{
return $this->belongsTo('App\User', 'user_id');
}
public function getAuthorAttribute()
{
return $this->user->username;
}
}
Now the getter works well and I can easily get the author of the given Post.
But if I tried to return the Post in a JSON response, it's also return me weird attributes like user that seems to come from my user() method that call a belongsTo():
return response()->json(Post::find(2), 200);
{
"id": 2,
"title": "Amazing Post",
"description": "Nice post",
"author": "FooBar",
"user": {
"id": 4,
"username": "FooBar"
}
}
If I use the attributesToArray() it's work as expected:
return response()->json(Post::find(2)->attributesToArray(), 200);
{
"id": 2,
"title": "Amazing Post",
"description": "Nice post",
"author": "FooBar"
}
Moreover if I remove the getter getAuthorAttribute() and the $appends declaration, I don't get the unexpected user attribute.
But I don't want to use this method each time and it doesn't make it work if I want to return all my Post using:
return response()->json(Post::all(), 200);
Have someone an idea why I get this additional attribute using belongsTo?
This behavior is because of performance.
When you call $post->user for first time, The Laravel read it from the database and keep it in $post->relation[] for next usage. So next time Laravel can read it from the array and prevent from executing a query again(it will be useful if you use it in multiple places).
Plus, the user is also an attribute and the Laravel merges
$attributes and $relations array together when you call $model->toJson() or $model->toArray()
The Laravel's Model source code:
public function toArray()
{
return array_merge($this->attributesToArray(), $this->relationsToArray());
}
public function jsonSerialize()
{
return $this->toArray();
}
Your first approach was good, you just need to add 'user' into the $hidden array
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $table = 'posts';
protected $appends = ['author'];
protected $fillable = [
'title',
'description'
];
protected $hidden = [
'user_id',
'created_at',
'updated_at',
'user', // <-- add 'user' here
];
public function user()
{
return $this->belongsTo('App\User', 'user_id');
}
public function getAuthorAttribute()
{
return $this->user->username;
}
}
And your resulting model would be:
{
"id": 2,
"title": "Amazing Post",
"description": "Nice post",
"author": "FooBar"
}

Laravel belongs returns none

I have a user model, which can have many reports, and a report model obviously belonging to a user, whenever one is created.
However when I use return $this->belongsTo('App\User') on the report model No user is returned even when I have the correct user_id on the report, and correct id on the user table.
User
protected $fillable = [
'name', 'email', 'password',
];
public function reports()
{
return $this->hasMany('App\Report');
}
Report
protected $fillable = [
'user_id', 'title', 'detail',
];
public function user()
{
return $this->belongsTo('App\User', 'user_id');
}
I've solved it simply by using $report->user, instead of calling it like a function via $report->user()

Laravel 5.2 change database column name reference

Hello i'm trying to change how to access to a database column name without change the name, for example, my column name is resourceType but I want to call it name and also I want the response json appears name instead resourceType. Looking around internet found I should use protected $maps = ['oldName' => 'newName']; but doesn't work. I want to change resourceType because I think doesn't look good the table name should be equal than a column resourceType->resourceType
This is my model
<?php
namespace Knotion;
use Illuminate\Database\Eloquent\Model;
use Mappable, Mutable;
class CTL_ResourceType extends Model {
public $timestamps = false;
protected $table = "CTL_ResourceType";
protected $primaryKey = "idResourceType";
public $incrementing = false;
public static $snakeAttributes = false;
protected $hidden = ['idCountry', 'idCompany', 'initials', 'thumbnail', 'icon', 'status', 'createTime', 'updateTime'];
protected $fillable = ['name'];
protected $maps = ['resourceType' => 'name'];
protected $appends = ['name'];
public function resource() {
return $this->hasMany('Knotion\CTL_Resource', 'idResource' );
}
public function country() {
return $this->belongsTo('Knotion\CTL_Country', 'idCountry', 'idCountry');
}
public function company() {
return $this->belongsTo('Knotion\CTL_Company', 'idCompany', 'idCompany');
}
}
and this is the response JSON I'm receiving. As you see resourceType stills there instead name
{
"total": 16,
"per_page": 15,
"current_page": 1,
"last_page": 2,
"next_page_url": "http://localhost:8000/krb/api/resources?page=2",
"prev_page_url": null,
"from": 1,
"to": 15,
"data": [
{
"idResource": "4e8f1ece-f666-11e5-8137-0f7932903a75",
"productionKey": "238493ujjsl",
"title": "ElTitle16",
"description": "ElDescription16",
"minimumAge": "4",
"maximumAge": "15",
"fileName": "ElFileName16",
"extension": ".png",
"URL": "ElURL16",
"createTime": "2016-03-30 04:58:16",
"creatorUser": {
"idUser": "85cf125c-f5ff-11e5-8137-0f7932903a75",
"name": "Roberto"
},
"creationCountry": {
"idCountry": "f03a75a0-f5ff-11e5-8137-0f7932903a75",
"country": "Estados Unidos"
},
"resourceType": {
"idResourceType": "5c902028-f601-11e5-8137-0f7932903a75",
"resourceType": "TípodeRecurso3"
},
"tags": [
{
"idTag": "40c6a114-f520-11e5-8137-0f7932903a75",
"name": "ElTag1"
}
],
"quickTags": [
{
"idQuickTag": "679bc8f0-f520-11e5-8137-0f7932903a75",
"name": "ElQuickTag4"
}
],
"relatedTo": [
{
"idRelatedTo": "7beddc6c-f520-11e5-8137-0f7932903a75",
"name": "ElRelatedTo3"
}
]
}
I hadn't heard of the $maps property or Mappable before, so I did a quick search. It looks like they (as well as Mutable) are part of the jarektkaczyk/eloquence package.
In this case, both Mappable and Mutable are traits that are supposed to be added to the class. Additionally, in order for them to work properly, you need to add in the Eloquence trait, as well.
Your use statements at the top of your file need to be changed to properly address the class names in the correct namespace, and then you need to add the traits to your class:
<?php
namespace Knotion;
// import the class names
use Sofa\Eloquence\Mutable;
use Sofa\Eloquence\Mappable;
use Sofa\Eloquence\Eloquence;
use Illuminate\Database\Eloquent\Model;
class CTL_ResourceType extends Model {
// add the traits to the class
use Eloquence, Mappable, Mutable;
// code...
}
Edit
If you wanted to do this without the package, you need to do three things:
You need to add resourceType to your $hidden array, so that it won't show up in your toArray()/toJson() results.
protected $hidden = ['idCountry', 'idCompany', 'initials', 'thumbnail', 'icon', 'status', 'createTime', 'updateTime', 'resourceType'];
You need to create a getNameAttribute() accessor method, which will be called whenever you attempt to access the name attribute.
public function getNameAttribute() {
return $this->resourceType;
}
You need to add name to your $appends array, so that it will be included in your toArray()/toJson() results.
protected $appends = ['name'];
Optionally, if that feels like too much work, you could always just override the toArray() method (called by toJson()) to force your naming convention, as well:
public function toArray() {
// call parent method to get initial array results
$array = parent::toArray();
// set the new key with data
$array['name'] = $array['resourceType'];
// unset the old key
unset($array['resourceType']);
// return the array
return $array;
}

Categories