mysqli, getting warning message that won't go away

I am using mysqli. I'm trying to update a user record. The update DOES succeed, but I am getting a slew of warning message for each and every single column involved in the update. Here is the code snippet which looks long, but the length is really irrelevant:

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_ALL); // Turn on Exceptions
    $sql = " UPDATE users " .
               "     SET username = ?, " .
               "	 password = ?, " .
               "         firstname = ?, " .
               "         middlename = ?, " .
               "         lastname = ?, " .
               "         address1 = ?, " .
               "         address2 = ?, " .
               "         city = ?, " .
               "         state = ?, " .
               "         zipcode = ?, " .
               "         phone1 = ?, " .
               "         phone2 = ?, " .
               "         email = ?, " .
               "         canHaveAppts = ?, " .
               "         eFiler = ?, " .
               "         apptColor = ?, " .
               "         notes = ?, " .
               "	 editdate = now(), " .
               "         editedbyid = ? " .
               " WHERE userid = ? ";
    
    $db = DB::getMYSQLIConnection();
    $stmt = $db->prepare($sql);
    $stmt->bind_param('sssssssssssssssisii', 
                      $u->username, $u->password, $u->firstname,
                      $u->middlename, $u->lastname, $u->address1,
                      $u->address2, $u->city, $u->state, $u->zipcode,
                      $u->phone1, $u->phone2, $u->email, $u->canHaveAppts,
                      $u->eFiler, $u->apptColor, $u->notes, $u->userid,
                      $u->userid);

    $retValue = $stmt->execute();
    if ($retValue === 0) {
        $message = 'From updateUser_mysqli(): FATAL ERROR! Updated FAILED! Call the Administrator. userid=' . $u->userid;
        throw new Exception($message);
    }

Open in new window


Here is the warning message I am getting for EACH AND EVERY column: (I am just showing the first few)

[08-May-2015 14:47:03 America/Los_Angeles] PHP Notice:  Indirect modification of overloaded property User::$username has no effect in C:\xampp\htdocs\newdimension\public\test\EEQuestion01.php on line 36

[08-May-2015 14:47:03 America/Los_Angeles] PHP Stack trace:

[08-May-2015 14:47:03 America/Los_Angeles] PHP   1. {main}() C:\xampp\htdocs\newdimension\public\test\EEQuestion01.php:0

[08-May-2015 14:47:03 America/Los_Angeles] PHP Notice:  Indirect modification of overloaded property User::$password has no effect in C:\xampp\htdocs\newdimension\public\test\EEQuestion01.php on line 36

[08-May-2015 14:47:03 America/Los_Angeles] PHP Stack trace:

... and so on ... for every single column, I get the same warning.

Open in new window


How do I get rid of this warning message? I googled this, actually saw a post from PHP site where the person who posted said this was a bug, but a responder said it wasn't. In short, I end up with no solution (see https://bugs.php.net/bug.php?id=40625). The last response was on 2013, so I'm hoping people have had time find a resolution to this?

Thanks.
elepilAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Dave BaldwinFixer of ProblemsCommented:
Where is the "$u->" coming from?
0
elepilAuthor Commented:
That's a User object that's already populated with data. The actual code where that was populated is:

    $u = getUserByUserId_mysqli(1);
    $u->firstname = 'John';
    echo $u; // This proves the User object was successfully populated
    
    $sql = " UPDATE users " .
               "     SET username = ?, " .
               "	 password = ?, " .
               "         firstname = ?, " .
               "         middlename = ?, " .
    ... etc ...

Open in new window

0
elepilAuthor Commented:
Dave, as it turns out, the solution was in that post, the one that says:

@martijn: Everything works fine, you just have to return from __get by reference (write &__get instead of just __get).

Open in new window


Here is the code for my User class and what I did to make it work. My comments are in UPPER CASE:

class User {
    protected $data = array();
    
    public function __construct() {
    }
    
    /* THIS USED TO BE JUST __get, BUT I ADDED AN AMPERSAND BEFORE IT, AND IT SEEMS TO STILL WORK, AND THE WARNING MESSAGES WENT AWAY, BUT I DON'T UNDERSTAND WHY. CAN YOU EXPLAIN WHY THIS HAD TO BE DONE? */
    public function &__get($name) {
        if (isset($this->data[$name])) {
            return $this->data[$name];
        } else {
            return false;
        }
    }
    
    public function __set($name, $value) {
        $this->data[$name] = $value;
    }
    
