Laravel returning intergers in json response - php

i am using
$user = User::find($user_id);
return response()->json(array('user'=>$user),200);
On local server with php5.9 it returns all the keys except id as string.
{
"success": "1",
"message": "success",
"user": {
"id": 75,
"name": "",
"postal_code": "73733",
}
}
But the same code on production server with php7.0 returns other keys as of type integer ex. check this postal_code value.
{
"success": "1",
"message": "success",
"user": {
"id": 75,
"name": "",
"postal_code": 73733,
}
}
So solve this i am using $cast=[] in User.php.
But i have used raw queries also. What is the best way to convert all the values in response json to be of string type.

The difference in the type is most likely due to the fact that your local server is using the php5-mysqld (non-native) driver, whereas your production server is probably using the php-mysqlnd (native) driver. One of the main differences is that the non-native driver reads all fields as strings, whereas the native driver will automatically convert integer fields to PHP integers.
The id shows up as an integer in both cases because Laravel automatically adds the primary key field ('id') to the casts array with the type defined by the $keyType property (default to int).
I would say you have four options:
Attempt to install the non-native mysql driver for PHP 7 on your production server (not recommended).
Don't do anything on the PHP side, and just make sure that whatever is consuming the json can handle strings or integers (probably a good idea either way, but still doesn't solve the real issue).
Add postal_code to your casts array, to ensure it is always casted to a string (not bad; this will work for most cases, but is not exactly the correct solution).
Change the field type of the postal_code field from an integer to a varchar(5), varchar(9), or varchar(10), depending on if you're going to store the +4, and with or without a hyphen (best solution).
Changing the postal_code data type in the database to a varchar really is the best option. The main reason is that, while they are comprised of numbers, postal codes are not actually integers, or numeric in nature. You will never be doing any arithmetic with them. Additionally, there are postal codes that start with a leading 0, and if the value is stored as an integer, this is an extra edge case condition you have to contend with whenever displaying postal codes.

Enabling PDO::ATTR_STRINGIFY_FETCHES setting will solve this problem. You can add this PDO setting under database configurations.
'options' => array(
PDO::ATTR_STRINGIFY_FETCHES => true,
),

You could cast to string like:
$user['postal_code'] = (string) $user['postal_code'];
Further information on variable type casting is in the PHP manual.
Hope this helps :)

Related

How to update Object in mongo via PHP

I've asked to update an Object in mongo, (I am kinda new in NoSQL) so.. much I know is from guides and so, currently I am using this Codeigniter MongoDB library which simplifies the task.
So, this is the object I have stored in MongoDB:
{
"_id": ObjectID("5cfdc59844d81560d407a2e3"),
"equipo": "2bdca4c0-854d-4f73-bca8-cfb78a31f928",
"jugadores": {
"5361aa85-df9c-4099-8157-fd4d558622cc": {
"tipo": "i",
"estado": false,
"nombre": "name",
"apellido_st": "last_name",
"apellido_nd": "second_last_name",
"email": "email#example.com"
}
}
}
And this is the 'query' I am using to update it.
$this->mongo->where(array
(
"equipo" => "2bdca4c0-854d-4f73-bca8-cfb78a31f928",
"jugadores" => "5361aa85-df9c-4099-8157-fd4d558622cc"
))->set(array("estado" => true))->update("torneos_inscripciones");
Obviously.. isn't working and I can't find why is the problem exactly, the estado field isn't getting updated; probably is more simple than I though but can't get into it. The purpose is to update the estado field based on the jugadores uuid, in this case 5361aa85-df9c-4099-8157-fd4d558622cc
Based in B. Fleming answer, I made a change to the code:
$this->mongo->where(array(
"equipo" => "2bdca4c0-854d-4f73-bca8-cfb78a31f928",
"jugadores.5361aa85-df9c-4099-8157-fd4d558622cc" => array(
'$exists' => true
)))->set(array("jugadores.5361aa85-df9c-4099-8157-fd4d558622cc" => array("estado" => true)))->update("torneos_inscripciones");
The problem now is making the array empty only showing the estado field.
I'm not having much luck finding any good documentation for the CodeIgniter methods. Their documentation is terrible. From what I can find, however, I suspect that your problem is in your where query. Specifically, it looks like you're searching for the value 5361aa85-df9c-4099-8157-fd4d558622cc for the key jugadores. The problem with this lookup is that 5361aa85-df9c-4099-8157-fd4d558622cc is a field, not a value, so neither MongoDB nor CodeIgniter would know how to handle this lookup.
You might have more success by checking for the existence of the key 5361aa85-df9c-4099-8157-fd4d558622cc, rather than trying to match it as a value:
$this->mongo->where(array(
"equipo" => "2bdca4c0-854d-4f73-bca8-cfb78a31f928",
"jugadores.5361aa85-df9c-4099-8157-fd4d558622cc" => array(
'$exists' => true
)
))->set(array(
"jugadores.5361aa85-df9c-4099-8157-fd4d558622cc.estado" => true
))->update("torneos_inscripciones");
Please note that I used a single-quoted string, i.e. '$exists' instead of "$exists". This is important, because in PHP if you use double-quoted strings, words prefixed with a $ will be treated as a variable and evaluate the result before inserting into the string. Using single-quoted strings ensures that the value is not interpreted as a variable.

