I can't get the data in appends with json in Laravel - json

I have two models in laravel project Item and ItemImgs
Item.php
class Item extends Model
{
protected $appends = [
'photo',
];
public function imgs()
{
return $this->hasMany(ItemImage::class);
}
public function getPhotoAttribute()
{
$img = $this->imgs->first();
return $img.src;
}
}
it's worked in views
dd(Item::all()); //worked
{{ $cane->photo}}; //worked
but when I try to get json
return response()->json([
'items' => Item::with('imgs')->get(),
]);
// not worked. Got timeout 500

You cannot use dot notation in PHP.
public function getPhotoAttribute()
{
$img = $this->imgs->first();
return $img.src; // Dot notation is not allowed
}
but you've to use:
public function getPhotoAttribute()
{
$img = $this->imgs->first();
return $img->src;
}

if what you're trying to do is to get the items that have imgs() then what you should do is query by relationship existence, as mentioned in the docs
https://laravel.com/docs/5.8/eloquent-relationships#querying-relationship-existence
'items' => Item::has('imgs')->get()

It is not possible to refer to the linked model tables in attributes. It works in views but gives out a memory error when outputting an array through json.
public function getPhotoAttribute(){
$img = ItemImage::where('item', $this->id)-
>first();
}
It works that way, but it's not elegant.

Related

How can I format the array on a specific format in my laravel controller function?

I'm currently creating a laravel vue spa, and just wondering on how can I get designation names with these designation id's with the same structure. This is the json of designation id's:
[
[
1,
5
],
[
1,
3
]
]
This is my getDesignations function in EmployeesController.php:
public function getDesignations($id) {
$employee_designation_ids = Employees::find($id)->pluck('designation_id')->toArray();
$designation_name = [];
foreach ($employee_designation_ids as $employee_designation_id) {
$designation = Designations::where('id', '=', $employee_designation_id);
//$designation_name[] = $designation;
}
return $employee_designation_ids;
}
If you want specifically that format, you can do it like this (with a lot of guesses in my part since you did not share your Tables structures)
public function getDesignations($id) {
$employee_designation_ids = Employees::find($id)->designation_id;
return [[$id, $employee_designation_ids]];
}
But why are you returning a double table for a single row result.
Thanks for all your help! I've managed to fix it with this method in my controller:
public function getDesignations(Request $request, $id) {
$employee_designation_ids = Employees::where('id', $id)->pluck('designation_id');
return Designations::whereIn('id', $employee_designation_ids[0])->pluck('name');
}

How to retrieve data from MySQL to JSON?

