Using Laravel 8, in a JSON POST request I have a field { "is_active": "1"} in string quotes. Have the below validation in Laravel
'is_active' => ['required','integer',Rule::in([0, 1]) ]
It's accepting integer 1 even enclosed in quotes. How to do strict check so that it allows only { "is_active": 1}
Type casting converts the value to a chosen type by writing the type within parentheses before the value to convert. The casts allowed are: (int) - cast to int.
https://laravel.com/docs/8.x/eloquent-mutators#cast-parameters
e.g
We have a property of a model called cast in which you can specify your column names just like below:
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'rating' => 'integer',
];
Related
Is there a way to use the #paginate directive from lighthouse-php without querying data from a model? Let say, i using a third party library to query data using an api or so.
Fortunately, such a feature has been added very recently: https://github.com/nuwave/lighthouse/pull/2232. This PR added support for returning data in a Paginator from option resolver in #paginator directive.
You can provide your own function that resolves the field by directly returning data in a \Illuminate\Contracts\Pagination\Paginator instance.
This is mutually exclusive with builder and model. Not compatible with scopes and builder arguments such as #eq.
type Query {
posts: [Post!]! #paginate(resolver: "App\\GraphQL\\Queries\\Posts")
}
A custom resolver function may look like the following:
namespace App\GraphQL\Queries;
use Illuminate\Pagination\LengthAwarePaginator;
final class Posts
{
/**
* #param null $root Always null, since this field has no parent.
* #param array{} $args The field arguments passed by the client.
* #param \Nuwave\Lighthouse\Support\Contracts\GraphQLContext $context Shared between all fields.
* #param \GraphQL\Type\Definition\ResolveInfo $resolveInfo Metadata for advanced query resolution.
*/
public function __invoke($root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): LengthAwarePaginator
{
//...apply your logic
return new LengthAwarePaginator([
[
'id' => 1,
'title' => 'Flying teacup found in solar orbit',
],
[
'id' => 2,
'title' => 'What actually is the difference between cookies and biscuits?',
],
], 2, 15);
}
}
(The docs are currently not getting updated correctly, which is why you probably did not find out about this. I am working on restoring the deployment.)
Eloquent allows Enum Casting.
Eloquent also allows you to cast your attribute values to PHP enums.
To accomplish this, you may specify the attribute and enum you wish to
cast in your model's $casts property array:
use App\Enums\ServerStatus;
/**
* The attributes that should be cast.
*
* #var array
*/
protected $casts = [
'status' => ServerStatus::class,
];
Once you have defined the cast on your model, the specified attribute
will be automatically cast to and from an enum when you interact with
the attribute:
if ($server->status == ServerStatus::provisioned) {
$server->status = ServerStatus::ready;
$server->save();
}
Is it possible to use enum casting in eloquent for array values?
I have an existing eloquent model that use to have one type. And now it needs to support multiple.
Does Laravel support array enum casting or ist this not possible? What would be an alternative approach to achieve something similar?
you can use spatie/laravel-enum
after installing it:
composer require spatie/laravel-enum
you can use it for array enum casting, something like:
protected $casts = [
'status' => StatusEnum::class.':collection',
];
and if the status is nullable you can:
protected $casts = [
'status' => StatusEnum::class.':collection,nullable',
];
this package also provider validation rule and other features.
and here is an interesting pull request that has been merged, but I did not test it.
I am saving an array in one column of my database using json_encode as follows and it works:
$service->description = $request->service_description;
$service->image = json_encode($url);
$service->duration = $request->service_delivery_time;
When I fetch the data I get a string. I am fetching using $service = Service::findOrFail($id);. I can decode the individual column as done below and pass it to the view.
$service = Service::findOrFail($id);
$images = json_decode($service->image);
return view('services.show',['service'=>$service , 'images'=>$images]);
What I am asking is, can I decode the images in one query?
Well this is a single query, json_decode runs after the SQL query returned your desired result.
What you can do is add a $casts property to your Service model so Laravel encodes/decodes it automatically for you, then you don't need to store these values with json_encode, just do $service->image = $url, and when you run findOrFail, the image property will already be a decoded json.
protected $casts = [
'image' => 'array',
];
Here's the documentation
You can use $cast or Accessor
1: $cast:
protected $casts = [
'image' => 'array'];
2: Accessor:
public function getImageAttribute()
{
return json_decode($this->attributes['image']);
}
something strange is going on.
I got an array like this:
=> [
"optionalinformation" => [
"domain" => [
"type" => "string",
],
],
]
This array is used by a resource and if I use tinker to check this resource like this:
$result = App\Http\Resources\ProductResource::make(Product::find(2));
is_array($result->optionalinformation);
In this case the result is true: This is an array.
But if axios fetches the result, I am getting this:
"optionalinformation": {
"domain": {
"type": "string"
},
It's no longer an array but an object. Any ideas why this is happening?
This is my api-resource:
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
*
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'optionalinformation' => $this->optionalinformation,
];
}
There is a bit of confusion here, mostly caused by PHP lingo.
In PHP lingo an associative array is still an array. But an associative array is actually a dictionary.
Other programming languages don't see an associative array (dictionary) as an array and as such have a different vocabulary.
Your data structure is actually a dictionary, and not a numerical indexed array.
From a JSON perspective if your data structure has non-numerical keys then it gets translated to an object.
Your confusion stems from the fact that is_array will return true if the variable is a zero based indexed array, when in fact it returns true for associate arrays also.
It's in the definition. Laravel's resource classes allow you to expressively and easily transform your models and model collections into JSON. Check the Resource docs
If you are expecting an array in return then I suggest skip resource and pass the data directly from the controller using ->toArray(). But then again you are using axios in your vuejs then I strongly recommend to stick with json format as an expected response.
My entity looks like this:
class Request extends Entity
{
protected $casts = [
'id' => 'integer',
'added_at' => 'datetime',
'deadline' => 'datetime',
'completed' => 'integer'
];
}
When saving, the model generates the date fields in 'Y/m/d' format for the sql query, hovewer my database can not parse this. How can I force it to generate dates in 'Y-m-d' format when calling $myModel->insert($myEntity) ?
Entities has the option of setters. It performs the validation or conversion in your case whenever you perform save an entity. Lets say you want to change the form of deadline in that case you have to set the Setter for your deadline as follow :
public function setDeadline(string $dateString)
{
$this->attributes['deadline'] = $dateString;
return $this;
}
In the following line : $this->attributes['deadline'] = $dateString; You will use some library like Carbon to format the $dateString and then reassign your variable deadline. Reference link :
https://codeigniter4.github.io/userguide/models/entities.html