PHP OOP- Object Interaction - php

I am currently working in PHP and have begun to utilise classes- I am learning a lot, however I am yet to have my "penny drop" moment- I am struggling with object interaction.
I'd really appreciate some clarification in regards to how one object should interact with another. As a very basic example if I have a database object which handles connecting and querying a database, how should other classes access the results of queries performed by the database object?
From my understanding so far, I can see 2 options. Either the query results within the database class are accessible publicly and are passed to other objects as arguments...
$databaseObject = new DatabaseObject;
$databaseObject->query("query goes here");
$newObject = randomObject;
$newObject->doStuff($databaseObject->query())
Or objects which rely on query results instantiate new database objects within themselves and therefore the results are contained within that object.
class databaseConnection {
public $queryResults;
function __construct {
connect to database...
}
function query {
perform queries...
$this->queryResults = query results
}
}
class NewObject
{
function doStuff() {
$db = new databaseConnection
do stuff with $db->queryResults
}
}
Option 1 seems wrong as properties in the database class are available globally, whereas option 2 seems to contradict the idea that classes should only hold methods and properties relating to the object they define.
I could think of many other examples. If I create a class responsible for managing a user throughout a system, yet classes responsible for other tasks need to know what privilege level a user has, do I make that property within the user class global and pass it to other classes? Do the other classes instantiate new user objects?
Any help much appreciated.

Either the query results within the database class are accessible publicly
This (for me) is the key to the answer. If you set or change a value in the instance, this rather implies that you want to set the value in the underlying dataset (although you might consider defering the write). Note that the magic methods allow you to associate actions with get and set operations implicitly. But not every query is updateable. If your sql is baked in, then you can determine the updatability at design time.
Also, I suggest that your query object has a set of record objects associated with it where you interact with the underlying data. Bundling the connection functionality in the same object as the query only really makes sense if it is a factory (supporting multiple queries) and creating query result objects. And the query (result) object should probably implement the iterator interface.
Both pdo and mysqli seperate the connection, query and results into seperate objects - for good reason.

class Connection {
public static $conn;
public static function getInstance() {
if (!self::$conn) {
self::$conn = new Connection();
}
return self::$conn;
}
public function query() {
echo "run your query here using self::\$conn object";
}
}
class Person {
public function doStuff() {
$conn = Connection::getInstance();
$results = $conn->query();
}
}
$person = new Person();
$person->doStuff();
Firstly, you want to get your database connection only one time rather then opening it every time.
Secondly, using the same database connection object you can run multiple queries as shown in the above example.
You will always get a single connection no matter how many other classes you use.

Related

Should a PHP user class extend a database class?

