2

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:

response in local

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:

response in production

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.

Community
  • 1
  • 1
Tanmay
  • 3,009
  • 9
  • 53
  • 83
  • how do you return your results json to output? – Saeed M. Aug 27 '18 at 06:23
  • What if you implicitly cast the value to integer: `(int)$value` before sending it to the client? – Jite Aug 27 '18 at 06:23
  • @smoqadam The default way. `return Model::with('user')`. I am not doing anything new. – Tanmay Aug 27 '18 at 06:26
  • Note for future readers: after conducting a research I think I may have found the answer to my first question. I am experiencing the issue because [my production server is not using MySQL Native Driver](https://stackoverflow.com/questions/31527050/laravel-5-controller-sending-json-integer-as-string#comment51016022_31527050) and I have two solutions: a) Ask hosting provider to install mysql native driver on production machine or b) Go through every single model and add `$casts` array to each of them to explicitly convert the json response to boolean. – Tanmay Aug 27 '18 at 07:24
  • Getting same issue, did you get any solution ? – Mitul Marsoniya Nov 04 '19 at 06:48
  • @MitulMarsoniya enable MySQL native driver on your server. – Tanmay Nov 04 '19 at 08:02
  • "any non-empty string will always evaluate to true" is not true. "0" always evaluates to false just like 0. – miken32 Mar 23 '23 at 22:47

3 Answers3

2

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.

matiaslauriti
  • 7,065
  • 4
  • 31
  • 43
Mat Lipe
  • 725
  • 8
  • 14
1

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.

matiaslauriti
  • 7,065
  • 4
  • 31
  • 43
Saravanan
  • 769
  • 7
  • 16
  • You can add a setattribute method in your model which will set value to true of false when you record 0 or 1 Synyax is set$camelCasedDbField$Attribute – r0ulito Aug 27 '18 at 06:34
  • I think it shouldn't matter how JSON interprets boolean. It should be fine with number because `0` or `1` as conditional expression will evaluate to `false` or `true` respectively. Also, mysql boolean data type `tinyint` doesn't understand `true` or `false` it only stores `0` or `1`. The question is why that same response is represented differently on two environments: Number on local, String on production. – Tanmay Aug 27 '18 at 06:39
  • 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 – Saravanan Aug 27 '18 at 06:41
0

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.

Tanmay
  • 3,009
  • 9
  • 53
  • 83