Laravel whereIn implementation of whereJsonContains - php

I have this code that works fine and returns 1 item collection:
$myCollection = MyModel::whereJsonContains('payload->ProductCode->id', "1")->get();
I however want to fetch the $myCollection not just when the value is 1 but when it is contained in one of many array items.
$array = [0 => 1, 1 => 2, 2 => 3];
$myCollection = MyModel::whereJsonContains('payload->ProductCode->id', $array)->get();
UPDATES
When I try this code it return an empty data. I mean when I use 1 instead of "1". Could that be the reason why it doesn't work when I use an array?
$myCollection = MyModel::whereJsonContains('payload->ProductCode->id', 1)->get();
A sample of what the payload contains is this. I suppose that could give more clarity to my question:
{
"ProductCode": {
"id": "1",
"name": "My Service",
}
}
Running the above code returns an empty data. How do I fix this please?

You need to follow your query as below.
$array = [0 => 1, 1 => 2, 2 => 3];
// Eloquent
PaymentTransaction::whereJsonContains('payload->ProductCode->id',$array)->get();;
// or
PaymentTransaction::jsonContains('payload->ProductCode->id', $array)->get();
you can try it as below too.
$array = [0 => 1, 1 => 2, 2 => 3];
$array = array_values(array_map('strval',$array));
PaymentTransaction::where(function ($query) use ($array) {
foreach ($array as $id) {
$query->orWhereJsonContains('payload->ProductCode->id', $id);
}
})->get();

I think the first part of #Dilip's answer is not correct as I had the same issue with whereJsonContains on laravel 8. It would return empty result if the field is not a JSON array. The second part of his answer solves the issue but doesn't point the problem here.
The whereJsonContains method is used to query JSON array fields which in your case, payload->ProductCode->id is not an array field. That's why you get empty array.
Now as you are looking for rows that the payload->ProductCode->id contained within your $array, the whereIn method is the method you are looking for.
As Laravel document says, "The whereIn method verifies that a given column's value is contained within the given array". So you code would be like this:
$array = [ 1, 2, 3];
$myCollection = MyModel::whereIn('payload->ProductCode->id', $array)->get();
// $myCollection contains rows that their `payload->ProductCode->id` is contained within [1, 2, 3] array.
You could use whereJsonContains method if your data was like this:
{
"ProductCode": {
"id": ["1", "2"],
"name": "My Service",
}
...
}

Related

PHP check if array contains multiple values

I have an array like this fetched from a database:
[0] => Array (
[permission_id] => 1
)
[1] => Array (
[permission_id] => 2
)
I would like to check if this array contains multiple values with a function. For example:
function checkIfArrayContains($array)
{
...
}
$array = array(1, 2);
checkIfArrayContains($array); //Should return true
$array = array(2);
checkIfArrayContains($array); //Should return true
$array = array(1, 2, 3);
checkIfArrayContains($array); //Should return false
How could this be achieved using PHP?
If you are only getting one column from the database, and you use PDO, I would suggest you use the fetch mode FETCH::COLUMN, to gain an array that looks like
$arr = [1, 2];
Then you can simply use in_array to check for the value
Here's a suggestion:
$dbPermissions = [
['permission_id' => 1],
['permission_id' => 2],
];
function hasSufficientPermissions(array $dbPermissions, array $permissions): bool
{
$dbPermissionValues = array_column($dbPermissions, 'permission_id');
return empty(array_diff($permissions, $dbPermissionValues));
}
var_dump(hasSufficientPermissions($dbPermissions, [1, 2]));
var_dump(hasSufficientPermissions($dbPermissions, [2]));
var_dump(hasSufficientPermissions($dbPermissions, [1, 2, 3]));
This will output:
true
true
false
How it works:
array_column reduces your database array to [1, 2]
array_diff finds values in the first array supplied that are not present in the second array supplied
if a difference exists, then false should be returned - this is where we utilize empty

PHP - Find an object by key in an array of objects, update its value

I have an array of objects, and want to update an attribute of one of the objects.
$objs = [
['value' => 2, 'key' => 'a'],
['value' => 3, 'key' => 'b'] ,
];
Let's say I want to set the 'value' of the object with 'key'=>'a' to 5.
Aside from iterating over the array searching for the key, is there any quicker/efficient way of doing this?
Thanks.
EDIT: There is debate as to why I can't use an associative array. It is because this array is obtained from a JSON value.
If my JSON object is this:
"obj": {
"a": {
"key": "a",
"value": 2
},
"b": {
"key": "b",
"value": 3
}
}
There is no guarantee that the order of the objects will be retained, which is required.
Hence I need an index in each object to be able to sort it using usort(). So my JSON needs to be:
"obj": {
"a": {
"key": "a",
"value": 2,
"index": 1
},
"b": {
"key": "b",
"value": 3,
"index": 2
}
}
But I cannot use usort() on an object, only on arrays. So my JSON needs to be
"obj": [
{
"key": "a",
"value": 2,
"index": 1
}, {
"key": "b",
"value": 3,
"index":2
}
]
Which brings us to the original question.
By using array_column(), you can pull all the values with the index key in the arrays. Then you can find the first occurrence of the value a by using array_search(). This will only return the first index where it finds a value. Then you can simply replace that value, as you now have the index of that value.
$keys = array_column($objs, 'key');
$index = array_search('a', $keys);
if ($index !== false) {
$objs[$index]['value'] = 5;
}
See this live demo.
http://php.net/array_search
http://php.net/array_column
You can make the array associative with array column. That way you can directly assign the value.
$objs = [ ['value'=>2, 'key'=>'a'], ['value'=>3, 'key'=>'b'] ];
$objs = array_column($objs, null, "key");
$objs['a']['value'] = 5;
https://3v4l.org/7tJl0
I want to recommend you reorginize your array lake that:
$objs = [
'a' => ['value'=>2, 'key'=>'a'],
'b' => ['value'=>3, 'key'=>'b']
];
And now
if( array_key_exists( 'a', $objs )) {
$objs ['a'] ['value'] = 5;
}
I had it like that initially. But I need for the objects to have an
index value in them, so I can run usort() on the main array. This is
because the array comes from JSON where the original order isn't
respected
Then create an index array:
// When fill `$objs` array
$objs = [];
$arrIndex = [];
$idx = 0;
foreach( $json as $item ) {
$arrIndex [ $item ['key']] = $idx;
$objs [$idx ++] = $item;
}
// And your task:
if( array_key_exists( 'a', $arrIndex )) {
$objs [ $arrIndex ['a']] ['value'] = 5;
}
Aside from iterating over the array searching for the key, is there
any quicker/efficient way of doing this?
You have to pay the price of iteration either way.
You can search your collection for the interesting object (takes linear time), or you form some kind of dictionary data structure, e.g. hash table (takes linear time) and then find the interesting object in constant time.
No free lunches here.