I am not sure if this is totally the wrong thing to do, so I am looking for a bit of advice.
I have set up a database class with the constructor establishing a PDO connection to a MySQL database.
I've been looking at singletons and global variables, but there always seems to be someone who recommends against either/or.
I'm experimenting with a user class which extends the database class, so I can call upon the PDO functions/methods but maintain separate user class code. Is this a stupid thing to do?
You should generally pass a connection into your user, so your user class would take a database type object into its constructor and then use that database object to execute queries against the database. That way your data access logic remains separate from your business logic. This is called composition, as opposed to what you're talking about, which is inhertance.
If you really wanted to be technical, it would be best to have a user object with nothing but public variables, and then you would use a 'service' to implement your business logic.
class UserService implements IUserService
{
private $_db;
function __construct(IDb $db) {
$this->_db = db;
}
function GetAllUsers() {
$users = Array();
$result = $this->_db->Query("select * from user")
foreach($result as $user) {
//Would resolve this into your user domain object here
users[] = $user;
}
return users;
}
}
Well, ask yourself if User is a special case of Database. I'm not sure how others perceive it, but I would be kind of offended. I think what you need is to read about the Liskov substitution principle.
As for solving your "people tell me that globals are bad" issue, here are two videos you should watch:
The Clean Code Talks - Don't Look For Things!
The Clean Code Talks - Global State and Singletons
The idea behind class extensions in OOP is for child classes to be related to the parent classes. For instance, a school might have a Person class with extension classes of Faculty and Students. Both of the child classes are people, so it makes sense for them to extend the Person class. But a User is not a type of Database, so some people might get upset if you make it an extension.
Personally, I would send the database object as an argument to the User class in the constructor and simply assign that object to a class property. For instance:
class User
{
protected $db;
function __construct($username, $password, $db)
{
//some code...
$this->db = $db;
}
}
Alternatively, though some might yell at you for it, you can use the global keyword to inherit a variable in the global scope for use within your methods. The downside is that you would then have to declare it global in every method that needs it, or you could do:
class User
{
protected $db;
function __construct($username, $password)
{
global $db;
//some code...
$this->db = $db;
}
}
But in answer to your question, no I don't think you should make User an extension of Database; even though it would do what you need, it isn't a proper OOP practice.
It is pretty simple according to the definition of an object. It is the encapsulation of data and the operation which is performed on that data so if we only consider the theoretical point of view it would leads us in pleasurable environment.
My suggestion would be to create an abstract data access class with the generalized basic crud operations and a simple query execution using either PDO, ADO or some other database abstraction library. Now use this class as a parent for most of your model classes like the User.
Now the basic CRUD is provided by the abstract data access class and you can write the behavior specific to the user object like getting all posts for the user by consuming the simple query interface of the abstract parent class.
This approach will bring more modularity in term of coupling functionality and more readability and reuse-ability.
I don't see anything wrong with it for specific cases. You could use it for something as simple as wrapping a user's DB credentials in an object so they don't have to specify them everywhere the DB object is used.
$db = new UserDB();
would be a bit nicer than
$db = new StandarDB($username, $password, $default_db);

How to access the database class in OOP?

So I know that questions with 'what is the best' in their title aren't supposed to be asked, but really.. how should you do this?
We have a database class and, for example, a user class. A user class will get methods such as create() and update(), which will need to do database stuff.
As far as I know there are 2 main options, passing on the database object in every __construct() or make the database class static.
(Any other tips about OOP + database driven websites are also appreciated)
A very common pattern here is to make the database class a singleton construct, which is then passed to every object constructor (that is called Dependency Injection).
The purpose of making the database object a singleton is to ensure that only one connection is made per page load. If you need multiple connections for some reason, you would want to do it a different way. It's important to pass it via the constructors though, rather than creating the database object inside an unrelated class so that you can more easily test and debug your code.
// Basic singleton pattern for DB class
class DB
{
// Connection is a static property
private static $connection;
// Constructor is a private method so the class can't be directly instantiated with `new`
private function __construct() {}
// A private connect() method connects to your database and returns the connection object/resource
private static function connect() {
// use PDO, or MySQLi
$conn = new mysqli(...);
// Error checking, etc
return $conn;
}
// Static method retrieves existing connection or creates a new one if it doesn't exist
// via the connect() method
public static function get_connection() {
if (!self::$connection) {
self::$connection = self::connect();
// This could even call new mysqli() or new PDO() directly and skip the connect() method
// self::$connection = new mysqli(...);
}
return self::$connection;
}
}
class Other_Class
{
// accepts a DB in constructor
public function __construct($database) {
//stuff
}
}
// Database is created by calling the static method get_connetion()
$db = DB::get_connection();
$otherclass = new Other_Class($db);
// Later, to retrieve the connection again, if you don't use the variable $db
// calling DB::get_connection() returns the same connection as before since it already exists
$otherclass2 = new Other_Class(DB::get_connection());
Another method is to create your database class directly extending either mysqli or PDO. In that case, the __construct() method supplies the object to getConnect(), as in
public static function get_connection() {
if (!self::$connection) {
self::$connection = new self(/* params to constructor */);
}
return self::$connection;
}
Well, what you can do is to have the database access layer in one object, which is then passed to your objects, respecting the inversion of control pattern.
If you want to dig a bit into this direction, have a look into dependency injection (DI): http://en.wikipedia.org/wiki/Dependency_injection
Having a singleton is usually a bad idea as you will end up having problems when testing your code.
Having the database access logic within a model class such as User violates the separation of concerns principle. Usually DAO (Data Access Object) handles db related concerns.
There are ORM frameworks such as Hibernate, which handle mismatch between OO and relational models quite well, potentially saving a lot of manual work.
I'm really surprised that no one said this, but here it goes: ORM.
If your weapon of choice is PHP, then the major options are Propel and Doctrine. They both have many strengths and some weaknesses, but there's no doubt that they're powerfull. Just an example, from Propel's (my personal favourite) user manual:
// retrieve a record from a database
$book = BookQuery::create()->findPK(123);
// modify. Don't worry about escaping
$book->setName('Don\'t be Hax0red!');
// persist the modification to the database
$book->save();
$books = BookQuery::create() // retrieve all books...
->filterByPublishYear(2009) // ... published in 2009
->orderByTitle() // ... ordered by title
->joinWith('Book.Author') // ... with their author
->find();
foreach($books as $book) {
echo $book->getAuthor()->getFullName();
}
You won't get more OO than that!
They will handle a lot of things for you like for one, abstracting your data from the database vendor. That said, you should be able to move (relatively painlessly) from MySQL to SQL Server and if you're building your own tools for web applications, then beign able to adapt to different environments is a very important thing.
Hope I can help!
Hey have a look at ORM's. Let them do the hard work for you? fluent nhibernate or microsofts entity framework.
I could be misunderstanding your question. Sorry if so

