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.
Related
After developing a few projects using Codeigniter since 2 years, I stared to learn Laravel.
I downloaded a few projects lo learn how they are coded. As I understood, many of them are using only models, views and controllers which is same as Codeigniter.
But one project has used repositories and interfaces. It is really hard to understand whats going on that project. So what is the usage of repositories and interfaces in Laravel? When should I use them?
I will try to explain as clearly as possible the two concepts.
Interfaces\Contracts
In general OOP interfaces are used to describe which methods/functionalities the class that implements that interface is offering without caring about the actual implementation.
Laravel uses Contracts mainly to separate a service from the actual implementation. To be more clear let's make an example
<?php
namespace App\Orders;
class OrdersCache
{
protected $cache;
public function __construct(\SomePackage\Cache\Memcached $cache)
{
$this->cache = $cache;
}
public function find($id)
{
if ($this->cache->has($id)) {
//
}
}
}
As you can see in this class the code is tightly coupled to a cache implementation (i.e. \SomePackage\Cache\Memcached) so if the API of that Cache class changes our code also must be changed accordingly. The same thing happens if we want to change the Cache implementation with another one (e.g. redis).
Instead of doing that, our code could depend on an interface that is agnostic from the implementation:
<?php
namespace App\Orders;
use Illuminate\Contracts\Cache\Repository as Cache;
class OrdersCache
{
public function __construct(Cache $cache)
{
$this->cache = $cache;
}
public function find($id)
{
if ($this->cache->has($id)) {
//
}
}
}
Now our code is not coupled with any specific implementation because Cache is actually an interface. So basically in our class we are requiring an instance of a class that behaves like described in the Cache interface, but we are not really interested in how it works internally. Doing that if we want to change the cache implementation we could write a class that implements the interface Cache without changing any line of code in our OrdersCache class. Doing that our code is easier to understand and maintain and your packages are a lot more reusable. See the section Loose Coupling in the Laravel documentation for further examples.
Interfaces and Service Container
One of the main features of Laravel is its Service Container, it is used to manage dependencies and performing dependency injection. Please take a look at Service Container definition from Laravel documentation.
Dependency Injection is widely used by Laravel also to bind interfaces to implementation. Let's make an example:
$app->bind('App\Contracts\EventPusher', 'App\Services\RedisEventPusher');
And let our class be
<?php
namespace App\Http\Controllers;
use App\Contracts\EventPusher;
class EventsController extends Controller
{
protected $pusher;
public function __construct(EventPusher $pusher)
{
$this->pusher = $pusher;
}
}
Without declaring anything else we are basically saying everytime that someone need an EventPusher instance, please Laravel, provide an instance of RedisEventPusher class. In this case everytime that your controller is instantiated, Laravel will pass an instance of RedisEventPusher to your controller without specifying anything else.
You can dig into that by looking at Binding Interfaces to Implementation section on the Laravel documentation.
Repositories
Repositories is a concept applicable to the MVC pattern independently from any specific framework. Typically you have your Model that is the data layer (e.g. interacts with the database directly), your Controller that handles the access logic to the data layer and your View that shows the data provided by the Controller.
Repositories instead could be defined as follows:
To put it simply, Repository pattern is a kind of container where data access logic is stored. It hides the details of data access logic from business logic. In other words, we allow business logic to access the data object without having knowledge of underlying data access architecture.
Soruce: https://bosnadev.com/2015/03/07/using-repository-pattern-in-laravel-5
To know how to use them within Laravel please take a look at this great article.
That's all, i hope it helps to clear up your mind.
Interfaces are what any implementing class should call.
interface CanFlyInterface
{
public function fly();
}
Think of it like programming without bothering with logic.
if ($object instanceof CanFlyInterface) {
$obj->fly();
}
Now we could have passed a Bird object, or an Aeroplane object! PHP DOESN'T CARE, so long as it implements the interface!
class Bird implements CanFlyInterface
{
public function fly()
{
return 'flap flap!';
}
}
class Aeroplane implements CanFlyInterface
{
public function fly()
{
return 'roar! whoosh!';
}
}
Your other question, what a Repository class is. It's just a class that keeps all your DB queries in the one place. Check this interface as an example:
interface RepositoryInterface
{
public function insert(array $data);
public function update(array $data);
public function findById($id);
public function deleteById($id);
}
Hopefully this should clear things up for you! Good luck with all your PHP coding :-D
Let's start with the easier one, the interface:
You normally use interfaces to implement classes with required methods:
http://php.net/manual/en/language.oop5.interfaces.php
Laravel's Contracts are a set of interfaces that define the core services provided by the framework. For example, a Illuminate\Contracts\Queue\Queue contract defines the methods needed for queueing jobs, while the Illuminate\Contracts\Mail\Mailer contract defines the methods needed for sending e-mail.
https://laravel.com/docs/5.4/contracts#introduction
When Laravel is running it can check if a class implements a special interface:
if ($cls instanceof IInterface) {
$cls->interfaceFunction();
}
Since Laravel is able to work with queues it will check if the event should be queued or not by checking for an exiting interface.
To inform Laravel that a given event should be broadcast, implement the Illuminate\Contracts\Broadcasting\ShouldBroadcast interface on the event class.
https://laravel.com/docs/5.4/broadcasting#defining-broadcast-events
Repository:
I didn't found that much about this:
Our repository should not have so much knowledge regarding who is providing them data or how they are providing it. https://laravel.com/docs/5.4/contracts#loose-coupling
But I found some other information on a webpage:
a Repository will connect Factories with Gateways
https://code.tutsplus.com/tutorials/the-repository-design-pattern--net-35804
The link will give you more information about the the details.
Hope I could help you :)
First of all, using Repository and Interface in larger application is not only beneficiary in Laravel but in all technology for coding standard as well as for separation of concern.
According to Microsoft (I found best explanation here)
Why to use Repository:
Use a repository to separate the logic that retrieves the data and
maps it to the entity model from the business logic that acts on the
model. The business logic should be agnostic to the type of data that
comprises the data source layer. The repository mediates between the
data source layer and the business layers of the application. It
queries the data source for the data, maps the data from the data
source to a business entity, and persists changes in the business
entity to the data source.
A repository separates the business logic
from the interactions with the underlying data source or Web service.
The separation between the data and business tiers has three benefits:
It centralizes the data logic or Web service access logic. It provides
a substitution point for the unit tests. It provides a flexible
architecture that can be adapted as the overall design of the
application evolves. There are two ways that the repository can query
business entities. It can submit a query object to the client's
business logic or it can use methods that specify the business
criteria. In the latter case, the repository forms the query on the
client's behalf. The repository returns a matching set of entities
that satisfy the query.
For Interface, you have a lot of answers above, hope you have understand.
First of all, repositories and interfaces are not specific to Laravel but common coding standards in most of the languages.
Below Laracasts videos will be useful to understand the basics if you don't mind spend few dollars.
https://laracasts.com/lessons/repositories-and-inheritance
https://laracasts.com/series/object-oriented-bootcamp-in-php
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.
I was going through the Laravel's Illuminate and I noticed it has an interface for nearly every implementation.
What's the exact purpose of this? Does it have any current use, or is it more to make the framework as scaleable as possible?
In software engineering contracts are more valuable than their implementations.
Here's a few reasons:
You can test classes which depend on an interface without relying on an interface implementation (which itself may be buggy).
Example with PHPUnit :
//Will return an object of this type with all the methods returning null. You can do more things with the mock builder as well
$mockInterface = $this->getMockBuilder("MyInterface")->getMock();
$class = new ClassWhichRequiresInterface($mockInterface);
//Test class using the mock
You can write a class which uses a contract without needing an implementation e.g.
function dependentFunction(MyInterface $interface) {
$interface->contractMethod(); // Assume it's there even though it's not yet implemented.
}
Have a single contract but multiple implementations.
interface FTPUploader { /* Contract */ }
class SFTPUploader implements FTPUploader { /* Method implementation */ }
class FTPSUploader implements FTPUploader { /* Method implementation */ }
Laravel offers support of the last one using its service container as follows:
$app->bind(FTPUploader::class, SFTPUploader::class);
resolve(FTPUploader::class); //Gets an SFTPUploader object
Then there's also the fact that its easier to document interfaces since there's no actual implementations in there so they're still readable.
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 will be building a system where a particular object will originate from a web service (SOAP based). It will then be displayed on a web page (via PHP). Under certain circumstances we'll store a copy with some additional information in a local MySQL database. And from there it will be batch processed into Salesforce CRM (again via PHP). We may also subsequently pull the object out of Salesforce for display online. So alot going on. For the most part the object is the same with each subsequent node in the system likely adding a couple of fields specific to it, unique ids mainly.
I'd initially toyed with the idea of encapsulating all the necessary functionality into the one class in PHP which would deal with reading and writing from each of the appropriate sources. This felt like it was over complicating the class, and not a good approach.
I then looked at having just a container class, with no real functionality attached beyond getters and setters. Then creating separate functionality outside of this to deal with the reading and writing between the different sources, simple enough code although tedious to map between all the different field names across the different sources. There is probably a design pattern or two that apply here, but I'm not familiar with them. Any and all suggestions on how to approach this appreciated.
What you are looking is Adapter pattern. You can keep your existing code till you completely change all the classes.
I'd suggest to use a composite memento serializable into XML.
I think they may be several ways to handle that. #EGL 2-101 adapter idea is one way to do it.
Basically, you have several sources, which in O.O. jargon, are different objects. But, you want to treated like if they where a single object.
You may want to make a single class for each source, test the "connection", as if each case was the only way you where going to work with. When you have several of that classes, try to make all classes share some interface, methods or properties:
class AnyConnection
{
public function __construct() {
// ...
}
public function read() {
// ...
}
} // class
class SOAPObject extends AnyConnection
{
public function __construct() {
// ...
}
public function read() {
// ...
}
} // class
class MYSQLObject extends AnyConnection
{
public function __construct() {
// ...
}
public function read() {
// ...
}
} // class
class SalesObject extends AnyConnection
{
public function __construct() {
// ...
}
public function read() {
// ...
}
} // class
Later, use a single class to wrap to all of these source classes.
class AnyObject extends AnyConnection
{
$mySOAPObject;
$myMYSQLObject;
$mySalesObject;
public function __construct() {
// ...
}
public function read() {
// ...
}
} // class
Later, add the code, to select which "connection" you want.
Why not separate data and operations?
Contain the core information into a class C. When web services sends this class, it is encompassed in an object of some class W. The web service pulls C and sends it to persistence layer, which creates and stores P that internally contains C, et.c.,
Akin to how data flows over a TCP/IP stack...
The way I see this after thinking about it a bit would be pretty much a class to play with your object and then serialize it.
I'd probably use something like this:
<?php
class MyObject
{
protected $_data;
public function __construct($serializedObject = null) {
if(!is_null($serializedObject)) {
$this->_data = json_decode($serializedObject);
}
}
public function __get($key) {
return $this->_data[$key];
}
/* setter and other things you need */
public function encode() {
return json_encode($this->_data);
}
public function __toString() {
return $this->encode();
}
}
Then just use it to pass it serialized to your different web services.
I think JSON would do a pretty good job on this one, because you can easily unserialize it fast in so many programming languages and it's so much lighter than XML.
DataMapper pattern is that what you're looking for.
You can have one mapper for each storage mechanism that you use and use them all with one object that represent data to business logic.
Is seems your problem is more of an architectural / design decision that pure implementation detail. (I haven't done PHP for a long while and do not know salesforce but other CRM systems)
I believe the technique/pattern that will work for you is the use of a staging area. This helps especially if you have changing integration needs and also when your source data looks different from your system model or when you have different sources to integrate from. Thus, you import into the staging area and then from the staging into your system. At each place you naturally have to map (can use metadata) and maybe transform/translate data. There will be initial effort to build this, but once it's done the step from staging to your system stays quite static/stable.
Using meta data mapping can address flexibility concerns but adds a bit of complexity on implementation. It all depends on the skills and time you have at hand for your project.
I would not have any association between the objects at all. They are used for different purposes but looks similar. period.
In .NET we use a library called automapper to copy information between different classes (like a business object and a DTO). You can build something similar in PHP, either by using get_object_vars or the reflection API.
myCopyApi.copy($myDTO, $myBO);
Say you retrieve a Car from the webservice. You can store it in a WebserviceCar, which has a property car.
Now, if you want to store that Car in the database, put it in a DatabaseCar, which also has a property car. If you want to put it in Salesforce, put it in a SalesforceCar object, which has a property car.
This way, you have one object which has the common fields and several objects which have storage-specific information.
Assuming that you are thinking about storing the actual object (serialized,encoded or whatever) in a field in the database: From my point of view the object it is never the same in two applications, as business-wise, it serves different purposes. Doing this is a kind of "cutting short" in a case where is no room for "cutting short".
Remember that mainly class represents a "category of objects" which all share same properties and behaviours. So let each application use it's own class as their purpose requires it. What can be created although is, as others suggested and as you thought, the creation of an Adapter or Factory which can be used in all the implied applications as it serves the same business purposes "translation" of objects.
Adapter pattern
Factory pattern