Array to string conversion - Validation rule for eloquent - php

I'm trying to validate a field using "in" and then passing an array befored defined. But when creating I get this error
"message": "Array to string conversion",
"exception": "ErrorException",
If I comment out the line where I use the validation, then works. So I'm pretty sure the problem is that.
I've seen another related posts, but they didn't work.
Thank you.
CONST ARRAY_EXAMPLES = [
'example1' => 0,
'example2' => 1,
'example3' => 2,
'example4' => 3,
'example5' => 4,
'example6' => 5,
];
protected $fillable = [
'array_example'
];
'array_example' => 'int|in:' .array_values(self::ARRAY_EXAMPLES)

When you concatenate two expressions in php both of them are casting to strings. But there is no any built in way to cast array to string. So you can't concatenate string and array here:
'int|in:' .array_values(self::ARRAY_EXAMPLES)
But you can convert array to string by implode:
'int|in:' . implode(',', self::ARRAY_EXAMPLES)

Related

Check if values in array are in another array using Laravel Validation

I want to check if all the values of my input, an array, are in another array. For example:
$my_arr = ['item1', 'item2', 'item3', 'item4'];
Validator::make($request, [
'item' => [ /* what do i put here??? */ ],
]);
I don't think the rule in works, because that expects a single value as input, not an array. in_array doesn't work either. I've tried creating a custom rule or closure, but neither of those allow me to pass in a parameter (the array I want to check against). Especially since I want this same functionality for multiple arrays, for different inputs, it would be nice to have a generic rule that works for any array I give it.
If that's not possible, I suppose I need to create a rule for each specific array and use !array_diff($search_this, $all) as this answer says. Is there an alternative to this?
True that in doesn't accept an array but a string. So you can just convert the array into a string.
$my_arr = ['item1', 'item2', 'item3', 'item4'];
Validator::make($request, [
'item' => [ 'in:' . implode(',', $my_arr) ],
]);
implode
Another better solution might be to use Illuminate\Validation\Rule's in method that accepts an array:
'item' => [ Rule::in($my_arr) ],
Laravel Validation - Rule::in

Laravel How can I return array of objects

I've got simple array of objects:
"myObject" => [
'key1' => ["property1" => 'value1', "property2" => 'value2'],
'key2' => ["property1" => 'value1', "property2" => 'value2'],
...
],
When I'm returning this via laravel dot syntax:
return [
'listOfObjects' => trans(objects)
]
I've got:
myObject: {
key1: {property1:'value1', property2:'value2'},
key2: {property1:'value1', property2:'value2'},
etc..
}
It's simple.
Now how can I modify my return to get only an array of objects, without numbers:
myObject: {
{property1:'value1', property2:'value2'},
{property1:'value1', property2:'value2'},
etc..
}
Any ideas?
I don't think it is possible to solve in PHP. As it is said in the manual
"...index may be of type string or integer. When index is omitted, an
integer index is automatically generated, starting at 0..."
Also, what you are asking seems to be quite pointless. If you could describe what it is you are trying to accomplish, people might be able to help you better.
The function to use in this case is:
$tryit = trans('objects');
$new = collect($tryit)->flatten(1);
$new->values()->all();
unfortunatelly there is a bug in Laravel 5.6 on this function and it digs two level deep instead of one :/
[edit]
I think I now understand what you want. What you call an Array in PHP is not necessarily an Array in JSON. For JSON your "myObject" is an Object.
For JSON to recognize something as an Array, it can only have numbers as keys.
So change the keys from "key1", "key2", ... into 0, 1, ...
$result = [];
foreach($myObject as $element){
$result[] = $element;
}
return $result;
After that, $result looks like this
$result = [
0 => ["prop1" => "val1", "prop2" => "val2"],
1 => ["prop1" => "val1", "prop2" => "val2"]
]
Or equivalently in the short notation
$result = [
["prop1" => "val1", "prop2" => "val2"],
["prop1" => "val1", "prop2" => "val2"]
]
Now JSON should recognize this as an Array instead of an Object when Laravel converts $result to JSON or you make it yourself: return response()->json($result);
[previous:]
You can not return an object which has values but no keys.
The simplest form of keys are numbers, which is what arrays are using.

Why is this array count returning 1 instead of 2?

