0

I have this code:

class Service {
    public function get_session($token) {
        foreach ($this->config->sessions as $session) {
            if ($token == $session->token) {
                $session->last_access = date('r');
                return $session;
            }
        }
        return null;
    }
    public function mysql_connect($token, $host, $username, $password, $db) {
        if (!$this->valid_token($token)) {
            throw new Exception("Access Denied: Invalid Token");
        }
        // will throw exception if invalid
        $this->mysql_create_connection($host, $username, $password, $db);
        $session = $this->get_session($token);
        $id = uniqid('res_');
        if (!isset($session->mysql)) {
            $session->mysql = new stdClass();
        }
        $mysql = &$session->mysql;
        $mysql->$id = array(
            'host' => $host,
            'user' => $username,
            'pass' => $password,
            'name' => $db
        );
        return $id;
    }
    public function mysql_close($token, $res_id) {
        if (!$this->valid_token($token)) {
            throw new Exception("Access Denied: Invalid Token");
        }
        $session = $this->get_session($token);
        if (!(isset($session->mysql->$res_id))) {
            throw new Exception("Invalid resource id");
        }
        unset($session->mysql->$res_id);
        if (empty((array)$session->mysql)) {
            unset($session->mysql); // this don't work, don't know why
            throw new Exception('isset($session->mysql) == ' .
                                (isset($session->mysql) ? 'true' : 'false'));
        }
    }
}

I call unset($session->mysql); if it's empty but the object is not removed, the exception throw true, How can I delete $session->mysql object? I've tried to add & in get_session but this didn't help.

Whole code can be found here.

Clay
  • 4,700
  • 3
  • 33
  • 49
jcubic
  • 61,973
  • 54
  • 229
  • 402
  • 2
    `unset($session->mysql->$res_id);` this is wrong. It might be part of your problem it should be: `unset($session->mysql->res_id);` – Dan Jan 05 '16 at 22:37
  • 1
    @dan08 it's dynamic variable `$res_id` hold real variable name, this part work. – jcubic Jan 05 '16 at 22:38
  • 1
    I don't get these `function mysql_connect($token, $host, $username, $password, $db)` - `mysql_create_connection($host, $username, $password, $db)` - `mysql_` connection uses 3 parameters (the 4th is for something else) and you seem to be trying to use a custom function called `mysql_connect()` which is a core PHP function (that should be throwing an error about it). Or am I missing something here; am I making a fool of myself with this comment? (lol). Just say the word and I'll delete this. – Funk Forty Niner Jan 05 '16 at 22:44
  • 2
    Please [stop using `mysql_*` functions](http://stackoverflow.com/questions/12859942/why-shouldnt-i-use-mysql-functions-in-php). [These extensions](http://php.net/manual/en/migration70.removed-exts-sapis.php) have been removed in PHP 7. Learn about [prepared](http://en.wikipedia.org/wiki/Prepared_statement) statements for [PDO](http://php.net/manual/en/pdo.prepared-statements.php) and [MySQLi](http://php.net/manual/en/mysqli.quickstart.prepared-statements.php) and consider using PDO, [it's really pretty easy](http://jayblanchard.net/demystifying_php_pdo.html). – Jay Blanchard Jan 05 '16 at 22:46
  • 2
    You should `var_dump($session)` to check gain some insight into whats happening to the object – Dan Jan 05 '16 at 22:47
  • $session->mysql = null; ? – E_p Jan 05 '16 at 22:47
  • @JayBlanchard I'm not using mysql_ I'm using mysqli object, that part is irrelevant so I left the code out. – jcubic Jan 05 '16 at 22:48
  • @Fred-ii- `mysql_connect` it's not a function it's a method of Service object. – jcubic Jan 05 '16 at 22:49
  • A minimal example works as expected: http://codepad.viper-7.com/Ka0IwJ Are you getting the exception when you expect the faulty `unset()` to run? – Jared Farrish Jan 05 '16 at 22:52
  • @jcubic Fair enough. Now, this `'isset($session->mysql) == ' .` that is inside single quotes and TBH, not entirely sure if that is also contributing here, since variables won't get parsed in single quotes. – Funk Forty Niner Jan 05 '16 at 22:57
  • @Fred-ii- They're not supposed to be parsed, that's part of the message in the exception. – Barmar Jan 05 '16 at 22:58
  • @Fred-ii- He calls `isset()` for real on the line after that. – Barmar Jan 05 '16 at 22:59
  • @Barmar after reading that again, I noticed. My mistake. – Funk Forty Niner Jan 05 '16 at 23:00
  • 1
    Next time please do not link to your repos and include the code in your post instead... – Clay Jan 05 '16 at 23:22

1 Answers1

6

You really should have posted your Session class in your post instead of linking to your GitHub repo... that's why the comments are confusing. You are using magic methods on your session class.

1 change I made: adding the magic __unset method.

Also, I had thought the constructor needed to be public but on further looking at it I was wrong about that (so my test code will not work unless the constructor is public... anyway...).

Here is the code below with the updated class:

<?
class Session {
    public $storage;
    public $token;
    public $username;
    public $browser;
    public $start;
    public $last_access;
    private function __construct($u, $t, $s = null, $b = null, $d = null) {
        $this->storage = $s ? $s : new stdClass();
        $this->username = $u;
        $this->token = $t;
        $this->browser = $b ? $b : $_SERVER['HTTP_USER_AGENT'];
        $this->start = $d ? $d : date('r');
    }
    function &__get($name) {
        return $this->storage->$name;
    }
    function __set($name, $value) {
        $this->storage->$name = $value;
    }
    function __isset($name) {
        return isset($this->storage->$name);
    }
    function __unset($name) {
        echo "Unsetting $name";
        unset($this->storage->$name);
    }
    static function create_sessions($sessions) {
        $result = array();
        foreach ($sessions as $session) {
            $result[] = new Session($session->username,
                                    $session->token,
                                    $session->storage,
                                    $session->browser,
                                    $session->start);
        }
        return $result;
    }
    static function cast($stdClass) {
        $storage = $stdClass->storage ? $stdClass->storage : new stdClass();
        return new Session($stdClass->username,
                           $stdClass->token,
                           $storage,
                           $stdClass->browser,
                           $stdClass->start);
    }
    static function new_session($username) {
        return new Session($username, token());
    }
}

And some test code:

$session = new Session('joe', '1234');
$session->mysql = 1234;
var_dump($session->mysql);
unset($session->mysql);
var_dump($session->mysql);

This is code of the added method:

function __unset($name) {
    echo "Unsetting $name";
    unset($this->storage->$name);
}

Check out the documentation to about the magic __unset method you need to add to your class:

http://php.net/manual/en/language.oop5.overloading.php#object.unset

__unset() is invoked when unset() is used on inaccessible properties.

Clay
  • 4,700
  • 3
  • 33
  • 49