Is this simple cast safe when saving records? - php

For most of my models in CakePHP I often create a function that handles saving a record. The default behavior for a Model's save is to return the data array or false.
I prefer the function to return true/false only. So I cast the result to (bool). Is this a valid way to cast something to boolean?
It's never not worked, but I've often wondered if it was a poor practice.
public function queue($url,$order=0)
{
$result = $this->save(array(
$this->alias => array(
'agg_domain_id' => $domain_id,
'order' => $order,
'url' => $url
)
));
return (bool)$result;
}

From php.net:
To explicitly convert a value to boolean, use the (bool) or (boolean) casts. However, in most cases the cast is unncecessary, since a value will be automatically converted if an operator, function or control structure requires a boolean argument.
So if you do if($this->queue('url',0)) then the cast is not necessary.
But if you do if($this->queue('url',0) === true) then you need to cast. And casting with (bool) is absolute legitimate.

Is this a valid way to cast something to boolean?
Yes
It's fine to do that where you only want to know success or fail.
When it's not ok
The only potential problems with casting the return value like that, is if the return value could be a falsey type e.g.:
array()
0
""
" "
a call to save always returns a nested array or false - there is no scope for getting a false-negative result with a call to save.

Related

Laravel 5.4 - Correct Validation rule for a required parameter that can be zero

I'm trying to validate a request to load stock into a table. Up until now stock has always had a positive value and the following validation rule worked exactly as expected:
[
"value" => "required|integer|min:0"
]
Stock is stored and can have multiple values and now stock can have a value of zero (0), I don't think it works with the 'required' rule.
I have changed it to use 'present' which I thought should suffice however it still fails, and adding 'nullable' also doesn't work:
[
"value" => "present|integer|min:0"
]
Are there validation rules to specify that a field must be present but the value can be zero?
Your initial validation rule just keeps working as desired; required doesn't throw an error on 0:
[
"value" => "required|integer|min:0"
]
From the Laravel documentation:
The field under validation must be present in the input data and not
empty. A field is considered "empty" if one of the following
conditions are true:
The value is null.
The value is an empty string.
The value is an empty array or empty Countable object.
The value is an uploaded file with no path.
So the issue was actually with my use of $request->intersect(...) in that it treats keys with a value of zero (0) as false and therefore removes them from the request data array.
For anyone else who may encounter this issue, here is the solution to treat zero (0) values as truthy while; null values, empty strings, and false will be treated as false.
Nb. $params, $rules, and $messages are arrays. See https://laravel.com/docs/5.4/validation#manually-creating-validators for more information.
return \Validator::make(array_filter($request->only($params), function($param) {
// This is needed to strip out empty values but treat zero (0) as truthy (default array_filter behaviour is
// to treat zero (0) as false) but we want these values to be present in the validated request data array as
// zero (0) in the context of a denomination is valid now that we will hold unactivated stock in the Vault.
return ($param !== null && $param !== false && $param !== '');
}), $rules, $messages);

How can I parse a JSON object in PHP? How can I retrieve the values of some specific fields of this JSON object?

