6

I have a PDO connection in my database class and recently I have been using this as an extension for other classes i.e. class Users extends Database this allows me to always keep a Database connection without having to have a function in my Users class.

However somebody pointed out that I shouldn't be doing this as its bad practice, why exactly is this bad practice? And how can I connect to my database class in my user class without extending?

Currently I have the call to the database inside my viewall() function I tried to put this in a __construct() function however it insisted on having parameters

I've tried the below code however I get the error message as follows:

Fatal error: Call to undefined method Database::prepare() in E:\xampp\htdocs\attendance\class.Register.php on line 13

Any ideas on how I can call on my database?

This is my code:

class.Connect.php

<?php // Database connection PDO class Database { public function __construct() { // Connection information $host = 'localhost'; $dbname = 'attendance'; $user = 'root'; $pass = ''; // Attempt DB connection try { $this->pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //echo 'Successfully connected to the database!'; } catch(PDOException $e) { echo $e->getMessage(); } } public function __destruct() { // Disconnect from DB $this->pdo = null; //echo 'Successfully disconnected from the database!'; } } ?> 

class.Register.php

<?php require 'class.Connect.php'; class Register { public function viewall() { $pdo = new Database(); $stmt = $pdo->prepare('SELECT * FROM users'); $stmt->execute(); $stmt->fetch(); } } $run = new Register(); $run->viewall(); ?> 
3
  • 7
    Is your user a database? No. Then why does it pass the test Users instanceof Database? If something is not something else, it shouldn't extend it. Commented Sep 17, 2013 at 14:58
  • 1
    Agreed with @deceze up to a point. However, it sounds like you're trying to build some kind of ORM, where you have classes that directly map to a given DB table. In this case, there may be merit in it, although semantically it would be better if it was extends DBTable or something, rather than extends Database. But if you are trying to write your own ORM, you might want to stop for a moment and consider using one of the exising libraries available (eg Doctrine) that already do this (and have already solved all the problems you're going to encounter as you write this). Commented Sep 17, 2013 at 15:03
  • "How can I connect to my database class in my user class without extending?" - have a look at dependency injection. Commented Sep 17, 2013 at 15:06

3 Answers 3

11

Simple rule of thumb: if a class extends another, then that class is that parent class (only slightly altered or extended). You can pass this child class instead of the parent class. Example:

class Foo { } class Bar extends Foo { } function baz(Foo $foo) { } baz(new Bar); 

This works, baz() expects a Foo but also accepts a Bar, because Bar is a Foo.

Now, is your Users a Database? No. Your users are not a database. Your users use a database. If at all, you should use composition:

class User { protected $database; public function __construct(Database $database) { $this->database = $database; } } 

A class should be what its responsibilities are. The responsibility of a user management class is to manage user data. Part of that may involve talking to a database, but that doesn't mean the user management class is a database. If User extends Database, that means it can do everything the Database class can do (and more). That means you could use the User class everywhere instead of the Database class, and that doesn't make any sense. Keep responsibilities separate.

Now, it's still debatable whether that is the right structure or not, but it goes into the right direction. But you may really want to have a User class, which represents one user. You then have a UserManager or UserORM or UserStorage or whatever, which is concerned with retrieving and storing User objects in a database. This class in turn uses a Database to do just that. That keeps responsibilities clear and separated. The User class represents user data, the Database class interacts with the database, the UserORM/Manager/whatever in the middle negotiates between the two.

Sign up to request clarification or add additional context in comments.

1 Comment

This site definitely needs to have a some sort of treasure to hold and promote this kind of excellent answers. Too bad, the very idea of the site forbids this :(
-1

There may be several ways to connect to a database such that you have a connection everywhere in your application. For a good practice, you can do it easily by using another class which can handle your datbase operations and you extend all your classes which require db operations from that class.

First change your Database class a little and pass the arguments for database connection as below :

<?php // Database connection PDO class Database { public function __construct($host, $dbname, $user, $pass) { // Connection information // Attempt DB connection try { $this->pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //echo 'Successfully connected to the database!'; } catch(PDOException $e) { echo $e->getMessage(); } } public function __destruct() { // Disconnect from DB $this->pdo = null; //echo 'Successfully disconnected from the database!'; } } ?> 

Now create another class lets call it ObjectModel as below

 class ObjectModel { protected $db public function __construct() { $this->db = new Database($host, $dbname, $user, $pass) //ofcourse you can get the db connections details and database name from a config file } // you can have more db operations functions like insert, update, delete etc } 

SO the ObjectModel class will be handling all your CRUDs and other db operations and running queries also. Now if you want to use the $db object, you can use it directly in the ObjectModel class and also in child classes of OBjectModel as below:

class Users extends ObjectModel { public function getUsers() { //$this->db-> whatever operation you want to do you can do it using this db object } } 

Remember that the ObjectModel has an object of the Database class called $db, so if your Database class is using PDO, then your ObjectModel $db object will have all those operations ie, using PDO.

I hope this will help for you also, as i am using such ObjectModel class for my classes and it saves me a lot of time to write codes again and again :) .

Happy Coding ;)

Comments

-1

Is extending classes good practice?

Well, yes, if you do it right and for the right reason.

The concept of inheritance (class extensions) in object-oriented programming is working like the same as if you had those objects in real world.

In real world when you use the world Car, then by convention you usually mean all the cars and you consider common attributes in it, for example, wheels, engine, steering, throttle, brake etc. but there are some cars that have those attributes and some additional too, for example a Fire Truck Car also has some extra attributes as a ladder attached, some tubes for water throwing etc. The same could be considered for the "behavior" of some objects, for example, a car can move, and by that we mean you have wheels rotation on the road in order to move (modeled by Car move method). Also, a firetruck may have an extended behavior, for example can move up and down the ladder it has. This can be modelled by having the method moveLadder() in the FireTruckCar class.

If you wanted to represent these concepts in PHP classes (OOP), you could do:

class Car { protected $wheels; protected $engine; //Rest attributes of Car. public function __construct($wheels, $engine) { $this->wheels = $wheels; $this->engine = $engine; //Initialize more attributes. } function move(){ $this->wheels->rotate(); } //..... } 

class FireTruckCar extends car{ //Additional Attributes. //The attributes of Car class belong to this //one too and are accessible as private. protected $ladder; protected $tubes; public function __construct($wheels, $engine, $ladder, $tubes) { //Call the parent constructor, to initialize parent attributes parent::__construct($wheels, $engine); $this->ladder = $ladder; $this->tubes = $tubes; } function moveLadder($direction){ $this->ladder->move($direction); } //... } 

Of course, there are many additional concepts in inheritance and generally OOP such as method overloading/overriding, abstract classed etc., but I am not goind to explain about them here as the point will be missed.I suggest you search for Object Oriented Programming Principles though and learn about them well.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.