Why is this array count returning 1 instead of 2?
Shouldn't it return 2?
$join = [
'JOIN' => ['coins','users.id','user_id'],
'JOIN' => ['coins','users.id','user_id']
];
echo count($join);
You are creating an associative array, which means that each element is associated to one unique key. Therefore, in an array, each key can only appear once. A key appearing twice means that the value will be overwritten.
If you try to var_dump your array, it would have this output:
array(1) {
["JOIN"]=>
array(3) {
[0]=>
string(5) "coins"
[1]=>
string(8) "users.id"
[2]=>
string(7) "user_id"
}
}
As seen from this result, only one line exists.
If you need to have 'JOIN' in every element, maybe you want to change your array structure into this:
$join = [
['JOIN' => ['coins','users.id','user_id']],
['JOIN' => ['coins','users.id','user_id']]
];
This will carry the information 'JOIN' in every element. However, I cannot imagine why you would need such a thing.
Instead, maybe you want to have multiple elements under the 'JOIN key:
$join = [
'JOIN' => [
['coins','users.id','user_id'],
['coins','users.id','user_id']
]
];
As per your comments, maybe you eventually want to have a structure like this:
$join = [
'JOIN' => [
['coins','users.id','user_id'],
['coins','users.id','user_id'],
],
'INNER JOIN' => [
['coins','users.id','user_id'],
['coins','users.id','user_id'],
]
];
According to your comments, it might be more desirable if you do this through object-oriented programming instead:
class Join{
const JOIN = 0;
const INNER_JOIN = 1;
// we are using constants to prevent bugs caused by typos
public $type;
public $coins;
public $usersDotId; // I don't really know what you are trying to do here
public $userId;
}
Then you can use it like this:
$joins = [];
$join = new Join();
$join->type = Join::INNER_JOIN;
$join->coins = "some_value";
$join->usersDotId = "some_value";
$join->userId = "some_value";
$joins[] = $id;
$join = [
'JOIN' => ['coins','users.id','user_id'],
'JOIN' => ['coins','users.id','user_id']
];
echo count($join);
how may I modify this array to have 2 keys, without changing the key name?
In order to not need to change this key name, make JOIN an array of numeric values so structurally you want:
array:
----> [Join] :
\---> [0]
\---> coins
|---> users.id
|---> user.id
This can be achieved with this syntax (clarified for understanding):
$join = [
'JOIN' => [0] => ['coins','users.id','user_id'],
[1] => ['coins','users.id','user_id']
];
(simplified for ease):
$join = [
'JOIN' => ['coins','users.id','user_id'],
['coins','users.id','user_id']
];
gives you a $join array with a count of 1, which contains (the one) an array with a count of 2, each of those containing 3 elements.
Without addressing the more specific problem that appeared in the comments, and acknowledging that you've already accepted an answer that works for your purposes, here is a more theoretical explanation for why you can't have two of the same key. This may be not be useful for you, but hopefully it could help someone who does not intuitively grasp this concept.
Regardless of whether you assign your own string keys ($array = ['key' => 'value'];), assign your own integer keys ($array = [42 => 'the answer'];), or let PHP automatically assign integer keys ($array[] = 'something';), the keys must be unique.
According to the PHP manual for arrays:
An array in PHP is actually an ordered map. A map is a type that associates values to keys.
Most programming languages have something like this. This association of values to keys means that by definition, keys must be unique. If a language allowed you to create a "map" with multiple identical keys pointing to different values, looking up a value by key would be impossible (or at least would produce ambiguous results), so the map would be fairly useless.
PHP will let you write things like:
$example = [
'a' => 1,
'b' => 2,
'a' => 3,
];
var_dump($example);
without giving any errors, but the result of that will be:
array (size=2)
'a' => int 3
'b' => int 2
where 'a' => 3 has overwritten the previously defined value of the 'a' key. This allows the map to continue to work, so that $example['a'] will always yield the same value. If you actually could have
array (size=3)
'a' => int 1
'b' => int 2
'a' => int 3
Then what would be the result of $example['a']? Any defined behavior (first instance of 'a', etc.) would mean that some values of 'a' would be inaccessible.
Because you are using same array key to both the element
try this,
<?php
$join = [
'JOIN1' => ['coins','users.id','user_id'],
'JOIN2' => ['coins','users.id','user_id']
];
echo count($join);
?>
Or with same key try following
$join = [
['JOIN' => ['coins','users.id','user_id']],
['JOIN' => ['coins','users.id','user_id']]
];

How to cast multiple array elements to object

I'm trying to create an array containing multiple objects.
I wrote this code (it's a member of an existing class)
public static $Roles = [
(object) ['code' => 'SO', 'name' => 'Socio'],
(object) ['code' => 'RESP', 'name' => 'Responsabile zona'],
(object) ['code' => 'AMM', 'name' => 'Amministratore'],
];
but I get this error:
syntax error, unexpected '(object)' (object) (T_OBJECT_CAST),
expecting ')'
on the second line.
I thought this should work, because I already used the same cast syntax to define associative array elements:
return view('edit-headquarter', [
'hq' => (object)['name' => '', 'id' => 0],
'submitAction' => 'insert'
]);
I'm doing something wrong?
EDIT: I'm using PHP 5.4.45
I'm not sure, but this can be related as suggested by Martin Persson
If you're using PHP version below v5.6, then you will not be allowed to have an expression as a default value for class members. Other than that, I don't see anything wrong with the way you have declared it.
To cast an associative array to object you can use a bit dirty, but widely used
$obj = json_decode(json_encode($arr));

How can I force PHP's json_encode integer values to be encoded as String?

I'm using PHP v5.6.
As i read that php json_encode function is automatically converting int to string. But not in my case. Json_encode is still return it to int not string.
Like example:
json_encode(['code' => 200, 'results' => [id=> 1]]);
my expected results is all become a string. but what i get is
{"code":200,"results":{"id": 1}}
Expected output:
{"code":"200","results":{"id": "1"}}
How can i change all the result become string without using "" for every value?.
NB: results array is based on query.
In the link posted by Thomas in comments, one user suggests that you do this:
$data = json_encode(array_map('strval', $data));
This might not be the most efficient in terms of performace though, since every entry on the array will pass through the strval function.
json_encode(['code' => 200, 'results' => [id=> strval(1)]]);
With strval() php will return
The string value of var.
To ensure that all numeric "leaf nodes" of a potentially multi-dimensional array are cast as strings, call array_walk_recursive() and make conditional changes to each value type. By checking if the value "is numeric", you prevent values like null and booleans from being cast as strings.
Code: (Demo)
$array = [
'code' => 200,
'results' => [
'id' => 1
],
'a' => [
[
'b' => [
4,
null,
false
]
]
]
];
array_walk_recursive(
$array,
function(&$v) {
if (is_numeric($v)) {
$v = strval($v);
}
}
);
echo json_encode($array);
Output:
{"code":"200","results":{"id":"1"},"a":[{"b":["4",null,false]}]}

Categories