laravel how to validate array index and values - php

I am submitting a single dimensional array of values to process on laravel 5.6
quantity[4]:11
quantity[2]:14
I have to validate both the index and the value, index should exits as stocks,id and value must be integer and minimum 1
I tried
public function rules()
{
$rules = [
'quantity.*' => 'exists:stocks,id',
'quantity' => 'required|integer|min:1',
];
return $rules;
}
but its validating only the values not index, please share your thoughts and comments.

I can not see anywhere we can validate array index with default Laravel validation. That why we need to write a custom one.
public function rules()
{
$rules = [
'quantity.*' => 'required|integer|min:1',
'quantity' => [
'required',
'min:1', // make sure the input array is not empty <= edited
'array',
function($attribute, $value, $fail) {
// index arr
$ids = array_keys($value);
// query to check if array keys is not valid
$stockCntWithinArrIDs = StockModelFullNameWhaterver::whereIn('id', $ids)->count();
if ($stockCntWithinArrIDs != count($ids))
return $fail($attribute.' is invalid.'); // -> "quantity is invalid"
}
],
];
return $rules;
}
The main point is compare stock count result when query whereIn (to reduce cost) their id with the array_keys of quantity. Because quantity's index is exists in stocks, $stockCntWithinArrIDs has to equal to count($ids), if not, there is at least one index is not as stocks id.
You can use foreach ($ids) then query the corresponding stock to see if my solution work. But PLEASE DO NOT use that solution on production env. :D
Hope this help!
Edited:
See: https://laravel.com/docs/5.6/validation#custom-validation-rules

Related

Get value of dynamic sub-array, in multidimensional array