I am absolutely new in PHP and moreover in Laravel framework (I don't know if Laravel provides some utility class for this kind of tasks). I came from Java.
So I have the following problem:
Into a class I perform a call to a REST web service, something like this:
$response = $client->get('http://localhost:8080/Extranet/login',
[
'auth' => [
'dummy#gmail.com',
'pswd'
]
]);
$dettagliLogin = json_decode($response->getBody());
\Log::info('response: '.(json_encode($dettagliLogin)));
$response->getBody() contains the returned JSON object, this is the output of the previous \Log::info():
{
"id":5,
"userName":"Dummy User",
"email":"dummy#gmail.com",
"enabled":true
}
So I have the following problems:
1) What exactly returns the json_decode() function? I really can't understand because PHP is not strongly typed and I have not a declared return type.
This is the method signature:
function json_decode($json, $assoc = false, $depth = 512, $options = 0)
and in the related doc it says #return mixed. What exactly means "mixed"?
2) Anyway the main problem is: I have to use the content of the previous returned JSON object and put these value into the related field of an array like this:
$attributes = array(
'id' => HERE THE id FIELD VALUE OF MY JSON OBJECT,
'username' => HERE THE email FIELD VALUE OF MY JSON OBJECT',
'name' => HERE THE userName FIELD VALUE OF MY JSON OBJECT,
);
So I think that I have to parse the value of the $response->getBody() or of the json_decode($response->getBody()) to obtain these values. But how exactly can I do it? What is the neater way to do it? Does the Laravel framework provide some utility to do it?
For better understanding, let's first describe - what's JSON?
It's a way of representing objects (arrays, objects, etc) in a string.
1) What exactly returns the json_decode() function? I really can't
understand because PHP is not strongly typed and I have not a declared
return type. This is the method signature:
function json_decode($json, $assoc = false, $depth = 512, $options =
0) and in the related doc it says #return mixed. What exatly means
mixed?
json_deocde converts the JSON string into the original "structure" it represent.
#return mixed means that the returned value of json_decode can be any type of variable. If the JSON represent an array - it would be an array type, if it represent an object - it would be an object type.
2) Anyway the main problem is: I have to use the content of the
previous returned JSON object and put these value into the related
field of an array like this:
$attributes = array(
'id' => HERE THE id FIELD VALUE OF MY JSON OBJECT,
'username' => HERE THE email FIELD VALUE OF MY JSON OBJECT',
'name' => HERE THE userName FIELD VALUE OF MY JSON OBJECT,
);
In order to make sure which type of variable your JSON represent, you can use var_dump(json_decode($json));. Anyway, it's a class object.
Therefore:
$object = json_decode($json);
$attributes = array(
'id' => $object->id,
'username' => $object->email,
'name' => $object->userName,
);
If you json string is an object (not an array) it will return an object (of type stdClass). Mixed means it can be multiple things, so if it was a json array, you'd get an array.
Best thing to do is use json_decode, and then var_dump (or var_export) to see what you actually get.

Validate that a PHP file only contains array inside

