Page 1 of 1

Unexistent variable between two PHP classes

Posted: Wed Jun 02, 2004 4:58 pm
by Guilherme Blanco
During the last 2 weeks, I've been creating a user management system to help me in all my projects.
I decided to build it in the easiest way to use, and I published one of the two classes I made in PHPClasses.

In the UserManager class, in the login method, I made some string checks and if the user is found, I registrate a "session".

* NOTE: The other class is to manipulate (read as emulate) sessions and cookies.

I used the arguments as the same way as setcookie() function does. You registrate a "session value" by sending its name. Detailing more:

$username = "Guilherme Blanco";
$argument = "username";

So, $$argument = "Guilherme Blanco";

So, in the function I use "username" to relate the content and the name of the $username variable, BUT in PHP this has 3 problems (that I can list):

- Global access doesn't refer to the parent class variables, only the global ones and also return me an empty string (should return me a warning, that the variable isn't set). Question: Does exist any way to refer it?

- Using a simple class, and global variable, the global works properly... when sending an array as argument, in the global $$argument;, I have a warning (array to string conversion). Question: Any hack available to work around with it?


My original intention is to store the key/value as in the same way as assigned them in the script escope. For example... If I want to store in a "session" the key/value $username = "Guilherme Blanco", I'll have something like this:

$_SESS['username'] = "Guilherme Blanco";

* Note: $_SESS is an array I created.

Trying to be more specific: How can I get the key name, without send the pair (key/value)?
In PEAR, they suggest to send this: ("username" => "Guilherme Blanco"). My intention is to use only "username" and I can recover the "Guilherme Blanco" inside the function.

