#1
  1. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Posts
    4
    Rep Power
    0

    class inside class workaround?


    I'm developing a menu class, and in it, I want to use my sql wrapper, which is also a class. I quickly found out that I'm unable to call a class inside another class. It has been suggested that I tell my menu class to extend my sql class, but it makes no logical sense for a menu to extend a db.

    So my question is, are there any other ways to access my sql class's functions inside another class?

    Thanks.
  2. #2
  3. Moderator Emeritus
    Devshed Supreme Being (6500+ posts)

    Join Date
    Feb 2002
    Location
    Austin, TX
    Posts
    7,196
    Rep Power
    2268
    PHP Code:
    <?
         
    require_once("sql_class.php");
         
    $sql_class = new sql_class;

         class 
    menu_class
         
    {
              global 
    $sql_class;

              
    $sql_class->my_method($var);

         }
    ?>
    Does that make sense?

    First, include the .php file that contains your sql class.

    Instantiate the class by setting it to a variable.

    Call the variable w/in the next class.

    You can then access the methods w/in that class using the '->' pointer.
    DrGroove, Devshed Moderator | New to Devshed? Read the User Guide | Connect with me on LinkedIn
    The Most Important Article You Can Read as a Developer
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2003
    Location
    Norway
    Posts
    40
    Rep Power
    15
    Or you can pass the sql_class as an argument to the menu_class constructor :
    PHP Code:
    <?
    require_once("sql_class.php");
    $sql_class = new sql_class;

    class 
    menu_class
    {
      var 
    $sql_class;
      
      function 
    sql_class($sql_class)
      {
        
    $this->sql_class $sql_class;
      }

      
    $this->sql_class->my_method($var);

    ?>
  6. #4
  7. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Posts
    4
    Rep Power
    0
    Okay, thanks for your advice, still not working yet.

    Making the class var a global gives me a parse error, "Unexpected T_VARIALBE...." and what not. Not sure why that isn't working.

    Attempting to pass the sql_class as an argument to the constructor still gives me a "call to nonmember function" error. Is it a scope problem since i'm attempting to access the methods in a separate function? Also, if i'm making a constructor, shouldn't it be named the same of the class it's actually being made in?

    Here's my code:

    PHP Code:
     require_once('dbclass.php');

    $db = new db_class;

    class 
    hier_menu
    {
        var 
    $db;
            
        function 
    db_class($db)
        {
            
    $this->db $db;
        }
        

        
        function 
    get_nodeid($url)
        {
            
    $query "SELECT id FROM nodes WHERE url = '$url'";
            
    $this->db->query($query);
            
    $record $this->db->next_record();
            
    $nodeid $record[id];
            return 
    $nodeid;
        }

    Last edited by ZombyHero; July 23rd, 2003 at 08:51 PM.
  8. #5
  9. No Profile Picture
    Apprentice Deity
    Devshed Loyal (3000 - 3499 posts)

    Join Date
    Jul 1999
    Location
    Niagara Falls (On the wrong side of the gorge)
    Posts
    3,237
    Rep Power
    22
    I use a singleton object function to do what you are trying. Every class which requires an instance of the DB connection would call the function in the constructor. The function ensures that only one instance of the DB class exists but any other object can instantiate it.

    In the DB class file (DB.class.php):
    PHP Code:
    <?php

    function getDB($db)
    {
        static 
    $instance;
        if (isset(
    $instance) && is_a($instance,'DB')) 
        {
            return 
    $instance;
        }
        else 
        {
            
    $instance =& new DB;
            return 
    $instance;
        }
    }


    class 
    DB
    {
        ...
    // end class

    ?>
    In classes which need the DB class (FooBar.class.php):
    PHP Code:
    <?php

    require_once 'DB.class.php';

    class 
    FooBar
    {
        var 
    $db;        // instance of DB class

        
    function FooBar()
        {
            
    $this->db =& getDB();
        }
    }

    ?>
    No globals cluttering up the namespace either

    The only problem with this method is if you serialize and pass the object from page to page (either manually or via sessions) since the constructor wouldn't be called and the connection wouldn't be valid on subsequent pages which requires that you use __wakeup to reconstruct the object.
    Last edited by rod k; July 23rd, 2003 at 09:14 PM.
  10. #6
  11. Mobbing Gangster
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Sep 2001
    Location
    "Best City" 2002 and 2003- Melbourne, Australia
    Posts
    4,912
    Rep Power
    36
    Originally posted by rod k
    The only problem with this method is if you serialize and pass the object from page to page (either manually or via sessions) since the constructor wouldn't be called and the connection wouldn't be valid on subsequent pages which requires that you use __wakeup to reconstruct the object. [/B]
    kudos on that rod but there is one more problem thou - you're still using external function getDB(). IMO it's best if you get user to pass database class manually when initializing your class, and that's, IMO, where they should be applying singleton pattern.
    And you know I mean that.
  12. #7
  13. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Posts
    4
    Rep Power
    0
    Followed your method, rod, and I've stopped getting errors. Now calling my nodeid($url) function doesn't seem to yield any results. Not sure if its calling my db class right or not.

    One other question for now, though. In your above code, when you define "getDB", you specify the parameter ($db). Yet when its called later, no parameter is being passed. Should the $db in getDB($db) be there or not?

    Thanks.
  14. #8
  15. No Profile Picture
    Apprentice Deity
    Devshed Loyal (3000 - 3499 posts)

    Join Date
    Jul 1999
    Location
    Niagara Falls (On the wrong side of the gorge)
    Posts
    3,237
    Rep Power
    22
    still using external function getDB(). IMO it's best if you get user to pass database class manually
    Sorry, Al, but I don't agree. IMO, classes should be as autonomous as possible. Why require the user to do something that the class can do itself? By placing the function in the same file as the DB class, it's a no brainer.

    Why is calling an external UDF from within a class a bad thing? Do you place that same restriction on non-UDFs? Obviously not.

    Now calling my nodeid($url) function doesn't seem to yield any results
    There could be many reasons for that, place some strategic print statements inside the function starting with a print "got here"; exit; as the first line of the method to verify it is being called.

    Not sure if its calling my db class right or not.
    If it wasn't you would get an error about calling a method on a non-object or some such.

    Should the $db in getDB($db) be there or not?
    It should not for this example, good catch. That code was modified from some existing code that I use. For Postgres each connection is to a specific DB so that is a required parameter for the constructor. In the singleton function for that, $instance is actually an array that is indexed by the database being connected to:

    PHP Code:
    function getDB($db)
    {
        static 
    $instance=array();
        if (isset(
    $instance[$db]) && is_a($instance[$db],'DB')) 
        {
            return 
    $instance[$db];
        }
        else 
        {
            
    $instance[$db] =& new DB($db);
            return 
    $instance[$db];
        }

  16. #9
  17. Mobbing Gangster
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Sep 2001
    Location
    "Best City" 2002 and 2003- Melbourne, Australia
    Posts
    4,912
    Rep Power
    36
    Originally posted by rod k
    Why require the user to do something that the class can do itself? By placing the function in the same file as the DB class, it's a no brainer.
    When you put it that way, it's all good. I'm just too used to idea of having one class per file and nothing else, so don't particulary enjoy sticking extra function by side of class. But I suppose it's fine.
    Originally posted by rod k
    Why is calling an external UDF from within a class a bad thing? Do you place that same restriction on non-UDFs? Obviously not.
    True, and with your clarification I don't think it's a bad thing in this case. What I was saying before is that one should not used any of the global variables simple because they restrict freedom and modularity of class - how is final user supposed to know what variabe you're expecting to get from global environment? However, as you said before, if you just stick that function in the same file then it will be fine as it will be - relatively - part of the same class/include.
    And you know I mean that.
  18. #10
  19. No Profile Picture
    Apprentice Deity
    Devshed Loyal (3000 - 3499 posts)

    Join Date
    Jul 1999
    Location
    Niagara Falls (On the wrong side of the gorge)
    Posts
    3,237
    Rep Power
    22
    What I was saying before is that one should not used any of the global variables simple because they restrict freedom and modularity of class - how is final user supposed to know what variabe you're expecting to get from global environment?
    I'll agree with this statement. Globals use inside a class IS a bad thing and should be avoided.



    I'm just too used to idea of having one class per file and nothing else, so don't particulary enjoy sticking extra function by side of class.
    I used to think the same way. When I started using phpDocumentor I started thinking of classes as part of a package. And a package can include classes, constants and functions. The trick is to seeing the external function as part of the class even if it is external, because its existence is essential to the class itself. It's rare that a standalone function is a better choice than a method when using OOP, but as in my example, there are some things that only a function can do that make the whole thing more elegent.
  20. #11
  21. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Posts
    4
    Rep Power
    0
    Okay, thanks for your help everyone. I'm sure I'll get the code to work eventually

IMN logo majestic logo threadwatch logo seochat tools logo