Understanding Interfaces and Abstract Classes - php

I have never used Interfaces or Abstract Classes in PHP, but have come to a point where I want to support similar but different types of the same object (in this case Network Switches) and possibly add more in the future. I communicate with them via SSH (PHPSecLib) and which the interactions are different, the actual methods would be the same.
In my particular case I believe an Abstract Class, implementing the constants, private variables, connect functions and constructor/destructors would be appropriate, leaving the extended classes ONLY to implement the functionality, where an Interface would just be a template but each extended class would still re-implement methods that are the same between them.
Am I correct in thinking that Abstract Classes are the way to go in this scenario? Do you need to place empty methods in Abstract Classes which are overridden by extended classes or can the extended class have methods that don't exist in the Abstract class?
Example:
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '/home/devicepo/public_html/include/PHPSecLib');
include('Net/SSH2.php');
include('File/ANSI.php');
abstract class Switch
{
const STATUS_UNKNOWN = "-1";
const STATUS_OFFLINE = "0";
const STATUS_ONLINE = "1";
public $conn;
private $_server;
private $_username;
private $_password;
private $_bashshell;
public function __construct($server, $username, $password)
{
if (!$server)
die("Switch configuration not Defined");
$this->_server = $server;
$this->_username = $username;
$this->_password = $password;
}
public function connect()
{
// Establish new SSH2 Connection
$this->conn = new Net_SSH2($this->_server, 22);
if(!$this->conn->login($this->_username, $this->_password))
{
die("Failed to connect to Switch: " . $this->_server);
}
}
public function enable_port($port)
{
// Define in extended classes
}
public function disable_port($port)
{
// Define in extended classes
}
}
?>

I believe that in your case the Abstract class is the way to go. The reasons are that:
Your child classes share a big part of code with the parent class
Your child classes have a notion of similarity.
To be more specific regarding point 2, keep in mind that two classes implementing the same interface are not necessarily related. The interface represents an ability. Consider for example an airplane and a bird. Both can implement a flyable interface, but except from that they are not related in any other way. On the other hand, your child classes have a similar type. They are all switches. So your abstract class could be
abstract class BasicSwitch { // You cannot use the name switch
const STATUS_UNKNOWN = "-1";
const STATUS_OFFLINE = "0";
const STATUS_ONLINE = "1";
public $conn;
private $_server;
private $_username;
private $_password;
private $_bashshell;
public function __construct($server, $username, $password) {
if (!$server) die("Switch configuration not Defined");
$this->_server = $server;
$this->_username = $username;
$this->_password = $password;
}
public function connect() {
// Establish new SSH2 Connection
$this->conn = new Net_SSH2($this->_server, 22);
if(!$this->conn->login($this->_username, $this->_password)) {
die("Failed to connect to Switch: " . $this->_server);
}
}
abstract public function enable_port($port);
abstract public function disable_port($port);
}
and a concrete implementation could be
class CiscoSwitch extends BasicSwitch {
public function __construct($server, $username, $password) {
parent::__construct($server, $username, $password);
}
public function enable_port($port) {
echo 'Port is enabled';
}
public function disable_port($port) {
echo 'Port is disabled';
}
}
The most important think to keep in mind here is that CiscoSwitch is also a type of BasicSwitch. This means that a CiscoSwitch can be used anywhere a BasicSwitch is expected. So consider that you have a Rack with many switches and you want to enable the same port an all switches in the rack. Here is your Rack class:
class Rack {
protected $switches;
public function addSwitch(BasicSwitch $switch) {
$this->switches[] = $switch;
}
public function enable_ports($port) {
foreach($this->switches as $switch) {
$switch->enable_port($port);
}
}
}
If you type hint on the Abstract class (BasicSwitch) and not on the implementation you can be sure that any switch inside the rack can enable and disable its ports. You really don't care which switch it is. You just know that it can do the job.
This is what code on an interface and not on implementation is all about. This way your code is open for extension but closed for modification. You can create as many switch types as you want but you will be sure that the Rack class will continue to work.

Related

Implementing interface based on the chosen interface