Not sure if my question is clear, but here's what I'm trying to achieve. Let’s say I have a multidimensional array like so:
$arr['client1']**['dog']['Jack']**
$arr['client2']['cat']['Stacy']
How can I get the second portion of the array (between **), knowing it can be anything. For client 3, it could be a crocodile. For Client 4, it could be a car.
So I'm looking to "build" the structure of the array, dynamically. Something like so:
$arr['client1']{partBetweenThe**InTheExemple}
{partBetweenThe**InTheExemple} would be constructed "on the fly" (hence, the dynamically).
EDIT: Hopefully some clarifications...
The array changes every time. Basically, I'm building an addon to poll any API on the web. The data structure I'm getting can be anything. So what I need to do is build the key combination "on the fly", with variables.
In the exemple above, my variable would be something like $query = ['dog']['Jack'] and to get the value, I would poll it like so (from a logistic perspective, I know this doesn't work):
$arr['client1'][$query] or $arr['client1']$query or $arr['client1']{$query}
You can define the query as an array with each level as an element. Then we can iterate through that and check if we find a matching key in the response:
function findInArray(array $query, array $data)
{
foreach ($query as $key) {
if (!array_key_exists($key, $data)) {
// The key was not found, abort and return null
return null;
}
// Since the key was found, move to next level
$data =& $data[$key];
}
return $data;
}
// Example response
$response = [
'client1' => [
'dog' => [
'Jack' => 'Some value',
],
]
];
// Define the query as an array
$query = ['dog', 'Jack'];
$result = findInArray($query, $response['client1']);
Demo: https://3v4l.org/WjXTn
Edit:
So since the array's structure can't be changed this will return the client if the structure remains ['client']['animal']['name'].
$clients = [
'client1' => [
'dog' => [
'Jack' => []
]
],
'client2' => [
'cat' => [
'Stacy' => []
]
]
];
$animal = 'dog';
$name = 'Jack';
foreach ($clients as $client => $options) {
if (
array_key_exists($animal, $options) &&
array_key_exists($name, $options[$animal])
) {
echo $client;
break;
}
}

How to check if NULL value exists in multidimesional array?

I have seen some methods to determine if some value exists in php multidimensional array but I am stuck at simple problem.
I have a following array.
$data = [
['name' => 'sagar', 'address' => 'kathmandu'],
['name' => 'sagar', 'address' => null ]
];
I want to check if null value exists anywhere inside 2 dimensional array and keys can be anything. Is there any builtin function or we have made our own or some methodology to check ?
If you have any idea, it would be extremely helpful.
$hasNull = false;
foreach ($data as $set) {
if ($hasNull = in_array(null, $set, true)) {
break;
}
}

Check if value exists within an array of objects

I am working on an API which receives a PHP object of $POST data. I am trying to check wether the 'smsPhoneNumber' inside customFields exists but not sure how to do this.
I am currently able to check for 'email' using:
if ( property_exists( $data, 'email' ) ) {
return true;
}
Question: How to check if 'smsPhoneNumber' exists?
--
var_dump:
object(stdClass)[1515]
public 'email' => string 'email#email.com'
public 'customFields' =>
array (size=2)
0 =>
object(stdClass)[1512]
public 'name' => string 'Firstname'
public 'value' => string 'james'
1 =>
object(stdClass)[1514]
public 'name' => string 'smsPhoneNumber'
public 'value' => string '077'
You could use an array_filter to get the custom field you want.
$phoneFields = array_filter($data->customFields, function($field) {
return $field->name === 'smsPhoneNumber';
});
This will only return objects in the array that have a name property equal to smsPhoneNumber.
if (!count($phoneFields)) {
// Phone not found
}
// or
if ($phone = current($phoneFields)) {
echo "The first phone number found is " . $phone->value;
}
The drawback of using array_filter() to search for the subarray values is:
array_filter() will not stop once it finds a match; it will keep iterating even after a match is found until it reaches the end of the array.
You should use a technique that allows an early break/return.
I recommend a simple foreach() with a break.
$foundIndex = null;
foreach ($data->customFields as $index => $customFields) {
if ($customFields->name === 'smsPhoneNumber') {
$foundIndex = $index;
// or $wasFound = true;
// or $smsNumber = $customFields->value;
break;
}
}
This will prove to be very efficient and easy to read/maintain.

How to search item of collection with key?

I got the following collection:
$this->items = collect([$productId => [
'name' => $product->title,
'price' => $product->price,
'is_sale' => $product->is_sale,
'sale_price' => $product->sale_price,
'sale_percent' => $product->sale_percent,
'can_use_promocode' => $product->can_use_promocode,
'qty' => 1,
]);
]);
How to search an item with key? In documentation (https://laravel.com/docs/5.2/collections) I dont see any methods for it
UPD: For example, user added an item to cart ($this->items). I want to check existence of item in cart (need to do it with key). Analog for php function array_key_exists, but for collections.
use has()
if($this->items->has('key_name_to_check')){
///your task if exists
}
You can do this:
$this->items->toArray()[$key]
Or you can use the first() method:
$this->items->first(function($i, $k) use($key) {
return $key === $k;
});
Update
If you just want to know if an item with given key exists in the collection, you can use the offsetExists() method.
The offsetExists() method is full analog of array_key_exists(), because all it does is this:
return array_key_exists($key, $this->items);

Symfony validation - only part of array

I need help with symfony validator. It is possible validate only specific values in array? For example I have array:
'0' => [
'interestidKey' => true,
'anotherInterestedKey' => 'foo'
],
'error' => [
'errorMsg => 'not interest for me'
]
I need to validate this array with validator mainly value 0. I need know if array contains '0' key and inside if is key interestidKey with boolean value. I always use Collection for array but it not work in this case because ofc shows me an error that error does not contain interestidKey.
How can I fix this?
I'm not sure you will be able to do what you want with the shipped out of the box constraints. But you should be able to do what you want by writing your own: https://symfony.com/doc/current/validation/custom_constraint.html have a look at that and see if it can help you.
if you're validate you could do:
if(array_key_exists(0, $array)) {
if(array_key_exists("interestid", $array[0])) {
return true;
}
} else {
// do the error stuffs
}
You could just build a loop over your array, check for the key and if it is a numeric key (or not the error key) apply your validation to the children. That would look like this:
use Symfony\Component\Validator\Constraints as Assert;
...
$constraint = new Assert\Collection([
'fields' => [
// put any constraints for your objects here, keyed by field name
'interestidKey' => new Assert\Type('bool')
],
'allowExtraFields' => true // remove if you don't want to allow other fields than specified above
]);
$violations = [];
foreach($data as $key => $item) {
if ($key != 'error') {
$violations[$key] = $validator->validate($item, $constraint);
}
}

Categories