I'm trying to solve it in the last 3 days... I didn't find a solution yet. If anyone has another suggestion (that follow my wishes (erm, I mean... that I don't have to send the pair key/value)), I'll apreciate.


For those interested, here is the piece of code that I have the problem:

Code: Select all

function setSessionValue()
    {
        // This function can set an array (no serialized) as the session values
        // or can set multiple values independent. All arguments should be send
        // as a string value (even when they're arrays). This will in the same
        // way as PHP does in cookie registration
        $num_args = func_num_args();
        // I have the number of arguments being send
        if ($num_args == 0) {
            // No value to insert, so return false
            return FALSE;
        } else {
            // Get the previous session variables in the table
            $aValues = $this->getSessionValues();
            if (!$aValues) { $aValues = array(); }
            // I'll insert each variable/array I find in the newSessValues
            // array, then I serialize it and try to insert when I have no more
            // arguments that the function sent me
            $newSessValues = $aValues;
            for ($i = 0; $i < $num_args; $i++) {
                $arg = func_get_arg($i);
                // Checking if the variable exists in the source code
                // Return FALSE (bug in the source) is I don't find it
                global $$arg;
                if (!isset($$arg)) {
                    // The variable doesn't exist; so, return FALSE
                    return FALSE;
                }
                // Checking if the argument is an array or a simple variable
                if (is_array($$arg)) {
                    // I'll merge the arrays. If arrays have the same string
                    // keys, then the later value for that key will overwrite
                    // the previous one. This also do the "update" session
                    $newSessValues = array_merge($newSessValues, $$arg);
                } else {
                    // I'll add the variable in my already existent session
                    // values. Ths also do the "update" if I found any item
                    // with the same name inside my session variables
                    $newSessValues[$arg] = $$arg;
                }
            }
            // Preparing the array to be inserted in the table
            $newSessValues = addslashes(serialize($newSessValues));
        }

        // Putting in the table OLD and NEW values
        $query = "UPDATE sessHandler SET sValues='".($newSessValues)."' WHERE sHashId = '".($this->_hash)."' AND sSessId = '".($this->_session)."'";
        $result = ($this->_linkId != NULL) ? mysql_query($query, $this->_linkId) : mysql_query($query);
        // If the insertion runned okay (I mean, happened wihout any problem),
        // I should return TRUE; otherwise, return FALSE
        $rows = ($this->_linkId != NULL) ? mysql_affected_rows($this->_linkId) : mysql_affected_rows();
        if ($rows > 0) {
            return TRUE;
        } else {
            return FALSE;
        }
    }


Thanks in advance,

Posted: Wed Jun 02, 2004 5:07 pm
by feyd
$$arg is looking for a name of a variable.. if you pass an array, you need to use $arg instead.

Posted: Wed Jun 02, 2004 5:16 pm
by Guilherme Blanco
A friend sent me one link... the array to string conversion is a known bug in PHP, since 2001.

Another report have been posted in 2003. Here is the link: http://bugs.php.net/bug.php?id=25692

Still trying to solve the others problems... :?

Posted: Wed Jun 02, 2004 8:36 pm
by markl999
The bug you link to above isn't a bug :o
The guy is trying to make an array element global, which of course you can't do.
If he had done use_global ('ary'); instead, all would have been well.

Posted: Wed Jun 02, 2004 8:54 pm
by McGruff
The code is not very clear.

Excessive comments are one bad sign - good code doesn't need much commenting.

Using "global" is always bad. You really don't want anything in the global scope in an OOP design.

I'd recommend refactoring into separate methods with around 6/7 lines in each. Each function (and class) should do just one thing. This forces you into a clearer understanding of what you are trying to do. With that, many problems simply melt away.

Posted: Wed Jun 02, 2004 9:32 pm
by Guilherme Blanco
Sorry...

I created a hack one hour ago and forgot to post that I solved it here.
It worked well... =)

mark999
I tryed it, but when I did it, I'm trying to grab a local variable inside other class, not a variable in a global escope.
So, this doesn't work to me.

McGruff
I have a little problem... I forget the things I program 2 or 3 days after I did it. Sometimes I forget what I did, and have to look at it some time before recontinue. That's why I comment everything... when I finish the class, I remove some comments, and leave only the necessary ones.
Thanks for the tips of OOP. I reoved something that I use in more than one place, but I never split one function into more than one.
I create classes to a specific job. I don't create classes to one method. This is a UserManager class, that has register, delete, update, login, logout, and isLoggedIn methods.
To manipulate the sessions, I use AuthManager, that has getSessionValue, setSessionValue, ...
In my point of view, I'm following the OOP idea. I'm assigning all the methods and properties inside a class to it work alone and that correspond to its behavior and styling. Correct me if I'm wrong.



My solution came with this idea:

I assign the variables before add them in a "session":

Code: Select all

$username = $user["username"]'
//...
$tmp->setSessionValues("username", ...);
So, instead of define variables in the child class, I'll define them in an array in the parent one. Then I can access this array everywhere, just using the right the methods. The code changed to this:

Code: Select all

$tmp->setValueToAdd("username", $user["username"]);
//...
$tmp->setSessionValues("username", ...);

This solved my problem...


This is the only place that I posted the bug that you surely assume something. I liked this community and I'll be here when I have a free time to help the others too.
I was admin of a Brazilian Webboard, but I have to leave my position because I've been working a lot.


Thanks again.

Posted: Wed Jun 02, 2004 10:27 pm
by McGruff
Guilherme Blanco wrote: I have a little problem... I forget the things I program 2 or 3 days after I did it. Sometimes I forget what I did, and have to look at it some time before recontinue. That's why I comment everything...
The comments don't really explain what's going on. I can guarantee that that even you, the author, will have problems if you have to come back to this in six months time.

Tightly focussed class methods help a lot in that regard. Eclipse is an excellent example of lean and mean classes - exactly the kind of thing I meant by one class, one task. A more modular design is much easier to update as well as being easier to read.

It's very important to keep refactoring until classes (and methods) do just one thing. Build up layers of classes calling other classes if you have to.

Some interesting reading here: http://www.phppatterns.com.[/url]