So if I have an interface iConnection
interface iConnection
{
}
Which is implemented by:
class OutlookConnection implements iConnection
{
}
And
class GoogleConnection implements iConnection
{
}
And another interface iComparison
interface iComparison
{
}
Which is implemented by:
class OutlookComparison implements iComparison
{
private $connection;
public function __construct($user, iConnection $iConnection) {
$this->connection = $iConnection;
}
}
And
class GoogleComparison implements iComparison
{
private $connection;
public function __construct($user, iConnection $iConnection) {
$this->connection = $iConnection;
}
}
In the main program I want to be able to switch between GoogleComparison and OutlookComparison based on the iConnection type without using an if or switch statement:
public function __construct(iConnection $connection)
{
$this->connect = $connection;
if($this->connection instanceof GoogleConnection){
$this->comparison = new GoogleComparison();
}
elseif($this->connection instanceof OutlookConnection){
$this->comparison = new OutlookComparison();
}
}
Is this possible to achieve within this constructor without switch or if statements?
This is an architectural issue. I suggest passing responsibility for providing comparison to the connection. One of the possible solutions could look like this below.
First - interface gets getter stub:
interface iConnection
{
public function getComparison();
}
Then - all the different connections implement it as you want, for example:
class OutlookConnection implements iConnection
{
public function getComparison()
{
return new OutlookComparison();
}
}
And finally, your construction similar to:
public function __construct(iConnection $connection)
{
$this->connect = $connection;
$this->comparison = $connection->getComparison();
}
From now on, you can either operate on comparison property or simply $this->connect->getComparison()->fooBarBaz(). All depends on your needs.

PHP - Good design pattern for static database connection class

I have a "static" class which connects to database and has various functions. The current base layout is as follows:
class DB {
private static $con;
private function __construct() {};
private static function init() {
if(is_null(self::$con) {
// Initialize database connection
}
}
public static someMethod1() {
self::init();
// Do stuff
}
public static someMethod2() {
self::init();
// Do stuff
}
public static someMethod2() {
self::init();
// Do stuff
}
}
My intention is to be easily be able to call these methods as: DB::someMethod1(). However, as you can see, I am having to cehck for initialization at every method beginning. Is this a good coding practice? Is there a better design pattern available? Initially I thought of builder pattern but that doesn't really fit here in my opinion.
It looks like you are trying to ensure that there is a single instance of your DB class AND also that the instance is available as a single, globally available constant.
I'd recommend separating those two concerns in order to simplify the implementation.
First, I'd focus on getting the database access object right. Plain objects are simpler to test and inject as dependencies than static functions. For example,
class DBThing
{
private $con;
public static function build()
{
return new static('theconnection');
}
function __construct($con)
{
$this->con = $con;
}
public function someMethod1()
{
echo "someMethod1: $this->con\n";
}
public function someMethod2()
{
echo "someMethod2: $this->con\n";
}
public function someMethod3()
{
echo "someMethod3: $this->con\n";
}
}
Gives you an object you can easily test and replace with alternate implementations if needed.
Second, I'd focus on the object lifecycle and making it discoverable in the application.
If you're really OK with a single instance and the global state that implies, then something like this gets you close to the interface you asked for in your original post.
$DB = DBThing::build();
$DB->someMethod1();
$DB->someMethod2();
$DB->someMethod3();
In general, I discourage global state but I'd have to know more about your application to know if it's appropriate in your case.
I just wrote a simple db class for a coding test. Take a look at how I used here: https://github.com/TheRealJAG/Valuation-Vision-Full-Stack-Test/blob/master/classes/db.php
class DB
{
private static $instance = null;
private $db;
private $host = '';
private $username = '';
private $password = '';
private $database = '';
private function __construct()
{
$this->db = new mysqli($this->host, $this->username, $this->password, $this->database);
if ($this->db->connect_error) {
throw new Exception("Connection to the mysql database failed: " . $this->db->connect_error);
}
}
public static function connection()
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance->db;
}
}
I'm 100% sold on the approach, but with the time I had for the test this is what I wrote. My biggest concern was that I only had 1 db connection open.

