Remove key data in dingo - fractal - transformer-model

I already looked into several example on how to remove the key "data" in response, but i cannot fix it.
I tried to use the callback provided by dingo
return $this->collection($users, new UserTransformer, function ($resource, $fractal) {
$fractal->setSerializer(new ArraySerializer);
});
In change the "$fractal->setSerializer(new CustomSerializer);" to "$fractal->setSerializer(new ArraySerializer);" since I dont have CustomSerializer(And how to make this custom serializer?) based on the fractal documentation array serializer but the out put has the key "data".
I also tested the fractal library in different project and implementing the ArraySerializer as the Serializer, and it works.
What am I missing in the setup of dingo-fractal?
UPDATE*
I included the setup in the config
$this->app->bind('Dingo\Api\Transformer\Adapter\Fractal', function($app) {
$fractal = $app->make('\League\Fractal\Manager');
$serializer = new \League\Fractal\Serializer\ArraySerializer();
$fractal->setSerializer($serializer);
return new \Dingo\Api\Transformer\Adapter\Fractal($fractal);
});
And in my controller
$obj = \App\EloquentModel\User::find(1);
return $this->response->item($obj, new UserTransformer);
And in my UserTransformer
public function transform(User $trans)
{
return [
'id' => (int) $trans->id,
'name' => $trans->name,
'description' => $trans->description
];
}
Applying those things removed the key "data" for single item.
{
"id": 1,
"name": "Juan",
"description": "The BOss"
}
But when I try to make it an Array. User::all(), the response has the "data" key.
Thanks.

I was missing the CustomSerializer, a class that is extend by ArraySerializer. Thanks to this link enter link description here

Related

on multiple auth in laravel laravel 8

I have this code in the user model class
using this code showing error
Showing like this
model class code
protected function type(): Attribute
{
return new Attribute(
get: fn ($value) => ["user", "admin", "manager"][$value],
);
}
As #Marwelln mentioned you would need PHP8 and you are are using php7.4. (See picture from the link you posted)
You can do Attribute:get(fn($value) =>....) instead

Laravel eloquent api resource remove `data` key (no collection)

I have custom eloquent api resource for user. For example when I use this resource
Code
$user = $request->user();
return new UserResource($user);
Then on response I get:
{
"data": {
"name": "Margarete Daniel",
"email": "goldner.berniece#example.net",
"verified": "2020-03-20T07:15:56.000000Z"
}
}
How I can change api resource and get example response:
{
"name": "Margarete Daniel",
"email": "goldner.berniece#example.net",
"verified": "2020-03-20T07:15:56.000000Z"
}
Add this to your resource
public static $wrap = null;
You can disable data wrapping by calling the withoutWrapping static method of your resource in the AppServiceProvider. In your case it will be:
public function boot()
{
UserResource::withoutWrapping();
}
You can refer to Laravel documentation about data wrapping for more explanation.
Answering as I keep stumbling on the same problem myself.
The easiest way to return a Laravel resource without the data wrap is to simply return it in a JSON response. So instead of doing:
return new UserResource($user);
You would do:
return response()->json(new UserResource($user));
This way you also don't have to worry about stuffing your AppServiceProvider with a lot of calls to the withoutWrapping method.
To remove the data wrapper for all resources inside your project just add:
use Illuminate\Http\Resources\Json\JsonResource
public function boot()
{
JsonResource::withoutWrapping();
}
Inside the boot method of your AppServiceProvider.php.
this worked for me
return UserResource::make($user)->toArray($request);
and for collection
return UserResource::collection($users)->collection;
For some reason this works:
$user = User::find(1);
return UserResource::make($user)->resolve();
Without ->resolve() it's not working.

How to load relations with { json:api } Client?

I am using the {json:api} Client to parse json into Eloquent like models.
I have two models, Congress and Speaker. A Congress has many Speaker.
This is what I was able to do:
$repository = app(App\Repositories\CongressRepository::class);
$document = $repository->all();
$document is a CollectionDocument with the following attributes:
I would like to get the speakers of the first Congress. This is what I tried
$congresses = $document->getData();
$congress = $congresses->first();
$congress->speakers // <- this is null!
Why is $congress->speakers null? I also tried to us $repository->all(['includes' => 'speakers']);
but this makes no differences.
It seems that $congress->speakers was null because the relation was null:
I use this package to create the json output. Inside the Schema.php I had to add self::DATA to make the data visible, as explained in the docs.
public function getRelationships($resource, $isPrimary, array $includeRelationships)
{
return [
'speakers' => [
self::SHOW_SELF => true,
self::SHOW_RELATED => true,
self::DATA => function () use ($resource) {
return $resource->speakers;
},
],
];
}
I still wonder if its possible to load the relation, if only the link is given in the API.

Delete Method in Axios, Laravel and VueJS

