Laravel Backpack: coordinates field - php

I have a field named map_box which contains coordinates (see the example below) and cannot be serve as string.
Previously, before Backpack, I use to cast the field to an array 'map_box' => 'array' and the result was the following: note that the coordinates are not string
[
-73.661,
45.589
],
Now, I am trying to achieve the same result, but I keep getting an array of strings. I have tried using the repeatable field with numbers field in it, but the numbers are string. I have also tried to cast the field, then use the text field but this returns an error (as the form is expecting a string and not an array).
My goal is to be able to edit this field in a CRUD controller while being able to serve them with the correct format in my API. Any ideas on how I could achieve the same result as above? I can also use the following format, if this one is possible:
{
lon: -73.661,
lat: 45.589
}
Thanks!

i am not sure if i understand you correctly ... what backpack has to do with this casting?
however if you have something like:
$value='"max_box":{lon: -73.661, lat: 45.589}';
or any string and you want to get float number positive or negative you can use this:
preg_match_all('/-?\d+\.\d+/', $value, $matches);
the $matches[0] will be an array of your numbers

Related

JSON_CONTAINS string everywhere in the structure

I have a JSON column in my MySQL database (5.7.25) that can contain any type of JSON structure (so I do not have any property that is common to all the rows)
How can I perform a query through laravel ELOQUENT in order to search rows that match a string in one of the property of the JSON column?
I tried with this:
JSON_CONTAINS(`payload`, "key")
But mySQL throws the following exception:
Invalid JSON text in argument 2 to function json_contains: "Invalid value." at position 0
For example if the structure is similar to this:
{first_name:"John", "last_name":"Smith", "company":"Demo Company"}
I would like to search for all the rows that contain the word "Demo" in any of the properties (Also if the string is a substring of the json property value).
The only working way I found was the following:
JSON_SEARCH(payload, 'one', '%Demo%') IS NOT NULL
But it seems to be a bit slow. So I am asking if there's a faster way
The post title is different from the actual question, but for people who are wondering how to search inside anywhere in JSON, you could use simply a LIKE.
Given a json:
{
"rule": 4,
"triggers": {
"then": {
"field": "Sessions_Remaining__c",
...
},
"when": ""
}
}
You wont get any value by using:
SELECT * WHERE JSON_CONTAINS(json,'"Sessions_Remaining__c"')
So you can use instead:
SELECT * WHERE json LIKE '%"Sessions_Remaining__c"%';

How do I search and replace a string that occurs multiple times throughout an object, in both values and keys?

I want to replace all instances of a particular string in an object which includes properties, values and keys that include this string, including within longer keys/values that contain this string amongst other information.
Currently I'm doing this:
$amended_object = str_replace('search', 'replace', serialize($object));
$object = unserialize($amended_object);
So I turn the object into a string, search and replace, and convert it back.
However I often get Notice: unserialize(): Error at offset when the object is in a particular state, and it seems like it's not a very good solution.
When you serialize you get something like s:5:"value" which means string:length 5:"value". So if you change value to bob it is no longer length 5 and unserialize will error.
So you would need to correct the string lengths as well. Try JSON as it doesn't store the types or lengths:
$amended_object = str_replace('search', 'replace', json_encode($object));
$object = json_decode($amended_object);
Serialize wont work unless you correct the length of the containing string in the entity.
So you take the substring of the entity, split it up by the : sign, count/get the length of the total value string you want to correct and recalculate that with your replacement considered. Then update the stringcontent.

Select, where JSON Array contains

So in Laravel 5 there's the handy thing called JSON Where Clauses using MySQL's new ability to store and fetch JSON stored in a column:
User::where('meta->colors', 'red')->get()
would return all rows, where colors in the column meta would be set to red.
Now let's say colors is not a string, but an array containing multiple colors (colors => ['red', 'blue', 'green']).
What would be an efficient way to retrieve all rows, where colors contains e.g. the value red?
JSON_CONTAINS() does exactly what you're looking for:
JSON_CONTAINS(target, candidate[, path])
Indicates by returning 1 or 0 whether a given candidate JSON document is contained within a target JSON document, or—if a path argument was supplied—whether the candidate is found at a specific path within the target. — 12.16.3 Functions That Search JSON Values
Currently, Laravel's query builder does not provide a corresponding API. There's an open internals proposal for it though.
In the meantime, you can execute a raw query:
\DB::table('users')->whereRaw(
'JSON_CONTAINS(meta->"$.colors", \'["red"]\')'
)->get();
Which would return all users that have "red" in their meta->colors JSON field. Note that the -> operator requires MySQL 5.7.9+.
You can also call the whereRaw() directly on an Eloquent model.
Laravel 5.6
As of the 5.6 release, Laravel's query builder contains a new whereJsonContains method.
I think a way would be using the like operator:
User::where('meta->colors', 'like', '%"red"%')
However, this would only work if the values never contain the character " and the delimiters wouldn't change.
An update for this answer, according to MySQL or MariaDb, the correct syntax must be JSON_CONTAINS(#json, 'red', '$.colors'), and is necessary to use JSON_EXTRACT.
So them, the code inside Laravel (for version 5.5 or less).
Like say #Elwin, meta column must contains the following JSON: { "colors": ["red", "blue", "green"] }
User::whereRaw("JSON_CONTAINS(JSON_EXTRACT(meta, '$.colors'), '\"{$color}\"')")
Remember to use double quotes in value sentence.
JSON_CONTAINS(JSON_EXTRACT(meta, '$.colors'), '"red"')
The whereIn method verifies that a given column's value is contained within the given array.
Try this:
$colorArray = ['red', 'blue', 'green'];
$user = User::whereIn($meta->color, $colorArray)->get();
More about Laravel's whereIn.

PHP cast object to appropriate datatype based on its value

I have some objects which come from an XML file. I am trying to convert the XML file to SQL data structure. So far, I managed to retrieve the tables and columns and now I need to find out data types for each column.
gettype() didn't help since it always returns object.
Casting is not efficient, I tried to cast to every data type to see if it suits one but, for example, if I cast 5hi to integer, the result would be 5.
Here is a part on XML file:
<device>
<manufacturer>SIEMENS</manufacturer>
<model>SOMATOM Definition</model>
<serial>60301</serial>
<version>syngo CT 2010A</version>
</device>
So, as an example, manufacturer is string and serial is integer.
How can I cast an object to appropriate datatype based on its value?
is_numeric Will provide you with the capacity to check if a value is numeric
If you're looking to ensure integers, loop over each character and use ctype_digit
You may also wish to use regular expressions to recognise more complex structures.
Example:
if(is_numeric($value)) {
$value = doubleval($value); //cast to double
}

PHP string to array keys

I have a string that holds the property and key values to accessing a value on an object..
For Example, the string is "property_name[key1][key2][key3]", which relates to $obj->property_name[key1][key2][key3]
I've been trying to parse the string with a regular expression, but all of my attempts have ben in vain.
So far, my regular expression looks like this, but it won't get key2.
^(\w+)\[([^\]]+)\](?:(\[([^\]]+)\])+)
Am I on the right track or is there a better way to do this that I should try?
Thanks.
The regular expression could look like this:
^(\w+)(?:\[(\w+)\])+
Then your matches will contain the property name and the array keys. If the number of keys varies, use this to get the actual value: Using a path to an array item
You should use AJAX instead and send a useful array with objects inside to the server that you can parse with PHP.
var changed_values = [
{
'part_of_form': 'XX',
'field': 2,
'subfield': 3
},
.......
]
Then in PHP you can loop over it:
foreach($_POST['changed_values'] as $changed_value) {
........
}

Categories