473,708 Members | 2,387 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

PHP OO - How to use a class within another class?

88 New Member
Hi,

Im just learning OO in PHP and not sure the best method to use the functions for example in a database wrapper class within another class for example which handles all user authentication. I have put together this test code of how I am currently implementing it:

Expand|Select|Wrap|Line Numbers
  1. <?
  2. class DB
  3. {
  4.   public function __construct($host,$user,$pass,$dbname)
  5.   {
  6.     mysql_connect($host,$user,$pass)
  7.       or die(mysql_error());
  8.     mysql_select_db($dbname)
  9.       or die(mysql_error());
  10.   }
  11.   public function qry($sql)
  12.   {
  13.     return mysql_query($sql)
  14.       or die(mysql_error());
  15.   }
  16. }
  17.  
  18. class User
  19. {
  20.   public $user_id;
  21.   public function __construct($user_id)
  22.   {
  23.     $this->user_id = $user_id;
  24.   }
  25.   public function update_user()
  26.   {
  27.     global $db;
  28.     $db->qry(" UPDATE users SET active = 1 
  29.       WHERE user_id = '" . $this->user_id . "' ");
  30.   }
  31. }
  32.  
  33. $db   = new DB("localhost","root","","test_database");
  34. $user = new User(2);
  35.  
  36. $user->update_user();
  37. ?>
Is that use of global considered bad practice? I was browsing the source of PHPBB3 and they use the global method when accessing its database class from other classes however I believe I can instead pass a reference to the object via a param so would that method be better? If someone could give me a few pointers it would be appreciated.

Cheers.
Apr 4 '09 #1
8 22905
Markus
6,050 Recognized Expert Expert
Have a database property for your User class.

Expand|Select|Wrap|Line Numbers
  1.  
  2. class DB {
  3.  
  4.    // ...
  5.  
  6. }
  7.  
  8. class User { 
  9.  
  10.     private $_db;
  11.  
  12.     public function User ( ) 
  13.     {
  14.         $this->_db = new DB;
  15.     }
  16.  
  17. }
Apr 5 '09 #2
hoopy
88 New Member
Hi Markus,

Thanks for the response, however I do have a question.

The __construct() for the DB class opens the connection from the login parameters passed. Therefore with your method I need to have the login details hard coded into the USER class itself rather than in the code which creates the instances.

Is this the standard practice for using classes within classes? Can you see my problem and advise of a possible workaround?

Thanks.
Apr 5 '09 #3
Dormilich
8,658 Recognized Expert Moderator Expert
a common practice for DB classes is implementing the Singleton pattern (which can also hold the DB access data (maybe coded through constants)

the User class doesn't need to pass DB data, unless you want to (be able to) connect to different databases.
Apr 5 '09 #4
hoopy
88 New Member
Thanks Dormilich.

I checked out about the Singleton pattern, follows some tutorials and came up with this which works well in that it only calls the database connection once and I can use that class within any other classes, here is my example code:

Expand|Select|Wrap|Line Numbers
  1. <?
  2. class DB
  3. {
  4.   private static $dbInstance;
  5.  
  6.   public function __construct($host,$user,$pass,$dbname)
  7.   {
  8.     echo("Would have connected to " . $host . " DB.<br />");
  9.   }
  10.  
  11.   public static function getInstance($host=null,$user=null,
  12.     $pass=null,$dbname=null)
  13.   {
  14.     if (!self::$dbInstance)
  15.     {
  16.       self::$dbInstance = new DB($host,$user,$pass,$dbname);
  17.     }
  18.     return self::$dbInstance;
  19.   }
  20.  
  21.   public function qry($sql)
  22.   {
  23.     echo("Would have executed: " . $sql . "<br />");
  24.   }
  25. }
  26.  
  27. class User
  28. {
  29.   private $db;
  30.   public function __construct()
  31.   {
  32.     $this->db = DB::getInstance();
  33.   }
  34.   public function SelectUsers()
  35.   {
  36.     $this->db->qry(" select * from users ");
  37.   }
  38. }
  39.  
  40. class News
  41. {
  42.   private $db;
  43.   public function __construct()
  44.   {
  45.     $this->db = DB::getInstance();
  46.   }
  47.   public function SelectNews()
  48.   {
  49.     $this->db->qry("select * from news");
  50.   }
  51. }
  52.  
  53. $dbc = DB::getInstance("localhost", "root", "", "test_database");
  54. $usr = new User();
  55. $usr->SelectUsers();
  56. $usr->SelectUsers();
  57. $nws = new News();
  58. $nws->SelectNews();
  59. $usr->SelectUsers();
  60. ?>
This will produce the following output:

Expand|Select|Wrap|Line Numbers
  1. Would have connected to localhost DB.
  2. Would have executed: select * from users
  3. Would have executed: select * from users
  4. Would have executed: select * from news
  5. Would have executed: select * from users 
So you can see it only connects once which is great and I dont need to provide DB login details within any of the classes.

Thanks for everyones help.

Cheers.
Apr 6 '09 #5
Dormilich
8,658 Recognized Expert Moderator Expert
[EDIT] Unfortunately, you got the Singleton Pattern wrong. what about
Expand|Select|Wrap|Line Numbers
  1. $a = new DB(…);
  2. $b = new DB(…);
?

you must leave the __construct() and __clone() methods empty in a Singleton pattern! (OK, you may throw an Exception or leave a note)

you can also try to pass the DB parameters via static properties.

Expand|Select|Wrap|Line Numbers
  1. require "db.config.php";
  2.  
  3. class DB
  4. {
  5.   private static $dbInstance = NULL;
  6.   public static $host;
  7. // or using a default value via constants
  8. // public static $host = DB_DEFAULT_HOST;
  9.   public static $user;
  10.   public static $pass;
  11.   public static $dbname;
  12.  
  13.   public function __construct()  {  }
  14.  
  15.   public function __clone()  {  }
  16.  
  17.   public static function getInstance()
  18.   {
  19.     if (self::$dbInstance === NULL)
  20.     {
  21.       self::$dbInstance = new self;
  22.       self::connect();
  23.     }
  24.     return self::$dbInstance;
  25.   }
  26.  
  27.   private static function connect()
  28.   {
  29.     # do DB connection here
  30.   }
  31. }
  32.  
  33. // optional if you use your defaults
  34. DB::$host = "localhost";
  35. DB::$user = "****";
  36. DB::$pass = "****";
  37. DB::$dbname = "my_db_name";
  38. $dbc = DB::getInstance();
  39.  
Apr 6 '09 #6
hoopy
88 New Member
Dormilich, thanks for that clarification.

I have implemented what you desribed and its working fine.

Thank you.
Apr 7 '09 #7
Dormilich
8,658 Recognized Expert Moderator Expert
I'm glad I could be of help.

OOP rulez.

@Dormilich
incorrect, but I noticed that way too late.
Apr 7 '09 #8
Dormilich
8,658 Recognized Expert Moderator Expert
just for additional information a Singleton like DB class using PDO

Expand|Select|Wrap|Line Numbers
  1. // used for connecting to MySQL
  2. // stores the Prepared Statements
  3.                              (the interface, so that all DB_User classes 
  4.                               can safely call the methods)
  5. abstract class DB implements DB_connector
  6. {
  7.     /* PDO instance */
  8.     private static $PDO = NULL;
  9.  
  10.     /* collection of Prepared Statements */
  11.     private static $PS = array();
  12.  
  13.     /* DB name to set up */
  14.     public static $dbname = DB_DEFAULT_NAME;
  15.  
  16.     /* close DB connection on script end */
  17.     function __destruct()
  18.     {
  19.         self::$PDO = NULL;
  20.     }
  21.  
  22.     /* create a single instance of PDO */
  23.     public static function connect()
  24.     {
  25.         if (self::$PDO === NULL)
  26.         {
  27.             try {
  28.                 // server, login & password hardly ever change in a project
  29.                 $dsn = 'mysql:host=' . DB_SERVER . ';dbname=' . self::$dbname;
  30.                 self::$PDO = new PDO($dsn, DB_USER, DB_PASS);
  31.             }
  32.             catch (PDOException $pdo)
  33.             {
  34.                 // any kind of error logging*
  35.                 ErrorLog::logException($pdo);
  36.  
  37.                 // throw Exception so you can safely quit the script
  38.                 $emsg = "MySQL connection failed.";
  39.                 throw new ErrorException($emsg, 500, 0);
  40.             }
  41.         }
  42.     }
  43.  
  44.     /* save the Prepared Statements. I prefer to have them where the
  45.        PDO object is. just personal preference */
  46.     public static function prepare($index, $sql)
  47.     {
  48.         # check if $index already exists (implement your own way)
  49.  
  50.         self::connect();
  51.  
  52.         try {
  53.             self::$PS[$index] = self::$PDO->prepare($sql);
  54.         }
  55.         catch (PDOException $pdo)
  56.         {
  57.             ErrorLog::logException($pdo);
  58.             return false;
  59.         }
  60.         return true;
  61.     }
  62.  
  63.     /* since the Prepared Statements are private, a getter method */
  64.     public static function getStatement($index)
  65.     {
  66.         if (isset(self::$PS[$index]))
  67.         {
  68.             return self::$PS[$index];
  69.         }
  70.  
  71.         // do some error handling here
  72.     }
  73. }
  74.  
  75. * ErrorLog is an Abstract Registry Pattern class that collects caught 
  76.   Exceptions (and is able to display them later)
Apr 7 '09 #9

Sign in to post your reply or Sign up for a free account.

Similar topics

3
2144
by: Dave | last post by:
I have a Solution with two projects. I am trying to reference a class in project2 from project1. When I right click on the project1 references (in Solutions explorer)and attempt to add a reference, I get the add reference window, I click on Project tab and browse to my solution/project folder and then to the project2.exe. However, I recieve an error ... seems like it is looking for a file with a dll extenstion. I'm a rookie at this...
15
17574
by: Guenther Sohler | last post by:
This is probably very easy to answer but for me its new. Yesterday I realized the need to be able to define a class within another one. So I have written some test code and its almost syntax error free. My first goal is to count the Outer classes with a global variable, which works fine But then I want to count the Inner classes within the Outer class. The Varibale innernum is global in repsect to the Class Inner, but I dont know how...
2
274
by: uvts_cvs | last post by:
template <class T> class foo { public: template <class Tin> T bar (Tin) {return T();} };
4
2718
by: Stephen Corey | last post by:
I've got 2 classes in 2 seperate header files, but within the same namespace. If I use a line like: // This code is inside Class2's header file Class1 *newitem = new Class1(param1, param2); I get "syntax error: identifier" and "undeclared identifier". Since they're in the same namespace, and even in the same project, do I need
2
7408
by: Craig Buchanan | last post by:
If I declare a class within another class like: Class ParentClass ... Class ChildClass ... End Class End Class How do I reference a property in the ParentClass in the ChildClass? If the
2
1262
by: Billy | last post by:
In .Net 2, when I have created a strongly typed dataset of a SQL table and then 'viewed' the code from the RHM menu. I am taken to the new partial class; as expected, but why do I have a partial class within a partial? plus if I was to inherit an interface then what partial class should I place the interface on, the outer partial class or the inner partial class? Regards Billy
2
1695
by: Gman | last post by:
Hi, I have created a usercontrol, a grid control essentially. Within it I have a class: clsGridRecord. I have coded the events such that when a user clicks on the grid, say, the events occur on the parent form. This is fine. The problem occurs when I want to raise an event for a user clicking on one of the clsRecords which are on the grid. So I've placed: Public Event GridRecordClicked(ByVal rec As clsGridRecord,
3
2276
by: Nick Valeontis | last post by:
Hi to all! I am writing an implentation of the a-star algorithm in c#. My message is going to be a little bit long, but this is in order to be as specific as possible. My question has nothing to do with the algorithm. It is related to OOP in c#. I have created a class named astar.cs. An instance of the class among other, contains a instance of a class named Input to store the input parameters of the algorithm and an instance of a...
7
2145
nathj
by: nathj | last post by:
Hi, I have a data abstraction class that holds all the functions for query the database. I now have a second class that holds all the functions for writing specific data to the database. The class definitions are all in the same php file and I need to use the first class within the second. On the page where the functions of the second class are used I have instantiated both classes however, when I try to use the functions of the...
0
8787
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9289
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9158
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9001
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7921
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5939
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4712
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3151
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2508
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.