I am discovering that php is touchy when comparing types, especially when it comes to 0 because it is considered false and thus (I think) empty.
Is a variable containing 0 considered empty?
I have written a class in php that takes a stdClass and is able to manipulate it in different ways like edit, duplicate arrays, delete, etc. I have no idea of how the stdClass is made up. In the class I have a method that takes the address to the property in the stdClass and changes the property value to the new value and has to compare the property value with the new value at the end. Most of the values are entered or chosen by the user in the browser by selecting an array key. The key may be numerical or text.
In the method I have:
if (empty($address) || empty($new_value)){
$this->last_error = "Unknown error";
return false;
}
empty($new_value) does not work when the value is 0. 0 in this case has been the array key. Is there a way to make this work for all possible situations.
Somewhere at the very end I have:
if ($new_value==$this->get_property ($address)) { return true; } else { return false; }
I think php is seeing this as: if (0==0){} Is this true?
This does not work when the property is set to zero.
Related
I want to create a function that won't create errors if it's passed arguments that aren't valid array keys, and successfully check if the argument is set as a key in an array.
static function IsAwesome($name) {
return isset(self::$_awesomeThings[$name]);
}
This creates a lovely message when someone passes, say, an object as $name:
Warning: Illegal offset type in isset or empty in ...
What's the simplest way to avoid this behavior without excluding potentially valid keys, like true, for example? Assume existing code that can't be changed already relies on this behavior.
maybe you need something like:
static function IsAwesome($name) {
return array_key_exists((string)$name, self::$_awesomeThings);
}
http://php.net/manual/ru/function.array-key-exists.php
given I have an array, say:
$myArray=['12','AB','3C']
I want to return the value 2 (which is the length of each of the array elements indivudually.)
But in case I have something like
$myArray=['12','AB2','3C']
I want to stop the calculation/loop right after the second element of the array 'AB2' and let my function return null.
What is the most effective way to reach this in the matter of being performance and speed effective? Since such an array can get long.
Casual way
I think you are trying to stop the array loop the moment you get two different lengths in an element?
In that case, at worst, you'd need an O(n) runtime (since you need to verify every element, unless you have an abstract data type in mind in which case it could be O(1), if it is stored in the object property or you calculate the difference detected on the fly while pushing items into arrays)
Since the moment we discover an element is not the same length, we can simply quickly store the length of the first element in the array since we know if we detect any other length other than what we stored, we can immediately return null
function linear_loop($array) {
$len_of_first = strlen($array[0]);
foreach ($array as $val) {
if (strlen($val) != $len_of_first) {
return null;
}
}
//Function still running, entire array was same, return the length of first element
return $len_of_first;
}
This function is O(n) with each operation is constant. strlen is O(1)
Algorithmic complexity of PHP function strlen()
Most "performance-fastest"
Since you said that the array can get quite long, if you are not immediately generating the array, but rather you need to push items into it, then in your push operation, you can check before pushing it the item_to_be_pushed is the same strlen or whatever property you are trying to compare as the one you've stored (which can be picked arbitrarily, since the array must be of uniform some property)
In this case, you could have some object with property: uniform_length and store that. Then whenever you push into your array, you can check against it with the uniform_length. If it isn't the same length, then you can store in the object property called uniform as false. (By default uniform is true since if there is only one element in the array, it must be uniform).
This would be an O(1) calculation since it is stored as an attribute. But you probably don't need an object for something as simple as this, and you can just store it as some variable.
O(1) vs O(n) Runtime and why it is more performance effective
Since not everyone knows Big O, a quick explanation on what I said. O(1) runtime is "infinitely" better than O(n) runtime since the runtime of the function will not grow with input (as in processing 1 million items require the same amount of steps as processing 1 item)
Just loop through and return early when you find something that isn't correct. Don't worry about micro-optimizations until you have profiled and found that this function is really your bottleneck
ex.
function isCorrect($arr) {
$len = strlen($arr[0]);
for($arr as $val) {
if(strlen($val) != $len) {
return false;
}
}
return true;
}
Just my two cents. You could also use array_map for this:
$myArray = ['12','AB','3CC'];
$lengths = array_map('strlen', $myArray);
// output
Array
(
[0] => 2
[1] => 2
[2] => 3
)
you can just write an if statement and check the max($lengths) and return true or false
-Cheers
I have a php object that has a key=>value with something like [ipAddress] = 'NULL'
and if I do:
if(isset($object->ipAddress)){
echo "I am set!!!";
}
It never echoes. because apparently it's not "Set." I was under them impression that it is set, because oft he word NULL.
Is there a away to get around this to say, you are set? with out actually giving it a value? I ask because I attempted to write a function like this: (Don't mind the debugging, its the debugging that lead me to this question)
private function checkForColumnInModelObject($modelObject, $column, $custom_name){
$relationship = array();
foreach($modelObject as $model){
if(isset($model->$column)){
$value_returned = $model->$column;
var_dump($column);
var_dump($custom_name);
var_dump($value_returned);
//$relationship[$custom_name] = $value_returned;
}
}
//return $this->toObj($relationship);
}
So what I am trying to do here is check for a column in a model object. Now you might be given an array of columns, which we walk through in a function that calls this one, and an array of different model objects. were trying to see if the model object has that column.
So for example:
Does equipmentModel have ipAddress Column? yes? fetch me the value.
and the way we do this is by saying "is the column on this model set". The problem is, we might have columns with NULL value ... hypothetically their set, their value is just null, but PHP's isset() is all like NO, you are not set.
Any ideas on how I could write this to keep the same logic, BUT allow values of null to pass through assuming that model has that particular column?
If you want to know if an object property exists, regardless of its value, you can use property_exists.
if (property_exists($model, $column) {
...
}
isset returns true whenever you do an assignment to some variable. When you do $somevar=NULL; (In this case it is an assignment), if(isset($somevar) { echo "Inside"; } , The "Inside" will never print. Since NULL is never considered a value.
I have a method that takes an array as an argument, and returns true or false depending on the presence of a particular value.
In this scenario how many test cases should be written?
I think 3:
If the value is present
If the value is not present
If the array is empty (could be covered by 2 though?? )
I can think of 3 test cases:
If the array is not empty (or not null)
If the value is valid or not (I can pass an object where it expects a string :) )
If the value is present in array
It is the code of the function you want to test, so you cannot tell how many test cases are useful. Think again what your code does, how will the value be found?
An example: If your code tries to find a value with a certain name, and you make a string comparison, then think of the problems that can arise with string comparisons -> should the key be found case (in)sensitive, is null equal to an empty string, how does it handle duplicates and are other types converted correctly to strings (type juggling)?
I have a multidiminsional array that I have created in php that is passed back to a jQuery script. I need to iterate through this array and process the data.
In Firebug I can see that the data is located at data.data.items. I've tried finding the length of the array using data.data.items.length, but it comes back as undefined. Interestingly, this worked prior to my php portion working correctly when it passed back an array of 8 empty items. Now that it's populated (and the indexes are strings), length doesn't work. There is also an object in each of the items. What's breaking this?
An Array in JavaScript is an object nonetheless. When setting values using strings (or anything that isn't an integer), you are actually setting a property of the object (you are actually doing this when setting it with integer keys as well, but it's handled slightly differently).
To the issue of its sudden breakage after using strings as keys, I would expect that PHP realizes when you have an honest-to-goodness array versus an associative array, thus it sends arrays (surrounded by []) when all keys are integers, and objects (surrounded by {}) otherwise. I believe in the string-keyed case, PHP is generating objects, and thus .length becomes undefined (rather than 0 as in an empty array).
To answer your question, there is a simple way to count the "length" of this data:
var i = 0;
for (var item in data.data.items) {
i++;
}
Which will iterate through each property of data.data.items and count them. Note that if you (or any library you include) adds a property to the Object prototype, this will not produce expected results. This is fairly uncommon, but you must be aware of it when using for..in.
You can address this by using the method Nagh suggested, which ignores properties not defined on that particular object:
var i = 0;
for (var item in data.data.items) {
if(data.data.items.hasOwnProperty(item)) {
i++;
}
}
You can always use "foreach" kind of loop. In this case, you don't need to know what array length is there or even is it array or not, since you can iterate over object properties aswell.
As Joe already has pointed, javascript doesn't have associative arrays and when you trying to use one - you end up with object with properties. However, if u sure, that only properties this object got - is your array you can use code like that:
for (i in arr) {
if (arr.hasOwnProperty(i)) {
//do something with arr[i]
}
}
However if you really need an array, consider using integer as an array index.