I have a configuration .php file that contains an array ( it has to be a PHP Array ) that contains something similar to:
<?php
return array(
'api_key' => 'e3awY0HoZr0c6L0791Wl2dA3',
'user' => 'Lequis',
'timeout' => '4'
);
These files are uploaded by users, i'd like to validate that the user doesn't add any malicious code, since these files will only contain an array, i'd like to validate that it is in fact only an array
Edit: see #VolkerK's comment regarding how this doesn't guard against the injection of malicious code.
Like #Jay Blanchard said, it may be better to actually think of a more appropriate data structure such as JSON. If you do want to stick to this structure however, you can use PHP's is_array() (http://php.net/manual/en/function.is-array.php) function to validate that a variable is an array before trying to pass that array to any other functions.
That only validates that you do have an array, and not that your array is in the proper format. To go one step further, you can validate that the array is of the right size using the count() (http://php.net/manual/en/function.count.php) function, these two things combined will ensure that you have an array with the correct number of values stored in the array.
The problem of checking to see whether or not the array values are in the correct format is a different beast. You can run through all of the keys and compare the passed key to an array of acceptable keys like so:
function isValidArr($usrArr){
$apiParams = array('api_key', 'user', 'timeout');
for($i = 0; i < count($usrArr); $i++ {
if(!strcmp($usrArr[$i], $apiParams[$i])) {
return false;
}
}
}
And then to check the values associated with each of the keys, I assume that the api_key is of a specific length or within a range, so you could check against that. For the timeout, you could ensure that the value is an integer. To validate against the username, you could implement a regex to ensure that the value adheres to a specific format.
I'm not sure what you want to check, an array or values?
If array, then, i think you can use simply is_array($arr) func.
If values, then there is a good Symfony component SymfonyOptionsResolver
You can use it like a validator for value types/values etc.
public function configureOptions(OptionsResolver $resolver)
{
// ...
$resolver->setAllowedTypes('host', 'string');
$resolver->setAllowedTypes('port', array('null', 'int'));
}
Or use some normalizer and check value with preg_match:
public function configureOptions(OptionsResolver $resolver)
{
// ...
$resolver->setNormalizer('host', function (Options $options, $value) {
if ('http://' !== substr($value, 0, 7)) {
$value = 'http://'.$value;
}
return $value;
});
}
Check documentation for additional info.
Is that what you're looking for?

when does php json_decode return false?

In the PHP documentation for json_decode it says it can return TRUE,FALSE,NULL.
Could some help me understand when it would return FALSE? I understand invalid JSON will return NULL, but when would the other two be returned if not the actual JSON value?
Thanks
JSON format definition clearly shows all possible values and their representations:
A value can be a string in double quotes, or a number, or true or
false or null, or an object or an array.
Both objects and arrays have special syntax in JSON representation (wrapped in {} and [] respectively), so they can't be mixed up with false in any case. The same goes with string - it's wrapped in "" (double quotation marks). As for Numbers, they have to contain at least one digit - so cannot be confused with false (and true and null) too.
So that leaves us with the only case: when json_encode processes an object having redefined its JSON representation. For example (PHP 5.4+):
class FalsyFoo implements JsonSerializable {
public $foo;
public function __construct($f) {
$this->foo = $f;
}
public function jsonSerialize() {
return false;
}
}
$f = new FalsyFoo(true);
$fj = json_encode($f);
var_dump( $fj ); // string(5) 'false'
var_dump( json_decode($fj) ); // bool(false)
Technically, we still work with false value here, but the source is obviously different.
If you're still not convinced, check the source code of json_decode, which calls php_json_decode_ex after checking the arguments. This, in turn, calls parse_JSON_ex first, which operates over the predefined state transition table; the latter has only one set of states leading to false value as result. If this call fails somehow, value is checked directly:
if (str_len == 4) {
if (!strcasecmp(str, "null")) {
/* We need to explicitly clear the error
because its an actual NULL and not an error */
jp->error_code = PHP_JSON_ERROR_NONE;
RETVAL_NULL();
} else if (!strcasecmp(str, "true")) {
RETVAL_BOOL(1);
}
} else if (str_len == 5 && !strcasecmp(str, "false")) {
RETVAL_BOOL(0);
}
... and that's the only case when return_value is set to boolean.
The documentation says that values true, false and null (case-insensitive) are returned as TRUE, FALSE and NULL respectively. This means that if the booleans true orfalse are in the object to be encoded, they will be shows as TRUE or FALSE, and the same for null. For example:
json_decode('["hello",true]');
would return:
["hello",TRUE]
It doesn't mean that json_decode will return values of true, false, or null

Value of option arguments: FALSE or NULL

When you have optional arguments that can have different types, which value is most suited to point out that the argument should not be taken into consideration? False or Null?
null is the value used to represent "no value", whereas false means "no", "bad", "unsuccessful", "don't" etc.
Therefore: null.
For me this depends on what I'm going to do with the value of said argument...
I am writing a database function where I can have default values as NULL
function somedbfunc($id = NULL, $column1 = NULL)
If these values are null my function may insert a blank record..
If I need to stop my function because of a non argument I may use FALSE
function blah($this = FALSE, $that = FALSE)
{
if ( ! $this || ! $that)
{
return FALSE;
....
So I am saying that both are totally valid, but it depends on the situation you find yourself in.
For optional arguments use null (generally).
Use null, if you need to differentiate between boolean values (true/false) and nothing (null). On the other hand if you don't need to check for not-set argument and you are using boolean variable then I'd go for false.
As you are saying that you want to tell the "optional arguments" "not be taken into consideration", I will go for null. False is explicitly saying "no" to the recipient. which is a valid input.

Categories