I would like to know where is the best place to set my db object with my model.
Should I hard coded it since my model should be designed for one project, so i set it inside my constructor or wherever i do initialization ?
or
Should I pass my db object to my constructor when instancing my object ?
What is the best way, i mean from experimented users, and efficient that'll give me more confort to use ?
Couple of things:
Most PHP projects that utilize a database connection represent that database using a Singleton pattern, if you aren't sure what this is, read up on it.
Typically I define my database connections in a configuration file which can easily be changed between environments (development, stage, production).
I'll then instantiate my database connection in a bootstrap file using the aforementioned Singleton pattern and configuration file.
My models will typically completely abstract the database/table data store, for each model I'll do something like this:
bootstrap.php
$config = load_config_data(ENVIRONMENT);
Db::setDefaultAdapter($config['database']);
Model/Table/User.php
class Table_User extends Db_Table
{
// Table name
protected $_name = 'user';
/* Do a bunch of database specific stuff */
}
Model/User.php
class User extends Model
{
public function updateUsername($userid, $username)
{
// Uses default adapter, Singleton pattern!
$table = Db::loadTable('user');
$table->update(
array('username'=>$username),
Db::quoteInto('userid = ?', $userid)
);
}
}
This is pretty much an introduction to the Model in the Zend Framework MVC, I would check it out for some ideas on how to organize your code (or save yourself some trouble and actually use the framework.)
For testability, you should pass it into the constructor rather than hard coding it. This helps you to write unit test because you can mock your DB object.
I would not hard code it, even if the code is never used for another project simply moving from a test database to a live database may require locating and changing the code in the model class. That would be far better placed in some kind of configuration file.
Personally, I would have the db object defined in whatever you use as a bootstrap - and then have the model(s) use that single object.
Related
I'm building a web application that needs to be able to write data to either a mysql db or an xml file, depending on the online status of the application.
In my model, I have a super class (Dao is data access object)...
abstract class Dao {
static function getInstance($online_status) {
if $online_status = 'online' {
return new DaoMySQL;
} else {
return new DaoXML;
}
}
abstract function dao_select();
abstract function dao_insert();
abstract function dao_update();
abstract function dao_delete();
}
Now, here is the part I'm confused about. I have a domain model/entity class that selects the appropriate Dao using:
$this->dao = Dao::getInstance($online_status);
So, now I have the correct data access object selected. But, the problem is I still two implementations of dao_select() and the other functions. Now, the main implementations are in the respective classes DaoMySQL and DaoXML, but dao_select() in each of those classes require different things. i.e. the DaoMySQL version needs two parameters, $table and $where_statement. DaoXML (which I haven't implemented) will need the element name, and maybe another argument, I don't know.
So, in my domain model class, after calling
$this->dao = Dao::getInstance($online_status);
is this where I need to include two separate local implementations (pertaining to the domain model/entity class only) of dao_select(), or this wrong? It just seems like I'm taking the elegance out of the process by doing something like this:
class EntityModel {
$this->dao = Dao::getInstance($online_status);
if($this->dao->type = 'mysql') {
$result = $this->dao->dao_select($table, $where);
} else {
$result = $this->dao->dao_select($xml_params);
}
}
I feel like I'm taking the simplicity out of the system... Does this approach make sense, or is there a better one?
You are doing it wrong.
Few notes to begin with:
in OOP the extends statement signifies is a relationship. Which means that, while class Duck extends Bird is all fine, writing class User extends Table is NOT.
in MVC the Model is not a class or an instance of a class. Instead it is a layer of application, mostly made of two types of elements:
domain objects: containing domain business rules and logic
data access structures: usually datamapper dealing with storage and retrieval of information
I would argue, that the third significant part of Model layer are services. But there are options on whether it is part-of or above Model.
Currently what you are trying to do is forcing a ActiveRecord (which is fine for small things, but as project grows, it becomes a burden on architecture .. which is what you are face with now) patterns to work with dynamic data sources. And to do so you are resorting to procedural calls.
Anyway, the point is that you should inject your DAO instance into your Domain Objects (what you calls "models"). And you should leave the creating of your DAO to a separate factory instance, which would be responsible for initializing them and providing them with data source (instance of PDO or file path). This way you can, not only separate the responsibilities, but also swap the storage destination "on fly".
To learn more you should investigate what is dependency injection. Here are few video that might help:
Don't Look For Things!
Global State and Singletons
I'm building a class to handle Paypal IPNs as part of a project, and since I already know i'm going to need to use it again in at least two more upcoming jobs - I want to make sure I structure it in a way that will allow me to re-use it without having to recode the class - I just want to have to handle changes in the business logic.
The first part of the question is re. interfaces. I haven't quite grasped their usefulness and when/where to deploy them. If I have my class file ("class.paypal-ipn.php"), do I implement the interface in that file?
Here's what i'm working with so far (the function list is incomplete but its just for illustration):
CLASS.PAYPAL-IPN-BASE.PHP
interface ipn_interface {
//Database Functions
// Actual queries should come from a project-specific business logic class
// so that this class is reusable.
public function getDatabaseConnection();
public function setDatabaseVars($host="localhost",$user="root",$password="",$db="mydb");
public function dbQuery($SQL);
//Logging Functions
public function writeLog($logMessage);
public function dumpLogToDatabase();
public function dumpLogToEmail();
public function dumpLogToFile();
//Business Logic Functions
private function getTransaction($transactionID);
//Misc Functions
public function terminate();
}
class paypal_ipn_base {
//nothing to do with business logic here.
public function getDatabaseConnection() {
}
public function setDatabaseVars($host="localhost",$user="root",$password="",$db="mydb") {
}
public function dbQuery($SQL) {
}
}
CLASS.PAYPAL-IPN.PHP
final class paypal_ipn extends paypal_ipn_base implements ipn_interface {
//business logic specific to each project here
private function getTransaction($transactionID) {
$SQL = "SELECT stuff FROM table";
$QRY = this->dbQuery($SQL);
//turn the specific project related stuff into something generic
return $generic_stuff; //to be handled by the base class again.
}
}
Usage
In this project:
Require the class files for both the base, and the business logic class.
Instatiate *paypal_ipn*
Write code
In other projects:
Copy over the base IPN class
Edit/rewrite the business logic class *paypal_ipn* within the constraints of the interface.
Instantiate *paypal_ipn*
Write code
So as you can see i'm literally just using it to define groups of related functions and add comments. It makes it easier to read, but of what (if any) other benefit is it to me - is it so that I can pull the extender and the base class together and force errors if something is missing?
stdClass Question
The second part of the question is building on the readability aspect. Within the class itself there is an ever increasing number of stored variables, some are set in the constructor, some by other functions - they relate to things such as holding the database connection vars (and the connection resource itself), whether the code should run in test mode, the settings for logging and the log itself, and so on...
I had started to just build them as per usual (again, below incomplete & for illustration):
$this->dbConnection = false;
$this->dbHost = "";
$this->dbUser = "";
$this->enableLogging = true;
$this->sendLogByEmail = true;
$this->sendLogTo = "user#domain.com";
But then I figured that the ever growing list could do with some structure, so I adapted it to:
$this->database->connection = false;
$this->database->host = "";
$this->database->user = "";
$this->logging->enable = true;
$this->logging->sendByEmail = true;
$this->logging->emailTo = "user#domain.com";
Which gives me a much easier to read list of variables when I dump the entire class out as I code & test.
Once complete, I then plan to write a project specific extension to the generic class where i'll keep the actual SQL for the queries - as from one project to another, Paypal's IPN procedure and logic won't change - but each project's database structure will, so an extention to the class will sanitize everything back into a single format, so the base class doesn't have to worry about it and will never need to change once written.
So all in all just a sanity check - before I go too far down this road, does it seem like the right approach?
if you are using a class autoloader, which I highly recommend, you would not want to keep the interface and the class in the same file so that the interface can autoload without needing to first load this one class that implements it.
For more info on autoloading:
http://php.net/manual/en/language.oop5.autoload.php
another thing you may want to consider is that a given class may impliment multiple interfaces, and multiple classes may implement the same interface.
interfaces are primarily used for various design patterns, to enforce rules, and to decouple a class from any dependent classes. when you decouple a class from its dependencies, it makes it much easier to modify code at a later time.
for instance, let's say you have a class A that takes in another class B as an argument, and this class is spread throughout your code. you want to enforce that only a class with a specific subset of methods can be accepted as this argument, but you do not want to limit the input to one concrete class and it's decendants. in the future, you may write an entirely different class that does not extend class B, but would be useful as an input for class A. this is why you would use an interface. it is a reusable contract between classes.
some would argue that since PHP is a dynamic language, interfaces are an unecessary complication, and that duck typing may be used instead. I find in large multi-user code bases however, that interfaces can save a lot of time, letting you know more about how one class uses another, without having to study the code in depth.
if you find yourself with a large list of variables that you have to pass around between objects or functions, they often do end up deserving a class of their own, but each case is different.
-- dependency injection example --
class A implements AInterface {
public function foo($some_var) {}
}
interface AInterface {
public function foo($some_var);
}
class B {
protected $localProperty;
// inject into the constructer. usually used if the object is saved in a property and used throughout the class
public function __construct(AInterface $a_object) {
$this->localProperty = $a_object;
}
// inject into a method. usually used if the object is only needed for this particular method
public function someMethod(AInterface $a_object) {
$a_object->foo('some_var');
}
}
you can now see that you can write another class that impliments a foo method (and the AInterface) and use that within class B as well.
as a real world example (used often), say you have a database class with particular methods that interact with the database (getRecord, deleteRecord). now lets say at a later time you find a reason to switch database rdbms. you now need to use entirely different SQL statements to accomplish the same goals, but since you used an interface for your type hinting, you can simply create a new class that impliments that interface, but impliments those same methods in entirely different ways as it interacts with a different rdbms. when creating this new class, you will know exactly what methods need to be written for this new class in order to fit into the same objects that need to use a database object. if you use a container class that you use to create objects and inject them into other objects, you would not need to change too much application code in order to switch databases classes, and therefore switch database rdbms. you could even use a factory class, which could limit your changes to one line of code to make this type of change (in theory).
I'm fairly new to OOP PHP and am having trouble with getting a couple of classes to work nicely together. I'm using a database abstract class to do all the grunt work of talking to the database and that is all fine, and I can extend it with another class with the methods to make specific actions. The database class has an include_once to read in the config settings for the database.
Where I am confused is if I need to use a 2nd class to access the database on the same page, I need to reference a 2nd config file that has the same settings.
Example: I have a products class for a site I'm building and it is working fine. I wanted to use a 2nd class to control the actual shopping cart side of things, but when I try and extend the database class with the Cart class the page fails unless I override which config file it needs to reference.
Why do I need separate config files for each class and is there a way around this? It seems silly that I should need as many config files as there are classes that interact with the database.
Thanks for your help.
Jon
* Extra Info *
Sorry guys, Everything is in the same database. Here is some sample code.
All config files are like this:
$DB_HOST = "localhost";
$DB_USER = "abcdef";
$DB_PASS = "123456";
$DB_DATABASE = "newdb_name";
then I override the config file which it needs to pull in but doing this in the sub classes:
function __construct()
{
$this->conffile = "db_conf1.php";
parent::__construct();
}
and change the $this->conffile for each new sub class.
I'm using a database abstract class to do all the grunt work of talking to the database and that is all fine, and I can extend it with another class with the methods to make specific actions. The database class has an include_once to read in the config settings for the database.
This is a bad design. If you need to use two of these classes together in the same script, you're going to end up w--
Where I am confused is if I need to use a 2nd class to access the database on the same page
Phew, you got it already.
You generally only want one database connection per page. This generally means only one database object. You have two good options in PHP to deal with this.
The first has a fancy name: "Dependency Injection." In DI, your objects require some external resource to work. They receive this resource during construction.
In other words, you pass your database object in the constructor.
class Foo {
protected $db;
public function __construct($other, $args, $db) {
$this->db = $db;
}
}
This way, you still get the convenience of referencing the database from within your object without having to make it too intermingled.
The other option also has a fancy name: the "Registry Pattern." Registries act as gateways to "well-known" classes and instances. They're basically look-up tables, allowing you to make your program depend on data that will be present in the Registry rather than hard-coding class names or using globals.
Or, in other words, it's just a global hash with a special name.
Doing it right requires a class. This blog post from 2009 is an interesting starting point because it deals exactly with the problem of what to do with a database adapter. I'll omit example code here, as the blog post does a decent job of explaining itself.
There is a third option, of course, and it's the worst, yet most common in PHP land: assigning the database object to a global, then referencing the global as needed. It's quick, it's dirty, it usually works... but can make maintenance difficult, and can make automated testing impossible to do correctly. Don't do it.
You should remove the dependency on the config file from the database class and pass the variables you need into the database constructor e.g.,
class Database {
public function __construct($host, $user, $pass, $dbname, $port) {
// create connection
}
//...
}
Put the info for both your databases into one config file and create your database objects like this:
include_once 'config.php';
$db1 = new Database($host1, $user1, $pass1, $dbname1, $port1);
$db2 = new Database($host2, $user2, $pass2, $dbname2, $port2);
I've seen how powerful OOP is in c++ so I started reading up on OOP for PHP. This made me want to revamp one of my sites so it would use OOP PHP to clean up the royal mess that it's in now. I already know the basic concepts of OOP, but I'm struggling a bit with applying it.
So far, all the sites I've seen that use OOP PHP have some sort of mySQL DB class. I can definitely see its benefits (cleaner code when you want to access something in the DB) but I'm not entirely sure how to set mine up. Here's what I'm wondering:
What are the first things I should do
when building this class from the
ground up? (How should this class be
set up? What's the idea behind that
structure? What does it look like
when set up like that?)
What kinds of methods should be in my
DB class? (What kind of functionality
should my DB class offer? SQL
Inserts? SQL Updates? plain ole' SQL
queries? What data should these
methods return?)
How do I determine when I need to add
a new method to the class?
How should I use those methods in my other code?
Thanks.
If you mean a class to connect to the database, prepare and run queries, use PDO (try "Writing MySQL Scripts with PHP and PDO" for a tutorial). If you mean a Data Access Object (DAO), which is a class (or classes) to function as a bridge between the database records and your application objects, try the data mapper or active record patterns. Note that the active record pattern is a little older and falling out of favor with some, so the articles about active record in PHP tend to be older and are a bit out of date.
Whatever pattern you apply, the four basic operations your class(es) should provide are create, read, update and delete (CRUD). Create and read return application objects, and update and delete can return values indicating success or failure.
Using the class(es) is fairly straightforward: whenever you need an object, use create or read rather than the object constructor. When to use update or delete depends on your business logic. For example, you may need to update whenever you're done with an object (i.e. when the object is destroyed). What's trickier is how an object or function gets a reference to DAOs. Reading Martin Fowler's article on dependency injection for a few different approaches.
Further reading:
Persistence Patterns
Practical PHP Patterns: Data Mapper
Implementing the Data Mapper Design Pattern in PHP 5
Implementing The Domain Model: Entries and Authors
Using the Active Record Pattern with PHP and MySQL
There are several ways to go about this, firstly you can "integrate" a system into a native system such as mysqli or you can go about creating your own system / structure from scratch using drivers.
With the first method your a little limited as you have to abide by the internal structure of the native API.
My personal approach is usually the second as i can create a driver based system and decide what native system to use depending on the host operating system and several other factors.
When creating a database API for your applications to run on you do not want it to be specifically for that application, you should be able to grab the libraries drop them into a new project and everything should work as expected, so making it abstract is the first issue we will have to get around.
The next obstacle is to make the code extendible, the programming world changes radically so we should be prepared for changes, although the code would only suffice for a few years, it would be beneficial if we thought about thus years and was prepared.
imagine if next week a new database layer was created that was 50x faster then the current mysql(i) layer that's integrated into PHP, you would want to switch to that api ASAP, thinking about these factors is always a good thought to have during the development stages.
Firstly we should decide on the structure, with traditional abstraction layers the code is usually all built into 1 large class file, this can be bad programming as it should be broken down into its purposes.
We should be separating the classes / objects so that they perform the task there specifically designed for.
We should have 1 global "controller" which would be the main Database Class, this would control all operations sent to and from the sub classes.
We would be designing for PHP 5.3 as minimum, so lets get started:
What i tend to do is create some pseudo code of what the end-result would be like, this way i will have an understanding of what should be implemented.
$Connection = new DatabaseConnectionDetails(array(
"hostname" => "localhost",
"username" => "root",
"password" => "n/a",
"charset" => "UTF-8",
"database" => "my_database",
"driver" => "MySQL",
));
$Database = Database::getInstnace($Connection);
$Query = $Database->Query("SELECT * FROM {?:table} WHERE id = {?:id}",array(
"table" => "posts",
"id" => 22
));
if($Query->Execute())
{
$Results = $Query->GetResults();
foreach($Results as $Result)
{
echo $Result->data; //trims, converts to int, returns;
}
}
This would be how I would like to connect to my database, so this is how I would start working with the base class
class Database
{
private static $_DBInstance;
public static function getInstance(IDatabaseConnectionDetails $ConnectionDetails)
{
if(self::$_DBInstance === null)
{
self::$_DBInstance = new Database($ConnectionDetails);
}
return self::$_DBInstance;
}
public function __construct(IDatabaseConnectionDetails $ConnectionDetails)
{
//We will come back to this.
}
}
Looking at the class above you will see that firstly it has a create instance (singleton) that would help in using the database throughout any application, you would also note that im specifically defining what parameters are required.
Keeping the above factors in place throughout the whole abstraction layer will make life much easier.
Let me just explain a little about the the directory structure, you would have to seperate the following class
Database
Query Classes
Interfaces
Drivers
Helpers
and I would go for a structure a little like so:
includes
DBAL
Database.class.php
DatabaseConnectionDetails.class.php
Drivers
Interfaces
Result
As stated above would require a IDatabaseConnectionDetails interface, the purpose of this is so that the separation of credentials and the main database are made, therefore the IDatabaseConnectionDetails has a primary role of looking after the users credentials.
class DatabaseConnectionDetails implements IDatabaseConnectionDetails
{
public $hostname = "localhost";
public $username = "";
public $password = "";
public $charset = "UTF-8";
public $driver = "mysqli";
public function __construct($params)
{
//Set Params here
}
}
Now the beauty of creating a class for your configuration was mentioned above, the extensibility of the class, for example:
class MyCustomConfig extends DatabaseConnectionDetails
{
public $hostname = "host.domain.tld";
public $username = "my_other_user";
public $password = "IJH87b&OTIT8fh";
public $driver = "mssql";
}
This way as the classes are interfaced you can send any class into the main database object, being custom or not as the interface allows you to be extensible.
Now the drivers that are required, you should note that each driver should be part of an driver interface, that forces a set of methods to be within the driver itself.
interface IDatabaseDriver
{
public function setConnectionDetails(IDatabaseConnectionDetails $ConnectionDetails);
public function connect();
public function escape($string);
public function query($string);
/*
all the methods here that will allow the main class can access, such as:
- next()
- prev()
- reset()
ect ect
*/
}
The main database class would then be able to load the correct driver depending on $Config->driver.
you would create generic functions in the Main Database Class that would mimic a typical database system such as fetchObject,fetchArray() etc, these methods would then use the driver object to select, prepare, sanitize the data and then return the results using another object/class such as QueryResult which would have a set a dedicated methods that are solely for the purpose of traversing a result set.
Hope you enjoyed this long read but should get you started with an idea in your head.
Regards:
Robert
I'm creating an ORM in PHP, and I've got a class 'ORM' which basically creates an object corresponding to a database table (I'm aiming for similar to/same functionality as an ActiveRecord pattern.) ORM itself extends 'Database', which sets up the database connection.
So, I can call: $c = new Customer();
$c->name = 'John Smith';
$c->save();
The ORM class provides this functionality (sets up the class properties, provides save(), find(), findAll() etc. methods), and Customer extends ORM. However, in the future I may be wanting to add extra public methods to Customer (or any other model I create), so should this be extending ORM or not?
I know I haven't provided much information here, but hopefully this is understandable on a vague explanation, as opposed to posting up 300+ lines of code.
I agree with the other answers here - put the additional methods into a descendant class. I'd also add an asterisk to that though: each time you extend the class with extra methods, think about what you are trying to achieve with the extension, and think about whether or not it can be generalised and worked back into the parent class. For example:
// Customer.class.php
function getByName($name) {
// SELECT * FROM `customer` WHERE `name` = $name
}
// ** this could instead be written as: **
// ORM.class.php
function getByField($field, $value) {
// SELECT * FROM `$this->table` WHERE `$field` = $value
}
You're certainly thinking correctly to put your business logic in a new class outside your 'ORM'. For me, instead simply extending the ORM-class, I'd rather encapsulate it with a new, value object class to provide an additional degree of freedom from your database design to free you up to think of the class as a pure business object.
Nope. You should use composition instead of inheritance. See the following example:
class Customer {
public $name;
public function save() {
$orm = new ORM('customers', 'id'); // table name and primary key
$orm->name = $this->name;
$orm->save();
}
}
And ORM class should not extend Database. Composition again is best suited in this use case.
Yes, place your business logic in a descendant class. This is a very common pattern seen in most Data Access Layers generation frameworks.
You should absolutely extend the ORM class. Different things should be objects of different classes. Customers are very different from Products, and to support both in a single ORM class would be unneeded bloat and completely defeat the purpose of OOP.
Another nice thing to do is to add hooks for before save, after save, etc. These give you more flexibility as your ORM extending classes become more diverse.
Given my limited knowledge of PHP I'm not sure if this is related, but if you're trying to create many business objects this might be an incredibly time consuming process. Perhaps you should consider frameworks such as CakePHP and others like it. This is nice if you're still in the process of creating your business logic.
You're definitely thinking along the right lines with inheritance here.
If you're building an ORM just for the sake of building one (or because you don't like the way others handle things) than go for it, otherwise you might look at a prebuilt ORM that can generate most of your code straight from your database schema. It'll save you boatloads of time. CoughPHP is currently my favorite.
I have solved it like this in my Pork.dbObject. Make sure to check it out and snag some of the braincrunching I already did :P
class Poll extends dbObject // dbObject is my ORM. Poll can extend it so it gets all properties.
{
function __construct($ID=false)
{
$this->__setupDatabase('polls', // db table
array('ID_Poll' => 'ID', // db field => object property
'strPollQuestion' => 'strpollquestion',
'datPublished' => 'datpublished',
'datCloseDate' => 'datclosedate',
'enmClosed' => 'enmclosed',
'enmGoedgekeurd' => 'enmgoedgekeurd'),
'ID_Poll', // primary db key
$ID); // primary key value
$this->addRelation('Pollitem'); //Connect PollItem to Poll 1;1
$this->addRelation('Pollvote', 'PollUser'); // connect pollVote via PollUser (many:many)
}
function Display()
{
// do your displayĆng for poll here:
$pollItems = $this->Find("PollItem"); // find all poll items
$alreadyvoted = $this->Find("PollVote", array("IP"=>$_SERVER['REMOTE_ADDR'])); // find all votes for current ip
}
Note that this way, any database or ORM functionality is abstracted away from the Poll object. It doesn't need to know. Just the setupdatabase to hook up the fields / mappings. and the addRelation to hook up the relations to other dbObjects.
Also, even the dbObject class doesn't know much about SQL. Select / join queries are built by a special QueryBuilder object.