PHP OOP best practices or how to code right?

I'm trying to learn how to properly code PHP OOP.
This is where I'm running into issues.
I created several classes that extend main Application class and I want to make things work properly.
I have main file that's index.php that looks like this:
include_once('classes/Application.php');
include_once('classes/Configuration.php');
include_once('classes/Database.php');
$app = new Application;
$config = new Configuration;
$db = new Database;
var_dump($app->db_connected);
var_dump($db->db_connected);
$db->connect($config->dbhost, $config->dbuser, $config->dbpass, $config->dbname);
var_dump($app->db_connected);
var_dump($db->db_connected);
The output is:
1. bool(false)
2. bool(false)
3. bool(false)
4. bool(true)
My main application file looks like this:
class Application {
public $db_connected = false;
}
And my Database class looks like this:
class Database extends Application {
function connect($dbhost, $dbuser, $dbpass, $dbname) {
if(!$this->db_connected) {
mysql_connect($dbhost, $dbuser, $dbpass) or die(mysql_error());
mysql_select_db($dbname) or die(mysql_error());
$this->db_connected = true;
}
}
}
So the question is, why would line #3 of the output of index.php display false? The db_connected property has been overridden in Database class and set to TRUE, but it still returns false.
Although when accessed directly from Database class instance it shows TRUE correctly. What's the deal here?
Also when does the class EXTEND command occurs? Whenever parent class' instance is created or I have to manually create instance of the child class?
It seems you are reaching for the concept of of a static variable all instances of a class share the same static variable so using the new twice will not be an issue.
You can see the code on ideaone.
// your code goes here
class Application {
static $db_connected = false;
}
class Database extends Application {
function connect() {
if(!static::$db_connected) {
static::$db_connected = true;
}
}
}
$app = new Application;
$db = new Database;
var_dump(Application::$db_connected);
var_dump(Database::$db_connected);
$db->connect();
var_dump(Application::$db_connected);
var_dump(Database::$db_connected);
Your comment make me think you are looking for a better pattern all together. I would like to throw out some key principles namely OCP and LSP SOLID.
In this case you would avoid having Application being an instance of Database but instead use dependency injection. Here is the refactored code.
class Database {
private $db_connect = false;
public function connect () {
if(!$this->db_connect) { /* do connection */ }
}
}
class Application {
private $db;
public function setDatabse(Database $db) {
$this->db = $db;
}
public function getDatabase() {
return $this->db;
}
}
$db = new Database;
$app = new Application;
$app->setDatabase($db);
$app->getDatabase()->connect();
This line is your hint
Although when accessed directly from Database class instance it shows TRUE correctly. What's the deal here?
You have 2 instances. Above you are checking $db instance which you connected with, and then you print from $app which was never connected. They are separate entities, one is connected one is not.
Extend occurs as soon as the file is loaded, read by the php interpreter, this happens regardless of ever using the class.
Extend is called from the child and inherits everything form the class it extends. So if you call a child method in the parent, well you are doing it backwards. It goes one way, Prent -> Child.
I would use Dependance injection for the database, then you can reuse it's code.
Like this:
//parent class
class Application {
//holds a reference to the Database class
protected static $db_conn = false;
public function __construct($db){
self::$db_conn = $db;
}
}
//child class of Application
class Application2 extends Application {
public function getSomething($id){
return self::$db_conn->getbyId($id) ;
}
}
//separate utility class
class Database{
static $conn;
public function __construct( $dbhost, $dbname, $dbuser, $dbpass, $dbname) {
static::$conn = mysqli_connect($dbhost, $dbuser,$dbpass,$dbname);
}
public function getbyId( $id ){
..code to get stuff by id using $conn - previous connection ...
return $result;
}
}
$db = new Database("myhost", "myuser", "mypassw", "mybd");
$app = new Application2( $db );
$app->getSomething(1);
//create another app with the same database connection, this is the value of injecting it.
$second_app = new Application2( $db );
See you can reuse database over and over, you can replace it without changing the code in Application as long as the calls for the functions of the Database class don't change. Each thing is responsible for it's own business.
This is called separation of concerns.
Inheritance is good, when it's needed. You might have an basic application for free users of you're services and then extend that with a premium application for paid members. Sense they paid they get all the free functionality, but also the premium stuff to.
In my example above the database is something they both need, as well as other things will probably use this. Such as a login system may need a database connection, payment system might, a shopping cart might. These are all separate objects, they don't / nor should they extend off of one Master Class, that's a bad idea. Keep them separate.
STATIC
I seen mention of the :: static object operator. My example is a bit flawed when using the static property protected static $db_conn = false;
$app = new Application2( $db );
$second_app = new Application2( $db ); //assigning db 2x is not needed.
The reason for :: and the -> normal way. Is that static :: is shared across all instance of a class, and -> is just this instance of the class. I had assigned the $db class to a static variable 2 times a better way would have been like this.
//parent class
class Application {
protected static $db_conn = false;
//separate method then construct.
public function connect($db){
self::$db_conn = $db;
}
}
//we'll keep the rest of the code the same here.
$db = new Database();
$app = new Application2();
$app->connect( $db );
$second_app = new Application2();
$second_app->getSomething(1);
Now in this example $second_app never ran it's connect method. But because the first $app did and because the static for the database variable protected static $db_conn. Now all classes that have extended the Application class have a database connection. This is what static does. It's value is shared across all instance of the class. So when you see :: think all class instance and when you see -> think only this class instance. It's actually one thing I love about php, makes it so much easier to keep track of then in some other languages.
Not to confuse you but the other use of the :: is not actually needing an instance at all. Assume you have a Config class like this.
class Config{
static $db = 'hello';
static $items = array('one' => 'item 1' );
private __construct(){} // no construction allowed
static function getItem( $which ){
return self::$items[$which];
}
}
Now without ever creating an instance of the class by calling new Config() , you can simply.
echo Config::$db;
// prints hello
echo Config::getItem('one');
// prints 'item 1'
This is quite use full for config type classes. Where they are an empty shell just used to store data in and you don't need an object for them, essentially a way to keep things organized. So tying this in to the previous examples
$db = new Database(Config::$myhost, Config::$myuser, Config::$mypassw, Config::$mybd);
In your case best OOP practice is to use Mediator pattern. Concrete Mediator will be Application class:
class ApplicationBase {
private $db;
private $cfg;
public function setDb(Database $db) {
$this->db = $db; return $this;
}
public function setConfig(Config $cfg) {
$this->cfg = $cfg; return $this;
}
}
class Application extends ApplicationBase {
public function getDsn() {
return $this->cfg->getDsn();
}
public function getDbUser() {
return $this->cfg->getDbUser();
}
public function getDbPass() {
return $this->cfg->getDbPass();
}
public function getConnection() {
return $this->db->getConnection();
}
}
class AppComponent {
protected $app;
public function __construct(Application $app) {
$this->app = $app;
}
}
class Config extends AppComponent {
private $dsn;
private $dbuser;
private $dbpass;
// ... getters and setters
}
class Database extends AppComponent {
private $connection;
private function connect() {
$this->connection = new PDO(
$this->app->getDsn(),
$this->app->getUser(),
$this->app->getPass()
);
}
public function getConnection() {
if (null === $this->connection) $this->connect();
return $this->connection;
}
}
class Model extends AppComponent {
protected $table;
// Model stuff here
}
class Content extends Model {
public function getNews() {
$db = $this->app->getConnection();
return $db->query("SELECT * FROM $this->table LIMIT 5")->fetchAll();
}
}
Such architecture will be enough for simple, clean-looking applications and classes will be ready for easy unit-testing:
$app = new Application();
$cfg = new Config($app);
$db = new Database($app);
$app->setDb($db)->setConfig($cfg);
$content = new Content($app);
$news = $content->getNews();

