Fractal Transformer Laravel? - laravel

I tried to transform object like as:
$objects = Object::all();
$objects = (new ObjectTransformer)->transform($objects);
Where ObjectTransformer is:
class ObjectTransformer extends TransformerAbstract {
public function transform(Object $obj)
{
return [
'id' => (int) $obj->id,
'name' => $obj->prefix
];
}
}
I get an error:
Type error: Argument 1 passed to App\Http\Controllers\API\ObjectTransformer::transform() must be an instance of App\Http\Controllers\API\Object, instance of Illuminate\Database\Eloquent\Collection given

The function expects an Object and you are passing a Collection of Objects...
But if what you want is just to transform a collection, you don't need to create a specific class, just use the transform Collection method with an anonymous function that does the job:
$objects = Object::all();
$objects->transform(function($object,$key){
return [
'id'=>(int)$object->id,
'name'=>$object->prefix
];
});

Related

Return Laravel options() as array when no optional parameter has been provided

Laravel has the super handy optional() helper.
I would like to combine it with a custom Model attribute like this:
// this method is on the User model
public function getDataAttribute()
{
// this data comes from another service
$data = [
'one' => 1,
'two' => 2,
];
return optional($data);
}
So I can use it like this:
$user->data->one // 1
$user->data->two // 2
$user->data->three // null
However, I am also trying to return the entire array by doing:
dump($user->data); // this should dump the internal $data array
But this will return an instance of Illuminate\Support\Optional with a value property.
Illuminate\Support\Optional {#1416 ▼
#value: {#2410 ▼
+"one": 1
+"two": 2
}
}
Is it possible to return the original $data array if no "sub"parameter (= a child attribute of $user->data) is given? Or is there a possibility to detect a child parameter in the getDataAttribute()?
I hope it's clear what I am trying to achieve.
What you're asking for cannot be achieved.
My suggestion would be to keep things simple and define a getter method and pass the key of the array you want and from there return your data respectively, e.g.:
public function getData($key = null) {
$data = [
'one' => 1,
'two' => 2,
];
if (!$key) {
return $data;
}
return $data[$key] ?? null;
}
Notice also how this method is no longer an attribute, this is because AFAIR, you cannot pass args to attribute methods.
Reading Material
Null coalescing operator
Thanks to lagbox for pushing me in the right direction. I have solved this by using the following macro:
Illuminate\Support\Optional::macro('toArray', function()
{
return (array) $this->value;
});
This way I can access all data by using:
$user->data->toArray();

Transform keys in form request after validation

I want to transform the keys of my data in a form request (after validation), so I have a method:
public function data()
{
return [
'my_title' => $this->input('title'),
'my_body' => $this->input('body'),
];
}
Which is accessed in a controller via:
$request->data()
I know I can access each part by:
$request->data()['my_title']
But how can I set this up so it can be accessed like:
$request->data('my_title')
or even
$request->data->my_title
if you want this pattern
$request->data()->my_title
then you must data method return an object not an array:
public function data()
{
$array= [
'my_title' => $this->input('title'),
'my_body' => $this->input('body'),
];
$objectFromArray=(object)$array;
return $objectFromArray;
}
Try this
$var = $request->all();
$var['item_in_request'];
//or
$request->item_in_request; //property accessed via magic method
but my recommendation is to always use:
$request->input('item_in_request');
$request->get('item_in_request');

Store multiple objects in json column

I have table with some json column. I want to store multi objects in the json column in Laravel.
My json column look like this "position":[{"lat" : 500, "lon" : 5000, "date":"2020:04:21 16:58:23"}].
this is a function in a service that , i call in my controller
public static function savePositionCamion($id_tournee, $position)
{
$geoTour = GeoTournee::where('geo_tournee.id_tournee', $id_tournee)->first(['position']);
if (!$geoTour) {
$geoTournee = new self();
$geoTournee->id_tournee = $id_tournee;
$geoTournee->position = $position;
return $geoTournee->save() ? $geoTournee : false;
} else {
$arr_pos = json_decode($geoTour->position);
dd($arr_pos);
}
}
in the controller i call the function like this
$geoTourne = GeoTournee::savePositionCamion($request->id_tournee, json_encode($request->position));
anyone can help me to achieve this ! thank's
The array cast type is particularly useful when working with columns that are stored as serialized JSON. You have JSON or TEXT field type that contains serialized JSON, adding the array cast to that attribute will automatically deserialize the attribute to a PHP array when you access it on your Eloquent model:
class GeoTournee extends Model
{
...
protected $casts = [
'position' => 'array',
];
...
}
So you can save this json field like this:
$geoTournee->position = $position;
$geoTournee->save();
Accessing the position attribute and it will automatically be deserialized from JSON into a PHP array. When you set the value of the position attribute, the given array will automatically be serialized back into JSON for storage:
And you don't need to create savePositionCamion function, you can use firstOrCreate instead:
GeoTournee::firstOrCreate(['id_tournee' => $id_tournee], [ 'position' => $position ]);

How to call a class defined in the config

As the title suggests, I need to call a class.
Example config file within Laravel:
return [
'user' => App\User::class
];
The problem I have is that I need to do run the non-static method and not sure how to do that.
i.e. (new User())->getTable()
If you have this in your config file example_config_file.php:
return [
'user' => App\User::class,
];
You can call it like this using the new command to create an instance of the User model:
$userClass = config('example_config_file.user');
$user = new $userClass(); // blank instance of User model
Or like this if you want to use Eloquent methods:
$userClass = config('example_config_file.user');
$user = $userClass::find(1); // User model with id = 1
You can create a helper class and get any type of model like this:
class ModelHelper
{
public static function getModel($type, $id = null)
{
$modelClass = config("example_config_file.$type");
if($id) {
return $modelClass::find($id);
}
return new $modelClass();
}
}
Then in your code, whenever you need a user instance, call the helper class:
$user = ModelHelper::getModel('user'); // get a blank User model
$post = ModelHelper::getModel('post', 1); // get the post with id = 1

Laravel Dingo nested transformers

I'm trying to get one to many relationship objects with transformers. I want to get include metas but i only get just regular transform fields.
my transformer:
class AssistantTransformer extends TransformerAbstract
{
protected $availableIncludes = [
'assistantmetas'
];
public function transform(User $user)
{
return [
'id' => (int) $user->id,
'firstname' => ucfirst($user->first_name),
'lastname' => ucfirst($user->last_name),
];
}
public function includeMetas(User $user)
{
$assistantmetas = $user->userMetas;
return $this->item($assistantmetas, new AssistantsMetaTransformer);
}
}
Just use defaultIncludes not available includes, because it needs to send request via url? include=assistantmetas to get result like this.

Resources