I am trying to send a delete request via axios to laravel as follow:
axios.delete('api/users/' + this.checkedNames)
.then((response) => {
console.log(response)
}, (error) => {
// error callback
})
Now from axios documentation I read that for delete request we should be using a configObject so the above could be rewritten as so:
axios.delete('api/users/', {params: {ids:
this.checkedNames})
.then((response) => {
console.log(response)
}, (error) => {
// error callback
})
I have then Route::resource('users', 'UsersController'); in api.php so the default route for deleting is:
DELETE| api/users/{user}| users.destroy
and the controller's method is:
|App\Http\Controllers\UsersController#destroy
I am able to delete as expected a user when I pass a single id let's say api/users/12, it gets deleted correctly but when I try to pass the array above things get complicated.
if I try as per axios documentation axios.delete('api/users/', {params: {id: this.checkedNames}}) it looks I am sending this http://lorillacrud.dev/api/users?id[]=21&id[]=20 but I get a 405 method not allowed.
if I try axios.delete('api/users/' + this.checkedNames ) I get http://lorillacrud.dev/api/users/20,21 so in my destroy method I could grab the ids and delete, but I am wondering if this is the correct way to do it?
update
I seemed I made it work but I am not understanding so any help still appreciated to make a sense of what I am actually making work!
So, if change to:
axios.delete('api/users/destroy', {params: {'id': this.checkedNames})
and in my destroy method:
if ($request->id) {
foreach ($request->id as $id) {
User::destroy($id);
}
}
User::destroy($id);
}
So...
// not deletes the user
axios.delete('api/users/destroy', {params: {id: id}})
// ok deletes the users when using request->id in a for loop in the destroy laravel method.
axios.delete('api/users/destroy', {params: {ids: this.checkedNames}})
// ok deletes one user
axios.delete('api/users/' + id)
sorry guys but I have a lot of confusion why and what !!!
The route name is user.destroy why does it work when I pass an array and it does not when I pass a single value, why viceversa the route with method delete will not delete when pass an array ???
Any difference between using api/users/destroy vs api/users only?
Thanks for any help on this!
I also experienced the same problem. This works for me:
deletePost: function(id) {
axios.post('/posts/'+id,{_method: 'delete'})
}
Using axios.post() instead of axios.delete, and sending _method "delete"
It is because of the method signatures. The default delete route when using Resource expects a single parameter. So when doing:
axios.delete('api/users', {params: {'id': this.checkedNames})
you are missing a required parameter. The route definition is
Route::delete('api/users/{id}', 'UserController#destroy');
// You are missing `id` here. So it won't work.
Usually, if you are going to stray away from the default behavior, it is recommended to create your own function. So you could leave the default destroy($id) function as is to delete a single entry and write a new function that will delete many. Start by adding a route for it
Route::delete('api/users', 'UserController#deleteMany');
Then define the function to handle it
public function deleteMany(Request $request)
{
try
{
User::whereIn('id', $request->id)->delete(); // $request->id MUST be an array
return response()->json('users deleted');
}
catch (Exception $e) {
return response()->json($e->getMessage(), 500);
}
}
To summarise, your problem came from route definition. Your route from Axios did not match the route definition from Laravel, hence the 405.
I was having issue to send data as model while making delete request. I found a fix as follows:
deleteCall (itemId, jsonModel) {
return api.delete(`/users/${itemId}/accounts/`, {data: jsonModel})
},
Deleting users in array
Other good option, is to convert javascript array to string, and pass it has the required parameter, instead of passing object. Here the example:
In Vue.js 2.5.17+
//Use the javascript method JSON.stringify to convert the array into string:
axios.delete('api/users/' + JSON.stringify(this.checkedNames))
In Laravel 5.3+
//Resource default route (you don't need to create, it already exists)
Route::delete('api/users/{id}', 'UserController#destroy');
//In laravel delete method, convert the parameter to original array format
public function destroy($id)
{
User::destroy(json_decode($id); //converting and deleting users in array 'id'
}
Deleting single user by id
Just pass the id. You don't need to convert it.
In Vue.js 2.5.17+
axios.delete('api/users/' + id)
In Laravel 5.3+
You can name the parameter as you wish: user, id, item ,...
In Laravel 5.6+ < is named as $id //this can be the id or the user object
In Laravel 5.7+ > is named as $user //this can be the id or the user object
public function destroy($id)
{
User::destroy($id);
}
axios.post('/myentity/839', {
_method: 'DELETE'
})
.then( response => {
//handle success
})
.catch( error => {
//handle failure
})
https://www.mikehealy.com.au/deleting-with-axios-and-laravel/

Storing a new post tag if it doesn't exist in the table?

I have a single input field (using select2 plugin) in a blog post form which allow user to insert post tags from existing tags in the table or create new ones and store them in the Tag table and also attach them to the post when they hit submit post button. I've managed to get this work by filtering the input with array_filter(), if the input is !is_numeric the input will first get stored in Tag table and then attach the id to the post.
The problem with this is that it's not working when the new tag from the input is in full numeric type, like 2017 tag. Is there a solution to get this working so the new tag is not limited to string only but also numeric type ? and if possible, I don't want to use any package for this.
The post store method :
public function store(PostsReq $request) {
$input = $request->all();
$post = Post::create($input);
//Handle the tags
$getTags = $request->input('tagspivot');
$oldTags = array_filter($getTags, 'is_numeric');
$newTags = array_filter($getTags, function($item) {
return !is_numeric($item);
});
foreach ($newTags as $newTag) {
if ($tag = Tag::create(['title' => strtolower(trim($newTag))])) {
$oldTags[] = $tag->id;
}
}
$post->tags()->attach($oldTags);
// Upload Image
if ($request->hasFile('image')) {
$input['image'] = $this->uploadImage($request, $post);
}
return redirect()->route('postindex')->with($this->postStoreSuccess);
}
Here is three lines of code would be more than enough:
$tag = Tag::firstOrCreate([
'title' => $request->input('tagspivot'),
]);
You don't need to check for !is_numeric. However, in your form don't use tag id as value. use the title.

Resources