Use functions from a class in another class without extending?

I have multiple classes, in this case Core and User. At this moment User is an extension of Core. In Core, I have my main functions that are required in multiple classes, for example a database connection through PDO. I use a __construct function to build the database connection, no problems with that.
However, in my User class, I want to pass values to multiple attributes through __construct. For example a Firstname, Lastname, Email, Password and a few other attributes.
When doing this, I get a warning from Netbeans that the parent constructor should be used, and a lot of vague errors, I don't ask you to fix these errors.
I would like to know if there is a way for me to use the database connection function from Core in User without making the extension. I hope it is more clear with a little bit of background information!
Below both classes, only showing the parts related to the question:
abstract class Core implements ICore {
private $_dbcon;
public function __construct($_database){
$this->_dbcon = $_database;
}
public function _connectDB(){
return $this->_dbcon;
}
class User extends Core implements IUser {
public $_username;
private $_password;
protected $_email;
protected $_adres;
protected $_phone;
protected $_contactperson;
protected $_company;
protected $_kvk;
public function __construct($_username, $_password, $_email, $_adres, $_phone, $_contactperson, $_company, $_kvk){
$this->_username = $_username;
$this->_password = $_password;
$this->_email = $_email;
$this->_adres = $_adres;
$this->_phone = $_phone;
$this->_contactperson = $_contactperson;
$this->_company = $_company;
$this->_kvk = $_kvk;
}
You have to call the parent constructor.
class User extends Core
{
public function __construct($db, $username, ...)
{
parent::__construct($db);
$this->_username = $_username;
...
}
}
But in your case I would think about a better overall design. Read about Dependency injection. In this way you'd only have one DB connection and use that connection in other classes.
class User
{
protected $db;
public function __construct(Db $db)
{
$this->db = $db;
}
}

Dependency Injection simple implementation

after reading this question i wonder if someone can help me understand how to implement correctly Dependency Injection with these PHP Classes:
class DBClass
{
private $mMysqli;
function __construct(mysqli $database)
{
$this->mMysqli=$database;
}
function __destruct()
{
$this->mMysqli->close();
}
public function listUsers()
{
$query='SELECT * FROM Utente;';
$resultset=$this->mMysqli->query($query);
while($row = $resultset->fetch_array(MYSQLI_ASSOC)) {
echo $row['username'];
echo $row['pwd'];
echo "<br />\n";
}
}
public function runQuery($query)
{
return $resultset=$this->mMysqli->query($query);
}
public function getConnection()
{
return $this->mMysqli;
}
}
Session class:
class Session
{
private $_session;
public $maxTime;
private $database;
public function __construct(DBClass $database)
{
$this->database=$database;
$this->maxTime['access'] = time();
$this->maxTime['gc'] = get_cfg_var('session.gc_maxlifetime');
session_set_save_handler(array($this,'_open'),
array($this,'_close'),
array($this,'_read'),
array($this,'_write'),
array($this,'_destroy'),
array($this,'_clean')
);
register_shutdown_function('session_write_close');
session_start();
...
}
}
User Class (for details about the currently logged in user):
class User
{
private $username;
private $role;
private $session;
function __construct($session)
{
$this->session=$session;
...
}
}
Externally:
$connection=new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_DATABASE);
$database=new DBClass($connection);
$session=new Session($database);
$user=new User($session);
Is this the proper way?
Yes. You are now injecting the dependencies through the constructor which provides for less coupling. You can now more easily swap out these dependencies, e.g. when UnitTesting you can replace them with Mocks.
You have still some coupling though by using the concrete DBClass as a TypeHint instead of an interface. So when you would want to use a different DBClass, it would have to be named DBClass. You could achieve more loose coupling by coding against an interface that the concrete classes have to implement instead.
To create only single instances of a class (as asked in the comments), you could either use a Singleton (like Kevin Peno suggested) or a Factory to create and keep track of if the instance has been created yet. Or use a DI Service Container, which is similar to a Factory, yet not the same thing. It creates and manages objects for you.
The Symfony Components library has a Dependency Injection Container with excellent documentation and introduction to the topic on how to further enhance DI this with Service Containers. The containers can also be used to limit instances. Check it out.

Categories