Page 1 of 1

OO for sessions and db connection

Posted: Fri Dec 12, 2003 2:08 am
by lazy_yogi
With having to use session_start() exactly once, how would you work that into sessions used with classses.

For example, say you have a login() method in ur user class
So you have to call session_start() before setting session vars.

And say you have another method maybe in another class where u use session stuff - that may be called with or without the session login occuring before it. So since you can only have session_start() once, you don't know whether to call it here or not. Any way around this ?
Mmaye close the session_start() somehow so i can re-start it with each query.

Another problem is with db stuff. Do I have to close the connection for every query? It would be prefereable if I don't have to manually close it in the interface .. the class should take care of that itself. Is there a way around this problem ?

Cheers,
Eli

Posted: Fri Dec 12, 2003 9:24 am
by Weirdan
why not to use some flag in the session, say:

Code: Select all

if(isset($_SESSION["started"])&&$_SESSION["started"])
   //session already started, no need to start it here
 else{
   session_start();
   $_SESSION["started"]=true;
 }

Posted: Fri Dec 12, 2003 9:46 am
by aquila125
AFAIK mysql_connect closes it's connection automatically when the script ends, so no need for manual closure. mysql_pconnect makes use of a pooled connection and keeps the connection open..

Posted: Fri Dec 12, 2003 2:32 pm
by McGruff
Maybe you could make a CommonEnvironment class to encapsulate this or any other similar bits and pieces. The class would be called on every page request.

If you use a front controller design, you wind up with an obvious common "node" for all page requests where you can add stuff like initialising sessions.

Posted: Fri Dec 12, 2003 5:31 pm
by lazy_yogi
Weirdan wrote:why not to use some flag in the session, say:

Code: Select all

if(isset($_SESSION["started"])&&$_SESSION["started"])
   //session already started, no need to start it here
 else{
   session_start();
   $_SESSION["started"]=true;
 }
To see if the session_start() has been called this way, I would have had to use session_start() before checking it since you're checking session varibales to check if the session has been started. That's a circular problem. Unless I misunderstand what you're saying.


aquila125 wrote:AFAIK mysql_connect closes it's connection automatically when the script ends, so no need for manual closure. mysql_pconnect makes use of a pooled connection and keeps the connection open..
Yes this is true, but for the purity of OO design, I'd like to be able to closes the mysql connection when the object using the mysql object is deleted (which happens when the script ends).
And for writing unbreakable, correct code, I'd like to have the connection closed by my classes that use my mysql object when the object(that uses my mysql object) is not used anymore.
Ahhh ... mysql_pconnect looks great for creating just the one instance of the connection! Thanx for that. But then have to same problem of having to close the connection manually (which i wanna somehow do anyway) since pconnect doesn't auto close it when the script ends

McGruff wrote:Maybe you could make a CommonEnvironment class to encapsulate this or any other similar bits and pieces. The class would be called on every page request.

