In my controller class I just want to use only one spreadsheet class to handle all the functions related to spreadsheet creation, save, load, write etc.
Currently I'm using one open source library phpspreadsheet to create a spreadsheet, if later I want to change that to another library of spreadsheet creation, I don't want to change much on the controller class, instead, I can create another class for this library, like Spreadsheetlib2. So which design pattern is better to use here? "Bridge" or Adapter?
// Bridge Pattern what I'm trying now.
interface SpreadsheetInterface {
public function create();
public function write();
}
class Spreadsheet extends AbstractSpreadsheet {
public function create() {
}
}
class PhpSpreadsheet implements SpreadsheetInterface {
public function create() {
}
}
abstract class AbstractSpreadsheet {
protected $spreadsheet;
protected function __construct(SpreadsheetInterface $spreadsheet) {
$this->spreadsheet = $spreadsheet;
}
}
I would really pay that much attention to "what pattern to use". Patterns are not magical recipes, to write your code by. They are just "shorthand descriptions", that you use to describe stuff you already wrote, to some other developer.
The way I would do it would be creating a wrapper (I think that counts as "adapter"), which implements some specific interface, that you Controller depends upon. And in this wrapper I would pass the PhpSpreadsheet instance as a dependency (or create a new instance of it directly in that wrapper).
When your controller calls a method on the wrapper, it forwards the call to the underlying "spreadsheet class.
Heres a little trick that Doctrine uses to define a Connection interface, while extending PDO at the same time.
interface Connection
{
public function prepare ($statement, array $driver_options = array());
}
class PdoConnection extends \PDO implements Connection
{
}
So, they wanted to define an interface that they could implement based on the requirements of whatever DB they were connecting to. But they wanted to keep the API pretty similar to PDO, however PDO doesn't implement an interface, so they had to piggy back one onto it by extending PDO while implementing Connection, therefore PDO unwittingly implements the methods of Connection.
You can do the same really. Choose whichever spreadsheet library you like best and create an interface from its methods, create a new class extending it then implement your interface.
Now when you want to switch implementation, your favourite library ought to have provided you with a decent amount of method signatures to implement another version.
Related
Can you help to clarify PHP Interface for me. I get that the main point is so that multiple classes can implement some of the same functions.
abstract class Plane {
public function openDoors();
}
interface Fliers {
public function fly();
}
now lets use them
class Boeing747 extends Plane implements Fliers {
public function fly() {
// some stuff
}
public function openDoors() {
// do something
}
}
and
class Tweety implements Fliers{
public function fly() {
// some stuff
}
}
In this case both Boeing747 and Tweety can implement the interface Fliers to access the public function fly(). However, in all examples that I am seeing, no functionality is actually defined in the interface, but rather when it is called inside of the class method itself.
Why would I not just define fly() as a separate function in each of Boeing747 and Tweety, instead of using the interface? Can you provide a concrete, basic example where it would be advantageous? Thanks!
It's a technique known as Design by Contract. Essentially, the interface serves as a contract, or a promise that any class that implements the interface will exhibit a particular set of behaviours. It allows your code to check capabilities of an object passed to it without having to worry about details that don't matter in the current context. For example, your openDoors() method could equally apply to a house, an aircraft, a canal lock, a car or anything else with doors, but other than having doors all of these things have very little in common. Even if they do all support the idea of having doors that can be opened, they may actually perform the door opening actions in wildly different ways.
The interface allows you to tell calling code that all these things have doors that you can open, without having to impose any artificial relationship between them when none exists. The instanceof keyword lets you check if an object meets certain criteria (if it's an instance of a particular class or subclass, or if it implements a particular interface).
interface ThingWithDoors {
public function openDoors ();
}
class House implements ThingWithDoors {
// Implement openDoors here
}
class CanalLock implements ThingWithDoors {
// Implement openDoors here
}
class Boeing747 extends Aircraft implements ThingWithDoors {
// Implement openDoors here
}
// Calling code
if ($object instanceof ThingWithDoors) {
// We don't know exactly what class we have, but we do know it has an openDoors method
$object -> openDoors ();
}
You could in theory achieve the same thing with other PHP functionality such as method_exists or Reflection, but those techniques are far from ideal because there's no contract to enforce anything (two different classes could implement door opening but have completely different names for the methods that do it, and you'd have to check for both with method_exists calls). Then, suppose, some other programmer adds a new class to the system that implements door opening in a completely different way from the ones you already check for. All the code where doors could be opened throughout the program would have to be updated to account for this new method too! If you add a new class to the system and it implements the ThingWithDoors interface, however, then all the code that opens doors will automatically work with the new class as it did with the old class without any modification at all (provided the new class implements the interface properly and respects return values that, sadly, aren't enforced by PHP interfaces).
Another nice thing about this for the programmer is that they don't have to keep looking up in the documentation/source code how to invoke certain behaviours in an object. If they know what the ThingWithDoors interface looks like then they know that everything that implements ThingWithDoors can have its doors opened, and that the method call for doing it is always going to be openDoors (). That can save you a fair bit of time as a developer, especially on a big project!
in OO PHP an object can have only one parent class. To see why this is adopted , lets use the Bird Class to show what multiple inheritance is and how it can lead to problems.
If you wanted to create a Wooping_Crane class, it would make sense to derive this class from Bird class. Suppose you also have an Endangered_Species class.
Multiple inheritance would allow you to create a Wooping_Crane class from combination of these two classes( Bird and Endangered classes). This would seem to be an excellent idea until you realize that both classes define an eating behaviour. Which one to prefer? so this is the disadvantage of multiple inheritance.
PHP solves this in two ways : Firstly , using interface - a class with function definition only.
If Endangered_Species were an interface rather than a class, having more than one eating function wouldn't matter. The method definition in the Bird class would act as the implementation of the interface function. In this way interfaces avoid the problem of defining the same function twice.
Secondly, using traits. ou can read about it in other posts.
I have started writing a library of e-commerce classes in PHP as abstract classes with the intention of forcing the implementation of concrete classes to use a load() method which loads data into the objects:
abstract Cart {
abstract function load();
// other stuff ...
}
class MyCart extends Cart {
public function load()
{
// pull in data from anywhere ...
}
}
I was wondering if this is the right way to go about doing this...
I want to:
Keep the core library un-touched.
Keep it very simple, we intend to re-use this code and other people will be implementing it.
I've heard about adapters and things, although I haven't looked into these (yet).. can anyone point me in the right direction?
Cheers,
John.
Instead of using an abstract class, I would recommend using interfaces for this purpose:
interface Cart {
public function load();
// other stuff ...
}
class MyCart implements Cart {
public function load()
{
// pull in data from anywhere ...
}
}
Interfaces are used to describe the structure of a deriving class, it's the best way if you want to add different classes all offering the same methods. Another advantage would be that a class can only extend one parent class (i.e. your Cart class) but can implement several interfaces.
Read more about interfaces on PHP.net, here's one excerpt underlining why I think this pattern would fit your requirement:
Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are handled.
Ok I am trying to start really learning OOP style in PHP. I have declared both interfaces and classes and have the classes implementing the interfaces. I was wondering however, is it not possible to just load interface files in into PHP script files and call the methods from the interface instead of loading the class implementation files? If so, how would that be done b/c I cannot find an answer to this. Thanks!
Interfaces can have no implementation, so you cannot do that. Their purpose is to stipulate "contracts" (in the sense that "classes that implement this interface promise to provide public methods X Y and Z") that the classes (which implement the interfaces) must honor.
This is really really basic OOP stuff, and it's not applicable to just PHP. I would suggest studying some more OOP theory before you try to progress further.
You cannot call methods on an interface. An interface cannot be instantiated. You must create a class that implements the interface and use that class instead.
An INTERFACE is provided so you can describe a set of functions and then hide the final implementation of those functions in an implementing class. This allows you to change the IMPLEMENTATION of those functions without changing how you use it.
For example: I have a database. I want to write a class that accesses the data in my database. I define an interface like this:
interface Database {
function listOrders();
function addOrder();
function removeOrder();
...
}
Then let's say we start out using a MySQL database. So we write a class to access the MySQL database:
class MySqlDatabase implements Database {
function listOrders() {...
}
we write these methods as needed to get to the MySQL database tables. Then you can write your controller to use the interface as such:
$database = new MySqlDatabase();
foreach ($database->listOrders() as $order) {
Then let's say we decide to migrate to an Oracle database. We could write another class to get to the Oracle database as such:
class OracleDatabase implements Database {
public function listOrders() {...
}
Then - to switch our application to use the Oracle database instead of the MySQL database we only have to change ONE LINE of code:
$database = new OracleDatabase();
all other lines of code, such as:
foreach ($database->listOrders() as $order) {
will remain unchanged. The point is - the INTERFACE describes the methods that we need to access our database. It does NOT describe in any way HOW we achieve that. That's what the IMPLEMENTing class does. We can IMPLEMENT this interface as many times as we need in as many different ways as we need. We can then switch between implementations of the interface without impact to our code because the interface defines how we will use it regardless of how it actually works.
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 am building a 3rd-party library that requires a database access. To be more specific, it's an access control library. Currently the biggest problem I am facing is that how do I make it compatible with most frameworks and CMS's?
I could issue queries using a database instance that the developer specifies. This has three problems:
I need an access to a database instance.
The library needs to be able to deal with different database instances (PDO, MySQLi, mysql-resource, postgresql-resource, etc.)
There would be no caching, because the queries do not go through the application (assuming the app uses some).
Or I could just have methods that return the SQL, but is that any better?
The Adapter Design Pattern springs to mind
An “off the shelf” component offers compelling functionality that you would like to reuse, but its “view of the world” is not compatible with the philosophy and architecture of the system currently being developed.
For your concrete problem this means you create a class for your framework that exposes an API with all the method required by your other classes. This is the only interface you will interact it. Then you create adapters for each database you want to support. So your adapter will become the meditator between your framework and the DAL.
Example:
interface DB_Interface
{
public function somethingYourFrameworkUses();
}
class YourDB implements DB_Interface
{
public function setAdapter(DB_Interface $adapter)
{
$this->adapter = $adapter;
}
public function somethingYourFrameworkUses()
{
$this->adapter->somethingYourFrameworkUses();
}
}
The above is your main class. You will only interact with this class from your remaining framework's code. The functionality required to interact with a specific database is contained within a concrete adapter then. You instantiate and inject an adapter at runtime.
class PDO_Adapter implements DBInterface
{
public function somethingYourFrameworkUses()
{
// code to make this function work with PDO
}
}
class MySQLi_Adapter implements DBInterface
{
public function somethingYourFrameworkUses()
{
// code to make this function work with MySQLiAdapter
}
}
Add additional adapters as you see fit.
You could build on top of an existing database abstraction layer like Zend_Db, which will let you write the code once and it'll work everywhere.