Boolean value in a JSON response is converted to string on production server

I have a Laravel application. In the users table, I have a boolean column called active:
$table->boolean('active')->default(false);
And in the front-end I normally check to see if the user is active or not like this:
Plain JS: if(user.active){ // do stuff }
VueJS: v-if="user.active"
This approach assumes that the value of user.active property, which of course is coming from the json response, is a non-string value: either 0 or 1. And that's what indeed I am receiving in the local machine:
Here pink colored values represent String values and green colored values represent Number values.
So, clearly, my local machine is interpreting it as a Numeric value and when the number 0 or 1 is used in a conditional expression, it is converted to boolean.
However that's not the case on my production server. The json response in the production server is converted to string which leads to unintended behavior of my application:
Notice that the value for the active key is not a Number, it is a String here! And since it's interpreted as a String, any non-empty string will always evaluate to true; hence my condition will always evaluate to true.
I have two questions: a) Why is this happening? b) How can I fix it?
Additional information: Both the production and local server are running same mysql version. PHP version on prod: 7.2.8 and PHP version on local: 7.2.9.
I think you are assigning the value for the active key as a numeric value 0. But JSON interprets BOOLEAN only with two values true and false. Just try to assign the value to true and false instead of 0 and 1.
For Reference please check https://www.tutorialspoint.com/json/json_data_types.htm
Edit From Comments
Yes, you can modify the record in the front-end in the way you need, because you will use array and objects in the front-end. But when you post the values to the server you will convert the array objects into json string, and the json string will assume 0 or 1 as number or string and will take true and false as boolean values. So you have to assign the key in the way the JSON works. Hope this method may work when sending data from client to server as well as from server to client.
This is because of the following reasons,
Most of the front end languages are interpreted, so they execute freely without compiling. But the back end languages will compile before executing. That's why we are using var to define any datatypes and js will use them in any way. But backend languages like java and .NET needs the variable type to get defined.
And in other hand JSON is not a language. Similar to XML it is used to send raw data between client and server. And it is designed in the way to work with both front end and backend. So you have to assign the values that both platforms will accept. That why you have to assign true or false instead of 0 and 1.
If you are using an Eloquent Model for your database table you may assign the $casts property to your model to assure the data type within the JSON response.
For example with your "users" table:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
/**
* The attributes that should be cast.
*
* #var array
*/
protected $casts = [ 'active' => 'boolean' ];
}
Documentation is here.
Since the question is still receiving answers, I am going to leave the actual answer to this particular problem (Type mismatch).
Enabling the MySQL native driver for PHP on the production server, solved my problem.

Making a Laravel 5.4 query on a JSON field containing a JSON array