How should I use my database class in other class?

I have one database wrapper class. How should I use this class object to execute query in other class?
$liveresellerdb=new Database('host','user','spswd','db');
$fetch = $liveresellerdb->getResult($select_resellerData);
How should I include the database object in my one class?
Class one
{
function a (){
$sql="select * from table ";
//how should i execute here my query i mean to say
//every time i can't create the new object
// i want to know the good method by which i just execute the query by
// giving the database name
}
}
I'd advise against the Singleton pattern (using static members is a variation of this pattern) and use Dependency Injection instead. This means that you pass the database object to your service (the class that uses the connection) through the constructor.
Here is an example.
class UserFinder
{
private $db;
public function __construct(Database $db)
{
$this->db = $db;
}
public function findAllActive()
{
$sql = 'SELECT * FROM users WHERE active = 1';
return $this->db->executeAndFetchAll($sql);
}
}
$db = new Database($host, ...);
$finder = new UserFinder($db);
$users = $finder->findAllActive();
This ensures that you are not bound to a specific implementation of the Database class (you could make a sub-class) and will allow you to create separate UserFinders with separate Database instances. It will also make it easier to write tests for your application because you have less dependencies, which are not hidden and also replaceable.
In short: Use dependency injection.
Since global variables are dirty (you always need the global $var; statement), the easiest solution is to store them in a static member of a class, e.g. Database::$db.
Another solution (in a proper OOP environment) would be passing the database instance to the classes - in your code it would be the constructor of one which accepted the instance and then stored in a private member variable.
Maybe, you should think about implementing your Database class according to a Singleton Pattern.
Updated (according to comment below):
Ok. I have only one suggestion here (except passing object via method's parameters and Dependency Injection, described in igorw's comment)...
Dependency Injection is a good way, but this case you - I suppose - have some small amount of databases, so it can be better to save them all in some static private array and get by keys.
So you will have only one public static method getInstance($key) and keys can be stored as some predefined constants (to avoid "spelling" errors).
This way you don't require initialization at all (getInstance($key) can create new Database objects with necessary parameters [passed to constructor] depending on the $key parameter). Dependency Injection looks better in general, but in some particular cases this way can be easier-to-use.
Could be ok to have a Db setAdapter method that store database connections in a static property by name:
Db::setAdapter('db1', 'mysql:host=localhost;dbname=' . $dbname, $user, $pass);
Db::setAdapter('db2', 'mysql:host=localhost;dbname=' . $dbname2, $user2, $pass2);
Then a getAdapter method that will return a database connection when needed:
Db::getAdapter(); // return the default one
Db::getAdapter('db2'); // return an instance by its name
Behind the scenes you could implement a lazy connection too.