Laravel Stuck with returning a json request -> Integer Array -> receiving Eloquent Models

I tried to answer a JSON Request, returning Laravel-Models on the delivered id's in the request.
This is my - JSON-Request
{
"places": [1,2, 3, 4, 5]
}
First i transform it to an array:
Convert Request to Array
$array = $request->places;
Output:
array:5 [
0 => 1
1 => 2
2 => 3
3 => 4
4 => 5
]
And this is how i would receive all Models (1,2 are the manually entered id's in this example:
Get all Places
$posts = Post::whereIn('place_id',[1,2] )->get();
My Problem, the placeholder [1,2] only allows a list of Integer. But I'm not able to transform my array into the placeholder variable like this.
$posts = Post::whereIn('place_id',[$request] )->get();
If i put the Array into a String variable, lets say: $request = "1,2,3,4,5" then, I only receive Models from the first Value (number 1 in this case).
Is there any way to transform my JSON-Requests to receive all Laravel Models?
Any help will be appreciated,
Cheers Sebastian
You should try something like this.
$posts = Post::whereIn('place_id', $request->request->get('places', []))->get();
When your request body is.
{
"places": [1, 2, 3, 4, 5]
}

Using Laravel's pluck method without an associative array

Let's say I've got an Articles collection, and I want to fetch the popular articles.
So first, I make a scopePopular() method in the Article method. Very simple.
Now I want to fetch their ids, so I'll do this:
Article::popular->pluck('id');
The result will be an associative array:
[
0 => 1,
1 => 34,
2 => 17
...
];
I want to get a normal array, without the keys, Like:
[1, 34, 17]
I know I can just do something like this:
array_values(Article::popular->pluck('id'));
But I believe Laravel has much more cleaner way to do this. Any ideas?
All arrays have indexes.
[
0 => 1,
1 => 34,
2 => 17
];
equals to
[1, 34, 17]
In other words:
$a1 = [0 => 1, 1 => 34, 2 => 17];
$a2 = [1, 34, 17];
$a1 === $a2;
// returns True
You can use values() method which is wrapper for array_values():
Article::popular->pluck('id')->values();
Its exactly what you need and what you get, By default php has the incremental key from 0.
You want to see something like a JSON array I assume.
Just do a return the array and you will see the JSOn array in browser, but internally its like this only.
Please confirm and let me know.Thanks
$store_type = \App\Websites::find($request->store_id)->first()->store_type;
// Outputs - just a string like "live" // there was option like a demo, live, staging ...
It might be useful for someone else.

How to extract an array item from an array variable in Laravel 5?

I'm new to laravel and now currently using Laravel version 5.2.
I have this set of array:
{
"id": 2,
"title": 'sample',
"question_index": 1,
"question": "Hope you could help me buddy.",
"data": [
{
"id": 1,
"answer": 'yes',
}
]
}
The array was created using the following eloquent query:
$exam_data = $this->template->where('id', $id)
->with('data')
->get();
Now I wanted to retrieve the 'data' array inside that array using Laravel 5.
I tried the following code but to no avail...
$user_data = $exam_data->data;
$user_data = $exam_data['data'];
$user_data = $exam_data->get('data');
Though I can pluck it using this:
$user_data = $exam_data->pluck('data');
which has this result (I don't know why but I'm not satisfied on it):
[
[
{
"id": 1,
"answer": 'yes',
}
]
]
Is there any ways or method that I can use to retrieve the 'data' array?
Like For example:
$user_data = $exam_data->data;
and how about accessing 'answer' field?
$user_data = $exam_data->data->answer;
Is this possible?
Appreciate any comments or suggestions. thanks!
$exam_data = $this->template->where('id', $id)
->with('data')
->get();
returns a Collection of multiple records, something like:
Collection [
0 => Collection,
1 => Collection,
]
That's why you can't access "data" directly from $exam_data, and that's what ->pluck() does for you.
pluck() does the same as:
$filtered = [];
foreach ($exam_data as $exam) {
$filtered[] = $exam->data;
}
if you dd($filtered) you get what you're after.
If you are expecting a single record, though, you could use ->first() instead of ->get(), which returns a single Collection and there you can access the data relationship with:
$exam_data = ..... ->first();
$data = $exam_data->data;

Categories