    public function __toString() {
        $output = '[userid=' . $this->userid . ']' .
                  '[username=' . $this->username . ']' .
                  '[password=' . $this->password . ']' .
                  '[firstname=' . $this->firstname . ']' .
                  '[middlename=' . $this->middlename . ']' .
                  '[lastname=' . $this->lastname . ']' .
                  '[address1=' . $this->address1 . ']' .
                  '[address2=' . $this->address2 . ']' .
                  '[city=' . $this->city . ']' .
                  '[state=' . $this->state . ']' .
                  '[zipcode=' . $this->zipcode . ']' .
                  '[phone1=' . $this->phone1 . ']' .
                  '[phone2=' . $this->phone2 . ']' .
                  '[email=' . $this->email . ']' .
                  '[canHaveAppts=' . $this->canHaveAppts . ']' .
                  '[eFiler=' . $this->eFiler . ']' .
                  '[apptColor=' . $this->apptColor . ']' .
                  '[deletable=' . $this->deletable . ']' .
                  '[notes=' . $this->notes . ']' .
                  '[editdate=' . $this->editdate . ']' .
                  '[editedbyid=' . $this->editedbyid . ']' .
                  '[deleted=' . $this->deleted . ']' . '<br/>';
        
        return $output;
    }
}

Open in new window


I have never, in all the programming languages I've used, have to turn a function name into a reference, i.e., from __get to &__get. Do you know why this had to be done?
0
Acronis Data Cloud 7.8 Enhances Cyber Protection

A closer look at five essential enhancements that benefit end-users and help MSPs take their cloud data protection business further.

Dave BaldwinFixer of ProblemsCommented:
Sorry, I got nothing for you on this.  You're using functions that I've never used or even seen.
0
elepilAuthor Commented:
When you say I'm using functions that you've never used or even seen, what are you referring to? Are you talking about __get and __set?

If you're referring to getUserByUserId_mysqli(), that's just a function I created to facilitate getting a User object. Other than that, what other function can you be referring to?
0
Ray PaseurCommented:
I've never seen any PHP code like this.  What are you trying to do?  Maybe we can suggest a mainstream solution if we understand the objectives.
0
elepilAuthor Commented:
Hmm... I assume what both you and Dave are claiming unfamiliarity to are the __get and __set functions? They're PHP magic functions, in the same family with __construct, __destruct, __clone, __call, etc.

PHP magic functions are functions that are invoked based on an event. For example, __construct will only be invoked if you instantiate a new class with 'new'. In the case of __get and __set, they are invoked if a non-existent property in a class is accessed or when a non-existent property is being attempted to be set, respectively. If you look in my User class, notice there is only one protected property, i.e., an array called data. So when anything external tries to access a property in my class that is NOT explicitly  declared nor defined, or if anything external tries to set a value to a property that is NOT explicitly declared nor defined, the __get and __set functions are invoked instead. If you look at the code within those two functions, all they're doing is just managing an array called 'data', saving property names and values in it. So if you try to do a $user->username = "John", since there is no property called $username inside the class, the __set function takes over and all it does is $this->data['username'] = 'John';. And when you later try to access the 'username' property, since it is not explicitly defined within the class, the __get takes over, and all it does is return $this->data['username'];. See how beautifully it works? :)

Doing it this way saves you a lot of time from having to create individual getters and setters for every single property. This kind of class is also mandatory if you want to make use of PHP's ability to instantiate and populate a class after reading a row from the database -- all automatically done for you. Remember when I told you how PHP, due to how long it has been around, has accumulated a lot of features that save work for the programmer? This is one of the big ones that made me like PHP.

My code is working fine now, and the warning messages are gone. But I'm still befuddled why it took an ampersand in front of the __get to make the warnings disappear. That's like making a function name a reference, something I've never seen done on functions but only on variables. PHP can be such a strange animal.
0
Ray PaseurCommented:
Yes, PHP is "strange" sometimes.  But maybe if you can tell us in plain, non-technical language what you're trying to do, maybe we can save you a lot of time and effort.  We have dealt with this strangeness before and we no longer waste our time on the strange parts -- we just choose the good parts and move on to the good solutions!
0
elepilAuthor Commented:
Ray, I already said the application is now working, the warning messages are gone. If you read my last response to you, my question is now about how the ampersand preceding the __get rectified the problem. I ask this because I just want to try to understand how PHP works internally.
0
Ray PaseurCommented:
I think we're familiar with __get() and __set().  I don't rely on the magic methods very much, but I've explored active record designs and fluent interfaces a bit.  Sometimes the magic methods can be helpful there.  But in my experience it's better to know what you're doing rather than letting foreign code inject variables into your scope.

See if this article helps.  In some languages all arguments are passed by reference, but PHP is different, and some arguments are passed by reference while others are copied and passed as explicit values.  The difference is significant!
http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/A_12310-PHP-Variables-and-References.html

FWIW, I tried to find mainstream examples that used the ampersand on a magic method call, and it seems like nobody does that.  What I think is happening is this:  The script needs to read a variable in order to determine what to return.  The variable it needs to read is passed by reference, not by value.  The "read" part of this may be obscured by the syntax of the source code, such as making a reference to an array element.

Here's what I would like you to do.  Please set up the SSCCE that demonstrates the problem.  It has to exist in isolation, without database references, etc, so that we can copy the code, install it on our own servers and run it exactly as written to get the error messages you see.  Then we can take it apart and annotate the issues with comments.  As it stands now, I can't figure out how to get the error messages you're seeing, and I don't have your database, so I need you to set up the isolated test case for us.  I'll check back later.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
elepilAuthor Commented:
Thanks for responding.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.