I'm using the PHP REST API example that appears all over the web. Here's basically what it is:
<?php
require_once("Rest.inc.php");
class API extends REST {
const DB_SERVER = "myhost";
const DB_USER = "myuser";
const DB_PASSWORD = "mypassword";
const DB_NAME = "mydb";
public $data = "";
private $db = NULL;
public function __construct(){
parent::__construct();
$this->dbConnect();
}
private function dbConnect(){
try {
$this->db = new PDO("mysql:host=" . self::DB_SERVER . ";dbname=" . self::DB_NAME, self::DB_USER, self::DB_PASSWORD);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
}
public function processApi(){
$func = strtolower(trim(str_replace("/","",$_REQUEST['rquest'])));
if((int)method_exists($this,$func) > 0) {
$this->$func();
} else {
$this->response('',404);
}
}
private function activity(){
...
}
private function client(){
...
}
private function facility(){
...
}
etc...
private function json($data){
if(is_array($data)){
return json_encode($data);
}
}
}
// Initiiate Library
$api = new API;
$api->processApi();
?>
It works fine, except that I don't want to hardcode the database connection parameters in that script. What is the best way (or is there a way) to separate them from this script? I can't use an include file inside the class declaration. Can I put the whole dbConnect()
function in an include file, and include that outside the class definition? Any other options? I just want it so that there is nothing tying this script to a specific server. I would prefer to have the db server defined in a separate file that could be different on each server. I'm new to PHP and just wondering how the experts handle this.
**Edit: Got it working! This is a bit of a hybrid of the supplied answers.
dbConnect.php
<?php
class DB {
const DB_SERVER = "myserver";
const DB_USER = "myuser";
const DB_PASSWORD = "mypassword";
const DB_NAME = "mydb";
private $db = null;
public function __construct() {
try {
$this->db = new PDO("mysql:host=" . self::DB_SERVER . ";dbname=" . self::DB_NAME, self::DB_USER, self::DB_PASSWORD);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
}
}
?>
api.php
<?php
require_once("Rest.inc.php");
require_once("dbConnect.php");
class API extends REST {
public $data = "";
private $db = null;
public function __construct(DB $mydb){
parent::__construct();
$this->db = mydb->db;
}
}
// Initiiate Library
$api = new API(new DB());
$api->processApi();
?>
You need to use Dependency Injection
pattern, it will help you. And you will have something like this:
interface DB
{
// Here you need to declare your common methods for all DB classes.
}
class MasterDB implements DB
{
const DB_SERVER = "myhost";
const DB_USER = "myuser";
const DB_PASSWORD = "mypassword";
const DB_NAME = "mydb";
private $db = null;
private function __construct()
{
try {
$this->db = new PDO("mysql:host=" . self::DB_SERVER . ";dbname=" . self::DB_NAME, self::DB_USER, self::DB_PASSWORD);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
}
}
class SlaveDB implements DB
{
// Here you need to provide another connection
}
class API extends REST
{
private $db = null;
public function __construct(DB $db)
{
parent::__construct();
$this->db = $db;
}
}
$api = new API(new MasterDB());
// or
$api = new API(new SlaveDB());
$api->processApi();
It is not a perfect example, but this one will help you solve your problem! Next step probably is - create parent or abstract class for MasterDB
and SlaveDB
...