If you use a front controller design, you wind up with an obvious common "node" for all page requests where you can add stuff like initialising sessions.
This sounds interesting .. similar to what including a header with a global object would do .. (but thats proceedural and harder to read in the system, which I'm trying to steer clear of). Could you explain this a bit further and with some examples if you don't mind.

Thanx for all your input,
Eli

Posted: Fri Dec 12, 2003 5:52 pm
by Weirdan
lazy_yogi wrote:
Weirdan wrote:why not to use some flag in the session, say:

Code: Select all

if(isset($_SESSION["started"])&&$_SESSION["started"])
   //session already started, no need to start it here
 else{
   session_start();
   $_SESSION["started"]=true;
 }
To see if the session_start() has been called this way, I would have had to use session_start() before checking it since you're checking session varibales to check if the session has been started. That's a circular problem. Unless I misunderstand what you're saying.
If session_start has never been called then $_SESSION['started'] will not be set (but you still can test if it's set). If it's set - session is started. You can wrap this code in some function, say, my_session_start() to make sure the 'started' flag is always set on session start.

Posted: Fri Dec 12, 2003 6:18 pm
by lazy_yogi
Weirdan wrote: If session_start has never been called then $_SESSION['started'] will not be set (but you still can test if it's set). If it's set - session is started. You can wrap this code in some function, say, my_session_start() to make sure the 'started' flag is always set on session start.
Ah .... that's exactly what I need. Thanx!

That just leaves the db pconnect disconnect problem ...

Eli

Posted: Sat Dec 13, 2003 5:10 am
by lazy_yogi
Ok .. found the soln to both my problems if anyone is interested.

Firstly, the simplest way to only call session_start() once is

Code: Select all

if( !session_id() )
    session_start();

Secondly, the db disconnection issue.
In php5, classes will have destructors, but till that comes out you can just register a method using 'register_shutdown_function()', which registers a function for execution on shutdown (ie when the script ends). so to make it disconnect I will just do :

Code: Select all

class DB {
   function DB() {
       $this->host = "mysql.host.com";
       $this->db = "myDatabase";
       $this->user = "root";
       $this->pass = "mysql";
       $this->link = mysql_connect($this->host, $this->user, $this->pass);
       mysql_select_db($this->db);
       register_shutdown_function($this->close);
   }
   function close() {
       mysql_close($this->link);
   }
}
It's a hack, but it's a very very simple modification when php5 comes out soon .. just remove this :

Code: Select all

'register_shutdown_function($this->close);'
and put in this:

Code: Select all

function __destructor() {
    $this->close
 }
Eli

Posted: Sat Dec 13, 2003 8:30 pm
by lazy_yogi
Ok .. ran into a new problem with OO in php


I have my mysql wrapper class as a varable in my user class.
The mysql wrapper class works on its own in testing.

Here is the relavant part of the user class:

Code: Select all

include "class.mysql.php";
include "class.MyException.php";


class User {

    ### private: user parameters
    var $id;
    var $email;
    var $mysql; ### database connection for each 'User' class instance
    var $exceptions = array(); ### array of exceptions

    ### Constructor -  User::User()
    function User($id='') {

        ### if the id is an argument, try fill the attributes from db
        if ( !$id == '' ) {
            $this->id = $id;
            $this->validateID($this->id);
            if ( count($this->exceptions) > 0 ) return;
            $this->fillFromDB();
            if ( count($this->exceptions) > 0 ) return;
        }

        ### set a connection to the database 
        $this->mysql = new MySql();
    }

    ### fill all the fields of a user given an id -  User::fillFromDB()
    function fillFromDB() {

        ### validate pre-condition
        $this->mysql->query("SELECT * FROM user WHERE id='".$this->id."'");

    }
}
And this is where I get the problem: $this->mysql->query
There is a problem calling the query() method of the mysql objects which is an attribute of the User object.

Has anyone had this problem before ?
Is it a php problem ?


Eli

Posted: Sat Dec 13, 2003 8:49 pm
by McGruff
This sounds interesting .. similar to what including a header with a global object would do .. (but thats proceedural and harder to read in the system, which I'm trying to steer clear of). Could you explain this a bit further and with some examples if you don't mind.
Whether a "CommonEnvironment" class is a good idea depends on what code you've got to work with. In general, you don't want to overburden single classes with too many tasks, but on the other hand it might make sense: your call really. OOP allows you to encapsulate away to make whatever sorts of interfaces are useful to you, with the caveat that putting too much into one class makes code harder to re-use and debug. If you get this kind of "feel" from the code, a CommonEnvironment class might instead be made as a kind of controller class which instantiates a bunch of objects to carry out the individual tasks. Don't forget polymorphism - which can solve the problem of different needs on different pages. Polymorphic controller classes can be very powerful.

Some thoughts on front controller design here: viewtopic.php?t=15107

This basically builds every page in index.php. The top-level RequestManager class loads up all the other objects and hence is a common node. I think I might have mentioned loading common stuff in RequestManager but now I'm thinking that's more at home in the RequestHandlers.

A base handler class could store stuff common to all pages. that might be extended with module-specific handlers, and finally extended again with page-specific handlers where needed. The idea is to share code efficiently on pages which follow the same general plan at the same time as allowing pages to be customised if required.

Still a work in progress so treat as a possible source of ideas rather than a definitive text.

Good guide to OOP here: ftp://ftp.cs.orst.edu/pub/budd/oopintro ... /info.html

Posted: Mon Dec 15, 2003 1:20 am
by lazy_yogi
Does anyone have any information on my post 2 messages ago concerning accessing the method of and object which is an attribute of another object ?

$objA->objB_isAttributeOFObjA->methodOfObjB()

Eli

Posted: Mon Dec 15, 2003 4:56 am
by McGruff
That's fine - $this->object->method() works.

Posted: Mon Dec 15, 2003 7:34 am
by lazy_yogi
The would you mind taking a look at my code. It's not too complicated.

I have a mysql class which I've put as an attribute of the user class.
When I run test_user.php I get the error:

Code: Select all

Fatal error: Call to a member function on a non-object in c:\apache\htdocs\classes\class.user.php on line 172
And as far as I can see the problem lies in $obj1->obj2->obj2method()

The code is zipped up here :
http://cgi.cse.unsw.edu.au/~elip/phpstuff.zip

If you have the time, any help would be very much appreciated as I can't see any other reason for it not working.

Eli

Posted: Mon Dec 15, 2003 8:15 am
by McGruff
You'll get this error if you forget the $this (which you didn't) or if $this->mysql hasn't been instantiated (but it has) so I'm not sure what's happening.

What do you get if you print_r($this->mysql) in the constructor, immediately after instantiating the object?

Posted: Mon Dec 15, 2003 8:38 am
by lazy_yogi
Ahhhhhhhh.... you're right! It wasn't instantiated.
I called fillFromDB() just *before* instantiating the db object instead of just after.

Thanx very much for your help!

Cheers,
Eli