I have difficult to build and return a nested json. I want obtain the information from two differents table joined with an id.
This is my situation:
With this method on my controller:
public function eventOccList(EventOccurrence $eventOccurrence){
return new EventOccurrenceResourceCollection(EventOccurrence::all());
}
and with the mapping in the class EventOccurrenceResource
return [
'type' => 'event',
'id' => (string) $this->id,
'name' => $this->name,
'description' => $this->description,
'location_id' => $this->location_id
];
I obtain this JSON:
{"data":[{"type":"event","id":"1","name":"event_1","description":"event blabla","location_id":11}
If I want to obtain all the informations about the table "location" with the id "location_id" and show in the same json, what is the best way to retrieved this data?
Thanks !
I assume your Event Model have a location relationship :
public function location{
return $this->belongsTo(Event::class);
}
you can do this once you have your event in a Controller :
$event->load('location');
return $event->toJson();
You can then hide or append any attribute you want :)
Related
I want to populate a table with listings of car offers with dummy data.
The specific is that I want the make and model to be from a table already created in the database. Also the listing's title to be Make and Model. My code is this, but I assume it is totally wrong:
public function definition()
{
$id = DB::table('cars')->select('id')->inRandomOrder()->first();
$make = DB::table('cars')->where('id', $id)->select('make')->first();
$model = DB::table('cars')->where('id', $id)->select('model')->first();
return [
'title' => $make . " " . $model,
'make' => $make,
'model' => $model,
'year' => $this->faker->numberBetween(1950, 2021),
'slug' => $this->faker->word(),
];
}
The query builder in Laravel returns an object representing the database model when you fetch with first()
You should access the attributes when you're setting them as other model attributes
return [
'title' => $make->make . " " . $model->model,
'make' => $make->make,
'model' => $model->model,
'year' => $this->faker->numberBetween(1950, 2021),
'slug' => $this->faker->word(),
];
Note
The answer above only fixes the issue in the current code
The correct implementation would be to create models (if don't exist already) and link them with relationships through foreign keys and then attach them together in a seeder
The factory should only contain a clear and clean definition of fake data
I am trying to add an asset link to a nested properties value using Eloquents API resource function:
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'image' => isset($this->image) ? asset('storage/'.$this->image) : null,
'properties' => $this->properties,
'created_at' => (string) $this->created_at,
'updated_at' => (string) $this->updated_at
];
}
The following works fine for the image value, but I am using a nested properties['pdf'] file that I need to add asset('storage/') parameter to so it outputs the full URL.
How am I able to pass isset($this->properties['pdf']) ? asset('storage/'.$this->properties['pdf']) : null into the properties value? I still need the pdf value to return inside the properties value.
Note: There are other values inside properties but they are dynamic based on the data returned.
Probably not the cleanest idea but this worked:
$properties = $this->properties;
if(isset($this->properties['pdf']) && $this->properties['pdf'] != null){
$properties['pdf'] = asset('storage/'.$this->properties['pdf']);
}
Then I applied $properties to the return.
Im have ActiveRecord model and view for update form of this model. Also I have getter and setter in model class that looks like this
public function setTopvisorGoogleRegion($value)
{
$this->myvalue = $value;
return(true);
}
public function getTopvisorGoogleRegion()
{
return([1 => '123']); //I return this array for show you essence of the problem
}
Following logic in this code $model->topvisorgoogleregion must return [1 => '123']
In view I have next code
<?php echo($form->field($model, topvisorgoogleregion)->textInput());?>
<?php echo $form->field($model, 'topvisorgoogleregion')->widget(Select2::classname(), [
'data' => [1 => '123', 2 => '456'],
'options' => [
'id'=>'projectCtrl',
'placeholder' => 'Select option',
'multiple' => true
],
'pluginOptions' => [
'allowClear' => true,
'tags' => true,
],
]);
?>
When I open form I want to see option 1 => '123' already selected in Select2. Its logically because when already existing record is updating, ActiveRecord get data that already stored in model (in this case using getter) and fill fields in view with this data (In first field that using textInput I see text 'Array' because getter in model returns array). But Select2 is empty when I open update page. Whats going wrong?
If I delete first field (textInput) nothing changes
I find the solution - in getter I need provide ActiveQuery object, not array. I dont know why and how it works, but it works
I'm learning Laravel and have created a public endpoint where I want to output only certain information of some comments if a user is not authenticated from a GET request.
I have managed to filter out the comments based on whether or not they are approved. I now want to filter out the data that is returned. I have attached a screenshot of what is currently returned.
Ideally, I only want to return the id, name and the body in the json. How can I go about this? I tried the pluck() method which did not give the desired results. Any pointers would be greatly appreciated
public function index(Request $request)
{
if (Auth::guard('api')->check()) {
return Comment::all();
} else {
$comments = Comment::where('approved', 1)->get();
return $comments->pluck('id','name','body');
}
}
To select the particular columns, you can pass columns name to get as
$comments = Comment::where('approved', 1) -> get(['id','name','body']);
You can use a transformer to map the incoming data to a sensible output based on the auth state. The following example comes from the Fractal lib:
<?php
use Acme\Model\Book;
use League\Fractal;
$books = Book::all();
$resource = new Fractal\Resource\Collection($books, function(Book $book) {
return [
'id' => (int) $book->id,
'title' => $book->title,
'year' => $book->yr,
'author' => [
'name' => $book->author_name,
'email' => $book->author_email,
],
'links' => [
[
'rel' => 'self',
'uri' => '/books/'.$book->id,
]
]
];
});
Ideally, you would create 2 classes that extend from Transformer and pass the correct one to the output.
If you want to pass the result as json respose
$comments = Comment::where('approved', 1)->pluck('id','name','body')->toArray();
return Response::json($comments);
If you want to pass the result as to blade
$comments = Comment::where('approved', 1)->pluck('id','name','body')->toArray();
return view('your_blade_name')->with('comments',$comments);
I am using fractal for my small project, here is my code:
public function transform(Series $series) {
return [
'id' => $series->id,
'title' => $series->title,
'url' => $series->url,
'description' => $series->description,
'thumbnail_hd' => $series->thumbnail_hd,
'thumbnail_wide' => $series->thumbnail_wide,
'views' => $series->views
];
}
I would like to make views (which is an int) optional and not return the views unless requested - since this field is based on a relationship and will increase the processing time.
I would like to use it as relationships (so i can include particular fields whenever I need to):
// in transformer
public function includeUser(Series $series) {
return $this->item($series->user, new UserTransformer);
}
// in controller
return fractal()
->item($series)
->parseIncludes(['user'])
->transformWith(new SeriesTransformer)
->toArray();
But just for an integer instead of a whole array of data. Is it possible using Fractal?
What you can do is the following
public function transform(Series $series) {
$return = [
'id' => $series->id,
'title' => $series->title,
'url' => $series->url,
'description' => $series->description,
'thumbnail_hd' => $series->thumbnail_hd,
'thumbnail_wide' => $series->thumbnail_wide,
];
if ($series->views > 0) {
$return['views'] = (int) $series->views;
}
return $return;
}
I wouldn't suggest doing this though. I would usually just return views as 0.
If you're worried about your DB performance, your app is going to have to count the views anyway to know if they're greater than 0.
If you worried about client side performance, this is not going to matter with a single key value pair.