Pass MySQL connection to function

I am trying to set up a MySQL connection in a main script, and then call various functions depending on what I want to do. I am having trouble passing the connection information to the function.
I have a class "queries" which contains various functions, all which return an array. This is what the code looks like in my main script (calling function normal)
$mysqli = new mysqli($db_host, $db_user, $db_pass, $db_name) or die (mysql_error());
$stats = $queries->normal($mysqli);
And then inside of the queries resource, I have this code:
class queries {
function normal($mysqli) {
$query = "SELECT number, first, last FROM roster";
$roster = $mysqli->query($query);
Then I proceed to do what I need. I cannot get this to work though. I get the error
Call to a member function normal() on a non-object
on the line that I call the function in my main file.
This is similar to these questions, but I can't quite figure it out.
Passing database connection by reference in PHP
Ensuring MySQL connection works in PHP function
Thank you
$queries is not an object, much less a queries object. Figure out what you assigned to it instead, and assign the right thing to it :)
Ahh, I think I get it now. queries is a class, not an object. You need to make an object that is an instance of the class.
$queries_obj = new queries;
$queries_obj->normal($mysqli);
"Call to a member function normal() on a non-object" means that you are trying to call normal() on a variable that is not an object. Probably you meant to do this:
$queries = new queries();
$stats = $queries->normal($mysqli);
Think of your class definition as a recipe and the object as the actual dish you made using that recipe.
As stated by others, you likely haven't instantiated (created) an object of that class.
I would really not recommend structuring your code like this. Passing around the mysql connection can make your function signatures incredibly cluttered. Two other options are:
Singleton Pattern: Encapsulate your database interaction functions into a single class, and then every time you need to call one of them, you grab an instance of that class. What's nice about this method is that you always get the same db connection, instead of opening many request. If you're not using heavy OO (lots of procedural php, or lots of global functions), this is really helpful. For example:
public function foo() {
$results = Db::getInstance()->query("SELECT * FROM bar");
// Do other stuff
return $results;
}
Inheritance: This pattern is really helpful if you're working in something like MVC, or you need to have objects share functionality. Combined with a singleton, you keep a single db connection per request, and the easy access of the db instance in a member variable.
class DB {
public function __construct() {
$this->conn = Db::getInstance();
}
}
class Foo extends DB {
public function foo() {
$this->conn->query("SELECT * FROM bar");
}
}
Whilst i could agree that passing database handlers around in methods/functions isn't probably the best idea, it's not dirty to pass database objects through to classes via the constructor, especially if you have multiple connections.

factory class in PHP, no __construct? What method names do I use?

I have a factory class I'm making in PHP. Each instance represents a row from a database table.
Since I'll be dealing with dozens of database rows, it would be silly to have each instance do a select on instantiation. So I have a method to just dump values in to the object, for use in conjunction with a database query that returns a lot of rows.
But from time to time, I'll also want to have the object look up all the values in a query. So, I'll have another method that takes the primary key as an argument, and looks up the values from a database query.
So it seems that between these two methods, I won't really need a __construct method.
Is there a name for this type of pattern, more specific than 'factory'? What should I call these two different methods for constructing the object -- are there commonly used names for these methods?
I think the pattern you have is somewhat similar to the table data gateway.
Since it needs access to the database, I would recommend giving it a constructor. You can pass the constructor the database object (eg. PDO if you use it, or others), so the class does not need to know how to connect to the database.
Otherwise your idea seems good.
Maybe you need a DAO storage class in addition to your data class?
<?php
class Row {
private $fields1;
private $fields2;
__construct($field1, $field2) {
$this->fields1 = $fields1;
$this->fields2 = $fields2;
}
}
class Storage {
public load($id) {
$rawRow; // loaded from db
return $this->createRow($rawRow);
}
protected createRow(array $rawRow) {
return new Row($rawRow['fields1'], $rawRow['fields2']);
}
}
?>

Categories