I have a Symfony project where I want to store the all the rows from my MySQL table to JSON. Currently there are five rows in my table, but in my browser it only returns five empty values as {"results":[{},{},{},{},{}]}
I guess I have done something right, but not everything. What am I missing in my code?
#[Route('/budget/api', name: 'budget-api')]
public function index(Request $request, BudgetRepository $repository)
{
$results = $repository->findAll();
return $this->json(['results' => $results]);
}
Try createQueryBuilder its usefull.
#[Route('/budget/api', name: 'budget-api')]
public function index(Request $request, BudgetRepository $repository)
{
$qb = $repository->createQueryBuilder("b");
$results = $qb->getQuery()->getArrayResult();
return $this->json(['results' => $results]);
}
You can use the serializer or re-create the array yourself like that
$courses = $doctrine->getRepository(Course::class)->findByLikeTitle($search, $userId);
foreach ($courses as $key => $course) {
$jsonCourses[$key]['title'] = $course->getTitle();
}
```
You can achieve this by Using a Serializer to convert the array of objects into JSON. There are other ways to achieve this like using jsonResponse for example. But the serializer is the most robust way imo.
Example only:
use Symfony\Component\Serializer\SerializerInterface;
#[Route('/budget/api', name: 'budget-api')]
public function index(Request $request, BudgetRepository $repository, SerializerInterface $serializer)
{
$results = $repository->findAll();
$jsonResults = $serializer->serialize($results, 'json');
//If you need to handle any circular references, you can use this..
$jsonResults = $serializer->serialize($results, 'json', array(
'circular_reference_handler' => function ($object) { return $object; },
));
return $jsonResults;
}

Return URL image in Laravel API

I need to return URL path and name image from database.
This my call method to get data from database:
public function index(){
$rav=Rav::select('id','image','nameravs')->get('image');
return $this->sendResponse($rav->toArray(),'rav show is succesfuly');
}
Output data it look like this:
{
"id": 88,
"image": "1579781806.png",
"nameravs": "asdad"
},
But I want to return image with path URL like this:
"image": http://127.0.0.1:8000/images_ravs/1579781806.png
You can use Eloquent Accessor
add the image url attribute in Rav.php Model like below. then you can access it any place.
public function getImageUrlAttribute($value)
{
return env('APP_URL'). '/images_ravs/' . $this->image;
}
And don't forget to Add Appends property inside the Model
/**
* The accessors to append to the model's array form.
*
* #var array
*/
protected $appends = ['image_url'];
then you can access it like below.
$rav->image_url
Define An Accessor in your model like this example :
public function getImageAttribute($value)
{
return env('APP_URL') . Storage::url($value);
}
Try this:
public function index(){
$rav = Rav::select('id','image','nameravs')->get('image');
return $this->sendResponse(
[
'id' => $rav->id,
'image' => URL::to('/').'/images_ravs/'.rav->image,
'nameravs' => $rev->nameravs
],'rav show is succesfuly');
}
You can use selectRaw or select with DB::raw and just concat that path as a prepended string infront of your image column in your query:
Rav::select(DB::raw("id, nameravs, CONCAT('/images_ravs/', image) as image"))->get()->toArray();
No need to include the URL (unless for some reason you have some type of CDN in front of it) in which case you can just escape the string and add it if necessary.
I would do something like this: Try to use as many od Laravel's built-in functions as possible. In most cases you don't need to reinvent the wheel.
public function index(){
$ravs = Rav::select('id','image','nameravs')->get();
$results = [];
foreach($ravs as $rav){
$rav->image = env('APP_URL') . '/images_ravs/' . $rav->image;
array_push($results, $rav);
}
return response()->json($results);
}
In the Model you can create getAttribute:
public function getImageAttribute()
{
return $this->attributes['image'] ? URL::to('/uploads/' . $this->attributes['image']) : null;
}
Or you can create custom casts file:
protected $casts = [
'image' => ImageCast::class,
'created_at' => 'datetime',
'updated_at' => 'datetime',
];

How come ArrayDataProvider is best used for big array but is less efficient yii2

I have a class which extends from yii\rest\Controller, under this class is a function which returns an instance of ArrayDataProvider in JSON format.
public function actionIndex()
{
$user = User::find();
return $this->query($user->asArray()->all(), true);
}
protected function query($qry, $paginate=false)
{
$this->serializer['preserveKeys'] = false;
$dataProvider = new ArrayDataProvider([
'allModels' => $qry,
]);
if ($paginate) {
$dataProvider->setPagination(['pageSize' => 20]);
} else {
$dataProvider->setPagination(false);
}
return $dataProvider;
}
Assuming that the array returned is composed of 130k items (from actionIndex). Do everytime I hit this API with a page parameter on it, the ArrayDataProvider will process the 130k records and sliced it all over again?
Can someone tell what's the exact behavior an ArrayDataProvider is running? Is there any efficient way of handling such big array? What's the perks of using this as opposed with other providers?
Thank you!

Laravel return one model + association as JSON

I'm looking for a way to return a model as JSON including an association model after save (within a controller).
I know how to respond as JSON with associations by doing the following :
$objects = MyModel::with(['assocation1', 'association2.dependencies'])->get();
return response()->json($objects, 200);
But in a case of an object already found ? I've tried to use the same concept as above but it returns every rows.
$object = MyModel::first();
$object->with(['assocation1', 'association2.dependencies'])->get();
Laravel's documentation unfortunately does says much about it. What I'm trying to do is to return a JSON object including an association after save, within a controller :
class ExampleController extends Controller {
public function store()
{
$object = new MyModel($request->input('object'));
$response = DB::transaction(function () use ($object) {
if (object()->save()) {
// Here I want to return the object with association1 as JSON
return response()->json($object->with('association1')->get(), 201);
}
});
return $response;
}
}
Edit
More clarification about this case. Using either with or load seems to produce the same result: returning all rows from the Object object including associations. My goal here is to only return ONE object with it's association as JSON, not all of them.
I believe you aren't as far off as you think. In your second example, you shouldn't call get(). Try this instead:
if ( $object = $object->save() )
{
$object->load(['assocation1', 'association2.dependencies']);
return response()->json($object, 201);
}