Writing my first application in PHP that makes use of classes and objects.
I have a DB class which takes a string to select the appropriate config because there are multiple databases. I started out with a login class but scratched that idea in exchange for a user class so I can do user->isLoggedIn stuff. The user class uses MySQL which stores user and login information, as well as credentials for the second database.
$mysql = new db( 'mysql' );
$user = new user( $mysql );
if( !( $user->isLoggedIn() === true ) )
{
goToPage( 'login.php' );
exit();
}
The second database is Sybase and stores account information. I need the credentials from the user class to get lists and accounts information from here. I think an account class should be next but not sure of the best way to do it. Something like this maybe..
$sybase = new db( 'sybase' );
$account = new account( $sybase );
$account_list = $account->getList( $user->info );
$user->info being an array i guess of credentials and info needed for the account table, or is there a better way to go about this?
Edited to include db class example
config.db.php
$config_array = array();
$config_array[ 'mysql' ][ 'dsn' ] = "mysql:host=localhost;dbname=********;charset=UTF-8";
$config_array[ 'mysql' ][ 'user' ] = "********";
$config_array[ 'mysql' ][ 'pass' ] = "**************";
$config_array[ 'sybase' ][ 'dsn' ] = "odbc:DRIVER={Adaptive Server Anywhere 8.0};***************";
$config_array[ 'sybase' ][ 'user' ] = "**********";
$config_array[ 'sybase' ][ 'pass' ] = "*********";
class.db.php
public function __construct( $type )
{
require 'config.db.php';
$this->type = $type;
foreach( $config_array[ $this->type ] AS $key => $value )
{
$this->$key = $value;
}
try
{
$this->connection = new PDO( $this->dsn, $this->user, $this->pass, $this->options );
}
catch( PDOException $ex )
{
log_action( "db->" . $this->type, $ex->getCode() . ": " . $ex->getMessage() );
$this->error = true;
}
return $this->connection;
}
Does something like the following make sense?
class User()
{
public function getAccountList()
{
$this->Account = new Account( new Database( 'sybase' ) );
return $this->Account->list( $this->userid );
}
}
Also, Accounts have different sections (i.e. History & Notes, Financial Transactions, Documents) that will be different ‘tabs’ on the page. Should each one of those be a class too?
First up, as a secondary answer on the other answer by Dimitry:
The things you’ll gain by having a Singleton pale to the things you lose. You get a global object, which every part of your program can read and modify, but you lost testability, readability, and maintainability.
Because the Singleton object is in fact global, you cannot accurately isolate the single units in your application (which is crucial for Unit Testing), because your function is dependant on other components, which are “magically” inserted into it.
You lose readability because
method()may actually need other things to work (for instance, theuserobject needs adbinstance, this makesnew user($db)much more readable thannew user(), because even without looking at the source code, I can tell what the method/object needs to work.You lose maintainability because of the reason stated above as well. It’s harder to tell which components are inserted via the Singleton than it is to see it in the function’s “contract”, for that reason, it’ll be harder for future you and/or any other developer to read and refactor your code.
Let’s start from the top. You have 2 possible states for your
Dbobject,MysqlDb, andSybaseDb. This calls for polymorphism. You have an abstract classDb, and two concrete classesMysqlDbandSybaseDbinheriting from it. The instantiation of the correct Db object is the responsibility of a factoryNow you should ask yourself, who is responsible for getting the list of accounts? Surely they shouldn’t fetch themselves (just as much as it isn’t the user’s responsibility to fetch its own data from the database). It’s the
User‘s responsibility to fetch these accounts, using theSybaseDbconnection.In fact, the
Userneeds the following to work:DbFactoryinstance to it, so that we can easily get the instance if it were already instantiated, and instantiate it if not.The
Userisn’t responsible to set this data, it needs it in order to work.So the
Userconstructor should look like this (assuming “ID” and “name” fields):The
Userwill have a field$accounts, which would hold an array ofAccountobjects. This array would be populated with aUser::getAccounts()method.