I started having a weird behavior with PHP's empty() function. Everything used to work properly, but now it doesn't, and I don't get why.
I have a tbInventory class that represents out products. One record per unit.
That class has a getBootloaderRevision method/property:
public function getBootloaderRevision() {
if (empty($this->cBootloaderRevision)) {
return null;
} else {
return $this->cBootloaderRevision;
}
}
It used to work, but now, the empty() function returns true even if the member has a value. Here is an example:
$prod = new tbInventory($db, 1009);
$test = $prod->cBootloaderRevision;
echo $prod->cBootloaderRevision . "<br>";
echo $test . "<br>";
echo (empty($prod->cBootloaderRevision) ? "1" : "02") . "<br>";
echo (empty($test) ? "1" : "0") . "<br>";
I'm loading an item from my database, an Item I know to have a BootLoader Revision. I declare and load it on the first line, then I put the value of the MEMBER itself straight in a variable. I then echo both the member and the variable to prove they both have the value.
I then echo a 1 or a 0 depending on the result of the empty() function for both the member and the variable. Here is the results:
01.07
01.07
1
0
I'm at a lost here. I do NOT understand why this is happening. I know it used to work, I haven't touched this in over a year. We made an update on the server recently, and it seems to have started acting this way since the server. I was not in charge of the update, but I think they updated both the OS and PHP.
Have you ever seen something like that???
Thank you,
The only thing that would explain this behaviour is if cBootloaderRevision isn't a "physical" property but is being retrieved with the __get magic method, and the class either has no __isset method implemented or that method is returning results inconsistent with __get. The reason is that empty will invoke __isset first, but $prod->cBootloaderRevision will just invoke __get.
See http://php.net/manual/en/language.oop5.overloading.php#object.get.
Related
I'm having some trouble accessing the properties of a passed object in one of my functions. I know there is not an issue with the object definition or how I am accessing the properties, because I am able to do that elsewhere just fine.
For reference:
$officials_array is an array of Official objects.
$division and division_scope are properties of this object.
$modal_counter is just a counter (I have simplified the code down to just what is giving me issues, so as you can see the counter isn't actually modified in this code).
Here is the code:
$modal_counter = 0;
function echoOfficial($offical, $modal_counter) {
echo "Scope: " . $official->division_scope . " Name: " . $official->division;
return $modal_counter;
}
echo "<h2>National</h2>";
foreach ($officials_array as $official) {
if ($official->division_scope == "national") {
$modal_counter = echoOfficial($official, $modal_counter);
}
}
The if works fine, and the echoOfficial() function gets called, but the properties are not echoed along with the text (the output is just Scope: Name:), and it seems that the object does not actually get passed to the function. If I try to access one of the object's methods, the code just doesn't run.
I can't figure out what I am doing wrong. I think it may have something to do with accessing the objects from a foreach loop, but I am not sure.
You have a simple typo - function echoOfficial($offic!!al - you missed i.
I'd recommend you use any syntax-highlighting IDE to avoid such mistakes in future, as they are incredibly hard to detect otherwise.
If I run the following PHP code, I get 123. I don't understand the logic behind it. What I think is when I call the function each time it suppose to output 1. So the output should be like 111.
function keep_track() {
STATIC $count = 0;
$count++;
print $count;
}
keep_track();
keep_track();
keep_track();
// output 123
I know that a static variable holds the value even after the function exits but in the above function I am assigning a value in the very first line, yet it still adding +1 with the previous value of $count.
Could you please explain this? (I am sorry if I sound like a stupid.. but I am trying to find out how exactly this happening)
$count is initialized only in first call of function and every time the method is called, it increments $count.
In this link, scroll down to Using static variables for a better understanding.
The code static $count = 0; is executed once upon compilation which is why with each call of your function the value is not overwritten. See the note "Static declarations are resolved in compile-time." at http://www.php.net/manual/en/language.variables.scope.php
This is probably very easy to do, but I can't seem to get my head around it right now. Let's say in a component in a cakephp application, I have a variable my_model, which contains the model of the corresponding controller that is currently using the component like:
function TestComponent extend Object
{
var $my_model; // can be either User, or Person
function test()
{
$myModelTemp = $this->my_model;
$model = $myModelTemp != 'User' ? $myModelTemp.'->User' : 'User';
$this->$model->find('all');
}
}
As you can see above in my function test() what I'm trying to do is call the correct model based on the value of my_model. So based on the condition, my query will be either:
$this->Person->User->find('all');
Or
$this->User->find('all');
When I do it like I did above, I get an error saying Fatal error: Call to a member function find() on a non-object. In order words, that error means Person->User is not an object (so, it is considered as a string).
What you're saying could be true, however, it can refer to any part of the call.
So either Person or User could be invalid, or together they causes the error. Hard to say.
Try dumping the individual objects using var_dump();
So try:
<?php
echo "<pre>";
var_dump(is_object($this->Person));
var_dump(is_object($this->User));
echo "</pre>";
?>
to determine where you're code goes wrong.
To be clear, that return value needs to be true for it to be an object.
The one that returns false is the likely culprit.
Should your question refer to the correct way to reference an object, an object is basically an array. For example:
<?php
$obj = (object) array("this", "my_function");
?>
The above example casts the array as an object. However, using multiple layers might prove to be more difficult than you'd expect.
Generally, it looks like you might be going about this all wrong. Obviously you want the models to be dynamic, but then you're hard-coding things which defeats the whole point of it being dynamic in the first place.
It also seems like you might be violating the principals of CakePHP and MVC by doing all this in a component. I'm not sure this component should really be manipulating models or assuming which models are currently in use.
However, if you want to evaluate a string as an actual object, you can wrap it in { ... } (this is valid standard PHP syntax, not Cake-specific code).
Try this:
$modelName = $this->my_model;
$model = ($modelName != 'User') ? $this->{$modelName}->User : $this->User;
$model->find('all');
Now, if this doesn't work or you get an error saying it can't find the model(s) you need to ensure the models are actually loaded and initialised in the current scope.
I have a page named ChangeApprovalInfo.php - It has a function called Row_Rendered as follows;
function Row_Rendered() {
// To view properties of field class, use:
//var_dump($this-><FieldName>);
$RecordOwner = $this->RequestUser->CurrentValue;
echo $RecordOwner;
}
Echoing $RecordOwner gets me the data I will need for a sql query on another page....
I have another page called ChangeApprovalEdit.php - This page has
<?php include_once "ChangeApprovalinfo.php" ?>
at the top of the file.
ChangeApprovalEdit.php has a function where I need the $RecordOwner variable as defined in ChangedApprovalInfo.php
If I add "echo $RecordOwner" on the ChangeApprovalEdit.php page, I get an error saying it's an unknown variable. My understanding is that I need to "make it global" or some such business. I know very little about PHP and the pages I am editing are long and complex. (to me, at least)
What do I need to do? I know that the information I have provided might not be enough to answer the question. I don't know enough to even know exactly what I need to ask. If more information is needed, I will edit and follow up.
pastebin of the files
ChangeApprovalInfo.php = http://pastebin.com/bSRM1wwN
ChangeApprovalEdit.php = http://pastebin.com/AStG9pqb
EDIT:
Changing Row_Rendered to this seems to be more effective. I'm having trouble seeing WHERE I can later echo this variable... but I'm getting somewhere with this...
function Row_Rendered() {
// To view properties of field class, use:
//var_dump($this-><FieldName>);
$GLOBALS['RecordOwner'] = $this->RequestUser->CurrentValue;
}
Don't echo variables from functions, which just outputs them to the standard output. return them from the function so you can use the value elsewhere as well.
function Row_Rendered() {
$RecordOwner = $this->RequestUser->CurrentValue;
return $RecordOwner;
}
Then instead of
$obj->Row_Rendered();
use
echo $obj->Row_Rendered();
and if you want to use the value elsewhere, use
$value = $obj->Row_Rendered();
You can do a couple of things:
First, you can return $RecordOwner from the function, and store its value in a variable. This method is usually preferred.
function Row_Rendered() {
// To view properties of field class, use:
//var_dump($this-><FieldName>);
$RecordOwner = $this->RequestUser->CurrentValue;
echo $RecordOwner;
return $RecordOwner;
}
// Store it in a variable when calling the function.
$RecordOwner = Row_Rendered();
Or, you can make it global inside the function:
function Row_Rendered() {
// To view properties of field class, use:
//var_dump($this-><FieldName>);
$GLOBALS['RecordOwner'] = $this->RequestUser->CurrentValue;
echo $GLOBALS['RecordOwner'];
}
You can use the $GLOBALS superglobals array, like this:
function Row_Rendered() {
$GLOBALS['RecordOwner'] = $this->RequestUser->CurrentValue;
}
However, you should not do that. Instead, refactor your application so that the view in ChangeApprovalinfo.php just contains a function, which is then called with the appropriate parameters.
EDIT: Chaning Row_Rendered to this seems to be more effective. I'm having trouble seeing WHERE I can later echo this variable... but I'm getting somewhere with this...
function Row_Rendered() {
// To view properties of field class, use:
//var_dump($this-><FieldName>);
$GLOBALS['RecordOwner'] = $this->RequestUser->CurrentValue;
}
I feel compelled to write another answer to this update. Let me demonstrate the use of globals as seen from outside that function:
$obj->Row_Rendered();
$obj->foobar();
echo $GLOBALS['RecordOwner'];
Quick, what will be echoed and where does that value come from? Well, it depends on what $obj-foobar() does. Maybe it changes the global variable. Maybe it doesn't. Who knows if the variable has been set at all? How would you trace back what happened exactly without adding a debug line after every single function call?
And that's just three lines of code. Imagine that in an application of any complexity.
Now, the same thing if I return the value from Row_Rendered:
$owner = $obj->Row_Rendered();
$obj->foobar();
echo $owner;
If the Row_Rendered method is behaving as it should (returning the owner), this code is very predictable. If you do not follow this pattern, you'll have a hell of a time getting anything done when the application grows to any halfway complex size.
Set the variable as global from within the function
$my_global_var = "old value";
function doing_stuff(){
global $my_global_var; //this will use the global variable instead of creating a local one
$my_global_var = "new value";
}
echo $my_global_var;//returns "new value"
would it be considered bad practice to return different types from the same method in php. Maybe there is a best pattern for this but essentially i want my method to do something and if it fails return a string error message but if it works then return true. This doesnt seem quite right to me but the only other way i can see to make this work would be to return a string for the error message and a string with something like 'worked' or 'valid' or something if all goes ok. Again this means there is more coupling beetween methods that use this as they cant just check true of false but the have to know the word that will be representing a valid response from the method.
If you are trying to monitor whether a function worked, you are best served by making use of Exceptions. As in all programming languages that provide them, these are indicative of "exceptional" cases outside the confines of expected program flow, and do not require any type of return to indicate something went wrong. See the associated documentation linked below for the PHP specifics.
PHP Exceptions
Assuming that you are referring to a method in a class, it would be better to simply return a TRUE or FALSE from the method but use an $_error property in the class that can contain an array of error messages.
Then if the result is false, before returning the method can set the error message(s) in the $_error property and you can retrieve the message using a get_error() method.
Well, you could return an array, I suppose - the first index would contain your boolean true/false, and the second index would contain more information if necessary.
You can certainly get away with it in PHP, but it might cause problems down the road. Esp when you or someone else has to maintain the app in the future. In general I'd recommend avoiding any approach like this that creates an ambiguity about whats in the variable.
One way to achieve what you are doing is to have the function return a result code or message, and have the actual value that gets returned sent back using referenced parameters.
ex:
$msg = MyFunc( $o);
if ($msg == 'OK') //or ($msg == 0)
{
//use the returned object or value
$o->Foo();
}
else
{
//respond to error
}
Returning true or anything else may be a good solution. Sometimes. I't may break if you decide to change returned values. Personally, I like it.
You could return an array. If it's empty, there was no error. Every error would be a separate item in array.
Besides, you may try to throw exception.
PHP is a loosely typed language, so it's pretty ordinary in the culture of PHP to return dissimilar types from functions.
For example, mysql_query() returns a resource on success and a boolean false on error. You test for the error state and then call another function like mysql_error() to get the specific information about the nature of the error.
$query = mysql_query($sql);
if ($query === false) {
die(mysql_error());
}
However, when writing OO code, I would be cautious about returning different unrelated object types from a function. It requires developers to write lots of tedious type-checking code:
$result = $search->find($keyword);
if ($result === null) {
// no entry matches $id
} elseif ($result instanceof ResultClass) {
// one row found; do something with the result
print $result;
} elseif ($result instanceof ResultCollection) {
foreach ($result as $element) {
print $element;
}
} else {
// are there other types for $result?
}
What a pain to write all that code every time you call find()!
The above example would be better if the find() method always returned a ResultCollection. If no results are found, the collection would have zero entries. If you can assume the function returns a given type consistently, your code is simpler:
$result = $search->find($keyword);
foreach ($result as $element) {
print $element;
}