Is there a way to check if an object has any fields? For example, I have a soap server I am querying using a soap client and if I call a get method, I am either returned an object containing fields defining the soap query I have made otherwise I am returned object(stdClass)#3 (0) { }.
Is there a way to tell if the object has anything?
public function get($id){
try{
$client = new soapclient($this->WSDL,self::getAuthorization());
$result = $client->__soapCall('get', array('get'=> array('sys_id'=>$id)));
if(empty($result)){$result = false; }
}catch(SoapFault $exception){
//echo $exception;
$result = false;
}
return $result;
}//end get()
This method should return either an object or false and I am only receiving an object with no fields or an object with fields.
Updated to reflect current behavior, 5/30/12
empty() used to work for this, but the behavior of empty() has changed several times. As always, the php docs are always the best source for exact behavior and the comments on those pages usually provide a good history of the changes over time. If you want to check for a lack of object properties, a very defensive method at the moment is:
if (is_object($theObject) && (count(get_object_vars($theObject)) > 0)) {
...
One of the user contributed code on the php empty() page which I think addresses your problem of checking if the array is filled but has empty values.
http://www.php.net/manual/en/function.empty.php#97772
To find if an array has nothing but empty (string) values:
<?php
$foo = array('foo'=>'', 'bar'=>'');
$bar = implode('', $foo);
if (empty($bar)) {
echo "EMPTY!";
} else {
echo "NOT EMPTY!";
}
?>
Related
I have a class that has a method that expects a response from an API service in array format. This method then converts the response array into an object by casting (object)$response_array. After this the method attempts to parse the contents of the object. There is a possibility that the returned array could be empty. Before parsing the contents of the object in my class method, I perform a check for null or empty object in an if...else block. I would like to use an equivalence comparison operator like if($response_object === null){} and not if(empty($response_object)){}.
Below is how my class looks like
<?php
class ApiCall {
//this method receives array response, converts to object and then parses object
public function parseResponse(array $response_array)
{
$response_object = (object)$response_array;
//check if this object is null
if($response_object === null) //array with empty content returned
{
#...do something
}
else //returned array has content
{
#...do something
}
}
}
?>
So my question is - is this the right way to check for empty object, without using the function empty() and is it consistent? If not then how can I modify this code to get consistent results. This would help me know if null and empty mean the same thing in PHP objects. I would appreciate any answer where I can still use an equivalent comparison like this ===
It is not the right way to check for an empty object. If you call your function parseResponse with an empty array, the if condition will still be false.
So, if you would put echo in the if-else code like this:
class ApiCall {
//this method receives array response, converts to object and then parses object
public function parseResponse(array $response_array)
{
$response_object = (object)$response_array;
//check if this object is null
if($response_object === null) { // not doing what you expect
echo "null";
}
else {
echo "not null";
}
}
}
Then this call:
ApiCall::parseResponse(array()); // call with empty array
... will output
not null
The same happens if you test for empty($response_object). This used to be different in a distant past, but as from PHP 5.0 (mid-2004), objects with no properties are no longer considered empty.
You should just test on the array you already have, which is falsy when empty. So you can just write:
if(!$response_array) {
echo "null";
}
else {
echo "not null";
}
Or, if you really want an (in)equality, then do $response_array == false, making sure to use == and not ===. But personally, I find such comparisons with boolean literals nothing more than a waste of space.
All of the following would be working alternatives for the if condition:
Based on $response_array:
!$response_array
!count($response_array)
count($response_array) === 0
empty($response_array)
Based on $response_object:
!get_object_vars($response_object)
!(array)($response_object)
Note that get_object_vars could give a different result than the array cast method if $response_object were not a standard object, and would have inherited properties.
Look at this example
$ php -a
php > $o = (object)null;
php > var_dump($o);
class stdClass#2 (0) {
}
php > var_dump(!$o);
bool(false)
So, it is not good idea to compare object with null in your case. More about this: How to check that an object is empty in PHP?
This is something I haven't seen before but it appears to be supported and it does work, referencing the returned array key directly after the providing function is called. BUT... is this good practice? Will this be supported in the future? Does this even have a name?
<?php
function example_function() {
$return = array('part_1', 'part_2');
return $return;
}
$var = example_function()[0];
echo $var;
To get the same result I would normally do the following
$var = example_function();
$var = $var[0];
It's called Array Dereferencing. It has been available since PHP 5.4. It is acceptable to use although some might say it reduces readability.
Use it only when you are sure that you will always get array to work on. Sometimes ago I've have following code in some scraper class:
$ip = $this->getIP()[0];
I didn't check whether this function could return string and it caused some logic errors. Nowadays each time when I want to get array's item I do
$ip = $this->getIP()
if(is_array($ip)) {
$ip = $ip[0];
} else {
throw new Exception('Expects array here')
}
I am trying to loop through a JSON Object (DATA) containing three nested JSON Objects (NEWUSERS,NEWUSERDATA,NEWRELATIONS), using a switch function to choose the appropriate function for a MySQL insert. Each function housed in the switch is called once as I loop through the keys, but they ALL seem to only ever receive the NEWRELATIONS object. Consequently, the functions fail with the exception of insertNewTestRelations, the function intended to receive the NEWRELATIONS object. I think the answer must be staring me in the face, but can anybody think why the JSON object is being reused?
Reading and iterating JSON
$json=json_decode($_SERVER['HTTP_JSON'],true);
$data=$json['DATA'];
foreach($data as $key=>$json_obj){
$result=null;
$result=$db->insertNewSwitch($key,$json_obj,$last_sync);
$response[$key.":errors"]=$result['errors'];
$response[$key.":successes"]=$result['successes'];
}
Switch function
public function insertNewSwitch($key,$json_obj,$last_sync){
$result;
if($key="NEWUSERS"){
$result=$this->insertNewTestUsers($json_obj,$last_sync,$key);
}
if($key="NEWUSERDATA"){
$result=$this->insertNewTestUserdata($json_obj,$last_sync,$key);
}
if($key="NEWRELATIONS"){
$result=$this->insertNewTestRelations($json_obj,$last_sync,$key);
}
return $result;
}
Try using else in your logical operator for the switch, and also double equals for comparisons
public function insertNewSwitch($key,$json_obj,$last_sync){
$result;
if($key=="NEWUSERS"){
$result=$this->insertNewTestUsers($json_obj,$last_sync,$key);
}
else if($key=="NEWUSERDATA"){
$result=$this->insertNewTestUserdata($json_obj,$last_sync,$key);
}
else if($key=="NEWRELATIONS"){
$result=$this->insertNewTestRelations($json_obj,$last_sync,$key);
}
return $result;
}
You are using = not ==. This is most likely your problem.
Because you are assigning the values, it will evaluate to true each time, so each statement will be entered.
My current way:
class A {
public function function_b($myint) {
if (!is_numeric($myint)) return false;
// code ...
}
}
I would like to abandon the function is_numeric() like this:
public function function_b(Integer $myint) {
// code ...
}
It works with arrays like this:
public function function_c(Array $arr) {
// only executes following code if $arr is an array / instance of Array!
}
Note: the function has to return false if the value isn't a number (int)! I don't want to cast it.
How would you short my current code? Thanks in advance!
You can't force strict types in function prototypes in PHP inherently, because it's not a strictly typed language. PHP is a weakly typed language and trying to go against the grain will only hurt you in many situations. Also, is_numeric does not guarantee that your value is of type int (for what it's worth).
What you can do is analyze your need for why you think this approach is necessary in the first place and decide on how to best implement this without creating potential for bugs.
For example, take the following scenario where what your method expects is an ID for a database query.
class MyClass {
public function getUser($id) {
if (!is_int($id)) {
throw new Exception("Invalid argument supplied. Expecting (int), but argument is of type (" . gettype($id) . ").");
}
// Otherwise continue
$db = new PDO($dsn);
$stmt = $db->prepare("SELECT username FROM users WHERE user_id = ?");
$stmt->execute(array($id));
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
}
$MyObject = new MyClass;
$result = $MyObject->getUser($_POST['id']);
/* The problem here is $_POST will always be of type string. */
What this should tell you is that it makes no sense to force type checking here since PHP will have done the right thing for you had you just let it alone.
The question you need to be asking yourself is not "How do I force strict typing?", but rather "Why would I need to force strict typing at all?".
You should look into typecasting:
http://php.net/manual/en/language.types.type-juggling.php#language.types.typecasting
Just use (int) when accessing the value to typecast it to an integer.
You could just typecast it:
public function function_b($myint) {
$myint = (int) $myint;
}
Or better yet add a public setter to class A which will do it for you every time you set the value:
class A
{
public function setMyInt($myInt)
{
$this->myInt = (int) $myInt;
}
}
-- Update (based on comment) --
class A
{
public function doSomethingWithAnArray(array $array)
{
....
}
}
Notice the keyword array in the signature of the doSomethingWithAnArray method, now if you don't pass an array to this function PHP will throw a fatal error and cease code execution. This is known as typehinting, and can be applied to objects as well.
function needsInteger($int) {
if (((int) $int) != $int) return false;
// ...
}
The advantage here is that you can still accept loosely typed parameters, but the non-strict equality check against the cast value will yield an acceptable result.
I'm having some problems getting my object to gracefully fail out if an invalid parameter is given during instantiation. I have a feeling it's a small syntax thing somewhere that I simply need fresh eyes on. Any help is more than appreciated.
class bib {
protected $bibid;
public function __construct($new_bibid) {
if(!$this->bibid = $this->validate_bibid($new_bibid)) {
echo 'me';
return false;
}
//carry on with other stuff if valid bibid
}
private static function validate_bibid($test_bibid) {
//call this method every time you get a bibid from the user
if(!is_int($test_bibid)) {
return false;
}
return (int)$test_bibid;
}
}
Note that I have an 'echo me' line in there to demonstrate that it is in fact, returning false. The way that I'm calling this in my PHP is as follows:
if(!$bib=new bib('612e436')) {
echo 'Error Message';
} else {
//do what I intend to do with the object
}
This outputs the me from above, but then continues on into the else block, doing what I intend to do with a valid object.
Can anyone spot anything I'm doing wrong in there?
Thanks!
I see several problems in this code.
First of all, I think you want to do something like this:
$myBib=new bib();
if($myBib->validate_bibid('612e436'))
{ ..do stuff.. }
(or something similar)
remember that __construct is not a normal method. It's a constructor, and it shouldn't return anything. It already implicitly returns a reference to the new instance that you've made.
Second, your validate_bibid returns either a boolean or an integer. You won't get immediate problems with that, but I personally don't like the style.
Third, you've declared a protected member $bibid, but you don't set or reference it anywhere. I'd expect it to be set in the constructor for example. After that you can just call validate_bibid without any argument.
This piece of code is obviously confusing you because it has some weird constructs and therefore doesn't behave in a normal way. I'd suggest to rethink and rewrite this piece from scratch.
Update:
Another issue:
I don't think this line does what you think it does:
if(!$this->bibid = $this->validate_bibid($new_bibid)) {
You probably mean this:
if(!$this->bibid == $this->validate_bibid($new_bibid)) {
// Or even better:
if($this->bibid <> $this->validate_bibid($new_bibid)) {
You can't return in a constructor in PHP - the object is still created as normal.
You could use a factory or something similar;
if(!$bib = Bib_Factory::loadValidBib('612e436')){
echo 'Error Message';
} else {
//do what I intend to do with the object
}
Or throw an exception in the constructor and use a try catch instead of the if statement.
definitely, you need to have comparison with == instead of = which is an assign operation.