Transform keys in form request after validation - laravel

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');

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();

Laravel & vue axios get method returns Getters & Setters?

I am new in Vue.js and trying to use axios to fetch data from Laravel API.
The function in backend returns an array of arrays as:
public function getPersonTypes()
{
$data = [];
$personTypes = config('codeechoo.documentation.config.personTypes');
foreach ($personTypes as $id => $type) {
$data[] = [
'id' => $id,
'name' => trans($type)
];
}
return response()->json($data);
}
And the Vue function in methods is:
fetchPersonTypes() {
axios.get(route('api.documentation.person.types'))
.then((response) => {
console.log(response.data);
this.personTypes = response.data;
});
}
But the console show the result as an array of objects like:
id: Getter & Setter
name: Getter & Setter
So how can I get the real values of id, name props ?
You can extract the data by stringifying and then parsing it back:
let personTypes = JSON.parse(JSON.stringify(response.data));
console.log(personTypes);
What you will see in the console now is the whole data without the getters and setters.
I think you should call the route url directly.
NOTE: because in axios the default baseURL is already set, you don't need to type base url, only the path.
Example: instead of axios.get(http://yoursite.com/you/path), just type axios.get('your/path').
fetchPersonTypes() {
axios.get('your/path').then(({data}) => {
console.log(data);
this.personTypes = data;
});
}

Fractal Transformer 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
];
});

Yii2 custom validation rule not working

I'm trying to write some custom validation for a model in yii2, but I can't figure out why the validation always is positive, although my validation function always adds an error.
for example the rules
public function rules()
{
return [
...
[['myattribute'], 'myvalidation'],
];
}
public function myvalidation($attribute, $params)
{
$this->addError($attribute, "error");
}
the validate() function still returns true. What's the problem?
In validation rule add skipOnError => false
[
['myattribute', 'myvalidation', 'skipOnError' => false],
]
Then
$model->validate(); // should return false;
What I will recommend you is watch this lesson on custom roles and
read docs on it. It's not the best video tutorial, but this guy made it work correctly.
In your case :
1.In [['myattribute'], 'myvalidation'], remove extra array from here, make your model rules and custom valdation function look like this
public function rules()
{
return [
...
['myattribute', 'myvalidation'],
];
}
public function myvalidation($attribute, $params)
{
$this->addError($attribute, "error");
}
it's not wrong, but it's used when you have more than one attribute.
2.Then go to your form and put `` to your ActiveForm so it will look like this
<?php $form = ActiveForm::begin(['enableAjaxValidation' => true]); ?>
I mean, your need to do it in case if you want to validate it without reloading (using ajax).
3.Also add this to your controller's action that is connected to your view
if(Yii::$app->request->isAjax && $model->load($_POST)) {
Yii::$app->response->format = 'json';
return \yii\widgets\ActiveForm::validate($model);
}
This will validate your input in the form via ajax, if it's not ajax, this will not work.
['reg_date','validateDate', 'skipOnEmpty' => false, 'skipOnError' => false]
add this to your rules
public function validateDate($attribute,$params,$validator)
{
$validator->addError($this,$attribute,"Bugungi sana bo'lishi kerak!");
}
check this in your controller side like this
if($model->validate()){
echo "validate works";
}

Laravel - Change URL parameters using GET

I have RESTful API built on Laravel.
Now I'm passing parameter like
http://www.compute.com/api/GetAPI/1/1
but I want to pass parameter like
http://www.compute.com/api/GetAPI?id=1&page_no=1
Is there a way to change Laravel routes/functions to support this?
you can use link_to_route() and link_to_action() methods too.
(source)
link_to_route take three parameters (name, title and parameters). you can use it like following:
link_to_route('api.GetAPI', 'get api', [
'page_no' => $page_no,
'id' => $id
]);
If you want to use an action, link_to_action() is very similar but it uses action name instead of route.
link_to_action('ApiController#getApi', 'get api', [
'page_no' => $page_no,
'id' => $id
]);
href text
with these methods anything after the expected number of parameters is exceeded, the remaining arguments will be added as a query string.
Or you can use traditional concatination like following:
create a route in routes.php
Route::get('api/GetAPI', [
'as' => 'get_api', 'uses' => 'ApiController#getApi'
]);
while using it append query string like this. you can use route method to get url for required method in controller. I prefer action method.
$url = action('ApiController#getApi'). '?id=1&page_no=1';
and in your controller access these variables by following methods.
public function getApi(Request $request) {
if($request->has('page_no')){
$page = $request->input('page_no');
}
// ...your stuff
}
Or by Input Class
public function getApi() {
if(Input::get('page_no')){
$page = Input::get('page_no');
}
// ...your stuff
}
Yes you can use those parameters, then in your controllers you can get their values using the Request object.
public function index(Request $request) {
if($request->has('page_no')){
$page = $request->input('page_no');
}
// ...
}

Resources