i'm trying to query a JSON field containing an array of values.
For exemple sake we'll name the table "User" and the field "Friends". Here's how the Friends field looks like :
[{
"id": 1,
"img": "img-1.jpg",
"name": "Name 1"
},
{
"id": 2,
"img": "img-2.jpg",
"name": "Name 2"
},
{
"id": 3,
"img": "img-3",
"name": "Name 3"
}]
So what I would like to do is on the User table query everything from the Friends field where there is an id equals to 3.
So something like : User::where('friends->id', 3)->orderBy('id', 'desc')->get();
Of course, the exemple above works perfectly if the field did not contain an array, so if it was just :
{
"id": 1,
"img": "img-1.jpg",
"name": "Name 1"
}
Desperate, and even though I know it's not very logical, I have tried with "whereIn" : User::whereIn('friends->id', [3])->get(). Or stuff like : User::where('friends->[0]->id', 3)->get(), User::where('friends->[*]->id', 3)->get(), User::where('friends->*->id', 3)->get().
I have also tried with JSON_CONTAINS or JSON_SEARCH : User::whereRaw('JSON_CONTAINS(friends->"$.id", "3")')->get() and many different variants but nothing does it.
Before coming here I have read a few interesting articles on the matter (they are listed bellow), but I seem to be the only one who have ever stored a JSON array in a MySQL database, how is that possible ? ^^
https://mattstauffer.com/blog/new-json-column-where-and-update-syntax-in-laravel-5-3/
https://themsaid.com/laravel-mysql-json-colum-fast-lookup-20160709
http://www.qcode.in/use-mysql-json-field-in-laravel/
So if anyone could help me solve this problem I would really appreciate it.
Side notes : my current MySQL version is 5.7.11, so it does support JSON fields and Laravel doesn't throw any errors, it just returns an empty array.
Your whereRaw attempt is very close. If you were storing a single object, your path would be $.id. However, since you're storing an array of objects, your path is $[*].id. This should work for you:
User::whereRaw('JSON_CONTAINS(friends->"$[*].id", "3")')->get();
The friends->"$[*].id" selector (which is just a shortcut for JSON_EXTRACT()) will return a json array of the ids. JSON_CONTAINS() will then check if that json array contains the specified id.
Another option would be to build a json search string to use for JSON_CONTAINS(). For example, this query should also work:
User::whereRaw('JSON_CONTAINS(friends, \'{"id": 3}\')')->get();
This avoids the first call to JSON_EXTRACT(), so you're only calling one json method. I do not know which version would actually be faster, or if there would be any difference.
Also, on a side note related to JSON_SEARCH(), this function will only work if you are searching for string values. Since your json shows that the ids are represented as integers instead of strings, JSON_SEARCH() will not work. MySQL claims this is intended behavior (bug 79233 and dup bug 79316).
Just for reference, here is the documentation for the json search methods.

mongoDB index structure

I have put Index on mongoDB.
when I ensureIndex using php it put 1 as NumberLong(1) .
I want to know:
will this Indexing work or not.
If not
how to remove this NumberLong(1)
Code:
"0": {
"v" : 1,
"key" : {
"telNum" : NumberLong(1),
"requestID" : NumberLong(1)
},
"ns" : "database.collections",
"background" : true,
"name" : "tel_req"
}
Yes, the index will still work.
This is due to a change in the way that the PHP driver works ( https://jira.mongodb.org/browse/PHP-955 ).
I will come out immediately and say that it is not advised to remove it. That NumberLong object supports throwing in 64bit integers by default so it is extremely useful to have the defaults in the new PHP driver on by default and to treat NumberLong as the new generic number object.
However, to go into this a bit more and explain to you what's happening, there is this runtime configuration option called native_long: http://www.php.net/manual/en/mongo.configuration.php#ini.mongo.native-long which essentially allows MongoDB to store 64bit numbers by storing them into NumberLong objects. In PHP it would automatically convert to int data type and back again, making this transparent to the end user.
If you have this turned off MongoDB can only store 32bit integers.
This option used to be off by default but now it is on, that is why you are seeing this behaviour.
You can turn it off in the PHP configuration to remove the NumberLongs

json_encode doesn't double quote NULL ; cocoa touch mishandles

I'm writing a native iOS 7 app that requires retrieving data from a JSON api (that I control). Example JSON output looks like:
{
"id" : "544",
"name" : "1900 Green Gables",
"address" : "83 West Main Street",
"city" : "Milford",
"phone" : "(607) 547-1381",
"video_thumb" : null,
"thumbnail" : null,
"s_description" : null
}
I'm using php's json_encode() to convert the associative array returned from my DB query. In the objective-c I use NSJSONSerialization to convert the JSON into an NSMutableArray. The problem is that null values are converted to "<null>". I suspect this is because json_encode() is not double quoting null values. I'd rather keep the value null for consistency's sake (doesn't seem robust to check if a value is "<null>" in my obj-c code)
I know that I could fix the problem by regexing the output of json_encode(), but I'd rather avoid the extra step and I'm worried about the negative impact on performance. Are there any changes I can make to the PHP, Objective-C or even the SQL query to fix this?
<null> is the stringified description of [NSNull null], which is a placeholder for nil in Cocoa collections (which can't contain nil directly).
You should be comparing the value to [NSNull null]:
if (dictFromJson[#"video_thumb"] != [NSNull null]) {
// do stuff with video thumb here
}

Categories