Is there a way to refactor this? The plumbing has to be put in somewhere:
Here is my index.php page:
define('BASE_URL', __DIR__);
echo BASE_URL;
require_once(BASE_URL . DIRECTORY_SEPARATOR . "config\\config.php");
require_once(BASE_URL . DIRECTORY_SEPARATOR . "Classes\\PdoAdapter.class.php");
require_once(BASE_URL . DIRECTORY_SEPARATOR . "Classes\\Student.class.php");
$adapter = new PdoAdapter(DB_DSN, DB_USER_NAME, DB_PASSWORD);
$student = new Student($adapter);
$student->findByStudentID(4);
Here are my classes:
require_once(BASE_URL . DIRECTORY_SEPARATOR . "Classes\\IStudent.interface.php");
class Student implements IStudent {
public function __construct(IRepository $adapter) {
$this->adapter = $adapter;
}
public function findByStudentID($id){
$sql = 'SELECT * FROM students WHERE student_id = :student_id';
$this->adapter->connect();
$this->adapter->prepare($sql);
$place_holders = array(':student_id' => $id);
$this->adapter->execute($place_holders);
$results = $this->adapter->fetchAll();
//print_r($results);
foreach ($results as $student){
echo "</br>" . $student["student_id"] . " , " . $student["LAST"] . "</br>";
}
$this->adapter->disconnect();
echo $sql;
}
}
If I add a new method (same class), say:
require_once(BASE_URL . DIRECTORY_SEPARATOR . "Classes\\IStudent.interface.php");
class Student implements IStudent {
public function __construct(IRepository $adapter) {
$this->adapter = $adapter;
}
public function findByLastName($last_name){
$sql = 'SELECT * FROM students WHERE LAST = :last_name';
$this->adapter->connect();
$this->adapter->prepare($sql);
$place_holders = array(':last_name' => $last_name);
$this->adapter->execute($place_holders);
$results = $this->adapter->fetchAll();
//print_r($results);
foreach ($results as $student){
echo "</br>" . $student["student_id"] . " , " . $student["LAST"] . "</br>";
}
$this->adapter->disconnect();
echo $sql;
}
}
Should I be doing the connect, prepare, execute, over and over in the model like this? I could be a mapper and this would create an ORM of sorts. But I really don't want an ORM. I have to do this somewhere. The model seemed to give me a lot of flexibility, but doesn't this tie me to PDO (which is okay with me).
This is using PHP 5.4, PDO with MySQL. The $adapter
is a wrapper for a PDO class I have.
EDIT: I am using the concepts Model, Database, and Tables in a loose sense. I do not believe the Model is a table, for example. It is one aspect of the "M."
EDIT: I changed this:
public function __construct(IRepository $adapter) {
$this->adapter = $adapter;
$this->adapter->connect();
}
Then in my calling page:
$adapter = new PdoAdapter(DB_DSN, DB_USER_NAME, DB_PASSWORD);
$student = new Student($adapter);
$student->findByStudentID(4);
$student->findByStudentLastName('Smith');
I think that is better. I also removed the disconnect()
because I thought PDO automatically disconnected after the script is finished.
I now have:
<?PHP
require_once(BASE_URL . DIRECTORY_SEPARATOR . "Classes\\IStudent.interface.php");
class Student implements IStudent {
public function __construct(IRepository $adapter) {
$this->adapter = $adapter;
$this->adapter->connect();
}
public function findByStudentID($id){
$sql = 'SELECT * FROM students WHERE student_id = :student_id';
$this->adapter->prepare($sql);
$place_holders = array(':student_id' => $id);
$this->adapter->execute($place_holders);
$results = $this->adapter->fetchAll();
//print_r($results);
foreach ($results as $student){
echo "</br>" . $student["student_id"] . " , " . $student["LAST"] . "</br>";
}
echo $sql;
}
public function findByStudentLastName($last_name){
$sql = 'SELECT * FROM students WHERE LAST = :last_name';
$this->adapter->prepare($sql);
$place_holders = array(':last_name' => $last_name);
$this->adapter->execute($place_holders);
$results = $this->adapter->fetchAll();
//print_r($results);
foreach ($results as $student){
echo "</br>" . $student["student_id"] . " , " . $student["LAST"] . "</br>";
}
echo $sql;
}
}
The echo in the model here is for testing.
You can get away from implementing an interface and use a base class where the db connection and subsequent close are managed in the constructor. The query would be a parameter sent in to the constructor.
I think the MODEL in MVC is open to interpretation on how the plumbing is managed ( in terms of connections ), its just the naming convention that is important from table to controller depending on the framework.
I have done this a lot in php, but the only thing I have handy at the moment is python -> same premise though.
class db_query:
oracle_instance = ''
def __init__(self):
print '-- new db instance --'
def db_Query( self, host, port, sid, login, passwrd, queryString ):
try:
connstr = login + '/' + passwrd + '@' + host + ':' + port + '/' + sid
connection = cx_Oracle.connect( connstr )
except cx_Oracle.DatabaseError as e:
error, = e.args
print(error.code)
print(error.message)
print(error.context)
cursor = connection.cursor()
cursor.arraysize = 200
try:
cursor.execute( queryString )
except cx_Oracle.DatabaseError as e:
error, = e.args
print(error.code)
print(error.message)
print(error.context)
result = []
for rows in cursor:
result.append( rows )
cursor.close()
connection.close()
return result
Hope that gives you some ideas.