This is just a general question around a solution I'm trying to find.
I have potentially many providers of the same type of service and I need a way to be able to have a default, but then also manually call a switcher method to change them.
Currently, I've bound an Interface to an Implementation via configuration settings and this works well - but it means I can only support one active provider per type of service.
I noticed the Cache::disk() method is really what I'm looking for, but I'm not sure where this type of switch method should be defined.
Current:
interface IProvider {
public function getServiceInfo($args);
public function setServiceInfo($args);
}
class GoldService implements IProvider {
// implementation of the two interface methods
}
class SilverService implements IProvider {
}
// ProviderServiceProvider
public function register()
{
$this->app->bind(
App/IProvider,
App/GoldService
);
}
// Controller
public function getServiceInfo(Service $serviceId)
{
$provider = $app->make('App/IProvider');
$provider->getServiceInfo($serviceId);
}
Want to have.
// What I want to be able to do
public function getServiceInfo(Service $serviceId)
{
// Using a facade
if ($serviceId > 100)
{
Provider::getServiceInfo($serviceId);
}
else
{
Provider::switch('SilverService')
->getServiceInfo($serviceId);
}
}
I know I've thrown in an additional requirement there of the Facade - not sure if I've confused Contracts/Facades here - but essentially I want the interface to enforce the instance methods, but Facade for easy access to the instances.
Not really looking for code here - that'll be the easy part. I'm just not sure I've really grok'd this and looking for a nudge in the right direction..
Using an interface to ensure a service implements the methods you require makes sense.
But with regard to using a different service based on the properties of an object instance; that sounds more like the Factory pattern to me.
http://www.phptherightway.com/pages/Design-Patterns.html
Related
I'm working on something and I've already used some design patterns, but none of them fulfills my needs completely, and that makes me think I might use a combination of patterns, but I'm a little bit stuck so I will explain the situation here and hopefully somebody could add some light about the right way to work on this one. The language I'm working with is PHP 8, in case that it helps or limits on finding a solution.
I have a class that builds, via static methods, GraphQL queries and mutations. I can't give you the exact implementation but it's something like this:
class GraphQLBuilder
{
public static function getSettings(): string
{
return <<<GRAPHQL
query{
settings{
id
name
alias
}
}
GRAPHQL;
}
public static function getSetting(string $id): string
{
return <<<GRAPHQL
query{
setting(id: "$id"){
id
name
alias
}
}
GRAPHQL;
}
public static function setName(string $id, string $name)
{
return <<<GRAPHQL
mutation {
setting(
id: "$id",
name: "$name"
) {
id
name
}
}
GRAPHQL;
}
}
The GraphQL server is migrating to a new version and the field alias will be called aka, but for compatibility reasons they will keep the old field for a year. I need to create a new version of the Builder class that supports the new aka field, so it will have different getSettings() and getSetting($id) methods, but the setName() method will be the same.
My goal is to create a class that works with all the methods used (in the example, getSettings(), getSetting($id) and setName($id, $name)) but fallbacks to a base class for the not implemented methods. I'd use an interface to check that all the methods are covered in the new class.
So far, I've tried to use the strategy pattern by creating a BuilderFactory that returns whether GraphQLBuilder or GraphQLBuilderNewVersion, so the methods could be used at the same way: builder::getSettings(), but that makes me include the setName() method, without any difference, in the GraphQLBuilderNewVersion, and I wouldn't like to do that because I don't want to maintain the same code in different classes.
Another approach was creating an abstract class GraphQLAbstractBuilder that has a static $settingProvider attribute, and a GraphQLBuilderBase that holds all the methods that would be needed to fallback. Both GraphQLBuilder or GraphQLBuilderNewVersion extend from GraphQLBuilderBase and implement their own specific methods, but I'd like that those specific methods are controlled in the interface but they don't have a fallback, so I can make them fail in a controlled way.
I feel like I'm overthinking this and it may be a very straightforward solution, so any advice or tip to make a robust design on this problem will be really appreaciated.
In my laravel project I have following interface, repository and controller.
This is Interface
interface TrainingClassTypeInterfaces
{
public function updateTrainingClassType($id, $request);
}
This is Repository
use App\Models\Trainings\AppTrainingClassType;
class TrainingClassTypeEloquent implements TrainingClassTypeInterfaces
{
protected $model;
public function __construct(AppTrainingClassType $appTrainingClassType)
{
$this->model = $appTrainingClassType;
}
public function updateTrainingClassType($id, $request)
{
$response = false;
$isUpdated = $this->model::where('training_class_id',$id)->update([
'app_id' => $request->app_id
]);
....
}
}
This is controller
class TrainingClassTypesController extends \TCG\Voyager\Http\Controllers\VoyagerBaseController
{
protected $trainingService;
public function __construct(TrainingClassTypeEloquent $trainingClassTypeInterfaces) {
$this->trainingService = $trainingClassTypeInterfaces;
}
public function insertOrUpdate()
{
...
$this->trainingService->updateTrainingClassType($id, $request);
..
}
}
Everything working fine till here
As you can see I am using TrainingClassTypeEloquent's method inside TrainingClassTypesController. But it was returning error something like
Argument 1 passed to ...::__construct() must be an instance of
Basically it was asking me to put instance of Model into TrainingClassTypeEloquent class. Then I did as following
$TCTypes = new AppTrainingClassType();
$TCT = new TrainingClassTypeEloquent($TCTypes);
$TCT->updateTrainingClassType($id, $request);
which was working fine but I was confused that this approach is not proper, there should be some proper way.
After googling I found another solution which is singleton binding, and then I tried following in AppServiceProvider
$this->app->singleton(
\App\Services\Voyager\Eloquent\TrainingClassType\TrainingClassTypeInterfaces::class,
\App\Services\Voyager\Eloquent\TrainingClassType\TrainingClassTypeEloquent::class
);
After adding this singleton binding, I notice script was working without providing model instance into TrainingClassTypeEloquent class.
I would like to know how $this->app->singleton() is working, so in this way my concept would be clear about it. If someone knows then kindly guide me about it.
Thank you so much
It is all about BINDING a service to the service container.
What does $this->app->singleton(); method do?
The singleton method binds a class or interface into the service container so that Laravel can maintain dependency (when using an interface as the constructor parameter).
(Actually Singleton is a design pattern. Singleton implementation always returns the same object on subsequent calls instead of a new instance). So $this->app->singleton(); method returns the same object again and again.
Point to be noted that Laravel doc says:
There is no need to bind classes into the container if they do not
depend on any interfaces. The container does not need to be instructed
on how to build these objects, since it can automatically resolve
these objects using reflection.
But your controller class depends on an interface, so the container needs to be informed and to do this, you need to use this $this->app->singleton(); method but there are other ways around.
Again, at the same time, this TrainingClassTypeEloquent::class has a dependency of AppTrainingClassType::class. But in this case, we do not need to worry about that because Laravel uses Reflection API to maintain its dependency as this class does not use interface as like TrainingClassTypesController::class class.
Once you are done with binding the service to the container, Laravel will then automagically put the service onto the constructor method as an argument where the interface is used.
I hope this would help you. You may find more help from this answer.
You need to register TrainingClassTypeEloquent
$this->app->singleton(TrainingClassTypeInterfaces::class, static function ($app) {
return new TrainingClassTypeEloquent(new AppTrainingClassType());
});
Then you can inject it in your Controller
public function insertOrUpdate(TrainingClassTypeInterfaces $trainingService, $id)
{
$trainingService->updateTrainingClassType($id, request());
}
I'm looking for some direction regarding the following, I'm new to OOP and getting there but think either my lack of understanding is causing me to get stuck in a rabbit hole or I'm just over thinking things too much and being anal.
basically i have a main class called "CurlRequest" which sole purpose is to perform curl requests, providing a url and params it returns me some html. This class works and functions as intended and I'm happy with that.
I use this class for a few projects but for one I then wanted to track the performance of my requests made. attempted, failed, passed etc, so i created a static class for this which manages all my counters. I place counter references like the following at different areas in my CurlRequest class.
PerformanceTracker::Increment('CurlRequest.Attempted');
PerformanceTracker::Increment('CurlRequest.Passed');
PerformanceTracker::Increment('CurlRequest.Failed');
I have around 10 or so of these with my class tracking all kinds of things during the curl request and i also use my PerformanceTracker class in other classes i made.
However like mentioned i only wanted to do this for one of my projects, so find my self in the situation of having my original CurlRequest class and an altered one with performance counters in it.
My question is, is their a way i can use the same class for any project and choose to use the PerformanceTracker class or not. The obvious way i thought of was to pass an $option argument into the class and then have if statements around all the counters, but can't help think its messy.
if ($this->options['perfCounter'] == true ) {
PerformanceTracker::Increment($this->owner . '.CurlRequest.Failed');
}
this also adds a lot of extra code to the class.
I suggest placing the if statement in a separate method
private function handlePerformanceTracker($q)
{
if ($this->options['perfCounter'] == true ) {
PerformanceTracker::Increment($q);
}
}
And call this method instead of your calls to
PerformanceTracker::Increment(...);
Also if you find that you want to track performance differently between your projects it might be useful to change your constructor to accept a callable argument, this way you externalize the actual implementation from the CurlRequest class itself.
public function __construct(..., callable performanceHandler)
Then when you instantiate your class:
$curlRequest = new CurlRequest(..., function($outcome) {
//your implementation
});
You can use inheritance and create a subclass that performs the logging before delegating to the parents methods:
class PerformanceTracker
{
static function Increment($s)
{
echo $s;
}
}
class CurlRequest
{
function get($url){
//preform curl request, save html to variable etc
//dummy vars used here so working example code
$html = 'html here';
$curlError = false;
if($curlError){
$this->error($curlError);
}
return $this->success($html);
}
protected function success($html)
{
return $html;
}
protected function error($curlError)
{
throw new Exception($curlError);
}
}
class LoggingCurlRequest extends CurlRequest
{
function get($url)
{
PerformanceTracker::Increment('CurlRequest.Attempted');
return parent::get($url);
}
function success($html)
{
PerformanceTracker::Increment('CurlRequest.Passed');
return parent::success($html);
}
function error($curlError)
{
PerformanceTracker::Increment('CurlRequest.Failed');
parent::error($curlError);
}
}
$lcr = new LoggingCurlRequest();
$lcr->get('unused in example');
As i have used dummy classes with minimal code to demo the technique the benefit might not be obvious, but in you real code, the methods in the CurlRequest class will be more complex, but the methods in the logging class will remain as two liners, with the log function and the call to the parent method.
Using this technique you can modify the parent class without effecting the derived classes (provided the method signatures dont change), can create other derived classes (how about a CachingCurlRequest) etc.
For the full benefits of OOP you should look into dependency injection and interfaces
From an OOP perspective you could use the 'Null' object pattern. This just means that the dependency used by the CurlRequest class is abstract (possibly an interface?). You would then have Two concrete implementations of PerformanceTracker: the one you have today and one that does nothing (it does not have any behavior). In this way for the one project when you instantiate the CurlRequest class it would use the concrete implementation that has behavior and for all the other projects it would use the concrete implementation with no behavior. All of the code in CurlRequest would look the same but it would have different behavior depending on which concrete implementation it was using
I'm just learning about PHP's interfaces as I have never really used them before, but as I understand it they are only a interface, as they are called, to kind of uphold how classes that implement them are structured?
So for example, if you wanted to make two different classes for two different databases you could do:
class mysql {
public function connect() {
// code here
}
public function getData() {
// code here
}
}
class mongoDB {
public function connect() {
// code here
}
public function getData() {
// code here
}
}
...and that would technically be the same as:
interface database {
public function connect() {
}
public function getData() {
}
}
class mysql implements database {
public function connect() {
// code here
}
public function getData() {
// code here
}
}
class mongoDB implements database {
public function connect() {
// code here
}
public function getData() {
// code here
}
}
...am I right? It's just that using an interface it makes sure you don't go doing something like the below and hence not being able to change databases easily?
class mysql {
public function connect_mysql() {
// code here
}
public function getData() {
// code here
}
}
class mongoDB {
public function connect_mongo() {
// code here
}
public function getData() {
// code here
}
}
Is that pretty much the reasoning behind them?
What the interface does is it standardises what your code can rely on, and at the same time decouples that from a specific implementation. Wow, that sounds complicated. It's easier to illustrate it from the perspective of a user of interfaces:
function (MyDatabaseInterface $db) {
$db->connect();
$db->getData();
}
Type hints are a big part of using interfaces. This function declares that its argument must be an instance of MyDatabaseInterface, in other words, any object that implements MyDatabaseInterface. It is entirely up to you what specific object that is, as long as it implements MyDatabaseInterface. And since in MyDatabaseInterface you have specified the methods connect() and getData(), you can be sure that any object being passed in has these methods and that you can call them.
The other way around, have a look at this function:
/**
* #return MyDatabaseInterface
*/
function foo() {
...
}
It is irrelevant what this function does internally, but it declares that it will return an object of type MyDatabaseInterface, in other words some object that implements MyDatabaseInterface. When you call it, you know what you can rely on:
$bar = foo();
$bar->connect();
$bar->getData();
This function may return an instance of mysql or of mongoDB, it is none of your concern. You simply stick to what was declared in the interface and your code will work regardless of what specific object you get.
An interface literally defines the interface between code. It defines what methods code can safely call on other code, without tying down the specifics to specific classes. Your specific objects could define a ton more methods than are defined in the interface; an interface does not declare a class structure. A class could implement several interfaces at once, meaning it implements all the methods of all the interfaces; each individual interface would then just represent a subset of all the possible methods that could be called on an object.
You should describe specific "tasks" or "abilities" which can be accomplished in an interface, not "classes". It's a good sign if your interface names end with "-able", like Iterable. A class can then implement several interfaces and thereby describe all the things it "can do". You can then require function arguments with a certain "ability" at specific points, as shown in the example code above. This isolates and decouples parts of code from one another, which makes your code more flexible, reusable and adaptable to change.
For a useful real world scenario, imagine a larger development team which is working on a large project. There are several sub-teams, each responsible for a different part of the application. They all sit down together and come up with a general plan. At some point, the code of these separate teams needs to interact with each other. They can define these interfaces upfront:
"I'll need to call some method on your code that gives me the user credentials."
"OK, then you'll need to give me some object from which I can get the foobar."
"Then over here we'll have to talk to Joe's component to send the baz data."
...
They can define the different methods they will need to talk to each other in an interface before any code has been written, then go off and do their own thing. They can rely on code which hasn't even been written yet, because they already decided on what the interface will look like. They can even substitute the real code with mock objects for the time being while Joe is still hammering out his real code, then simply switch it in later with whatever Joe comes up with. And all those techniques are useful even if you're just working by yourself.
I'm currently helping build an API that I would like 3rd party developers to use. This API hooks to a service in the cloud. This service is constantly changing and not currently very reliable. Therefore, I would like to provide in my SDK both real clients and fake ones. Whenever the service is down, developers can simply use the fake client rather than the real one and continue coding.
I've looked at all sorts of design patterns and some addressed my problem nicely. Here is the catch though.. I want to make the code as simple as possible: So let's say my service is called Experia. I want people to be able to just do something like this:
class Experia extends Exp
...
$ex = new Experia(/*initialization parameters*/); //init prameters like user name, password etc
$ex->story()->create($storyArgs);
currently, Experia is a class that extends another class Exp that contains a list of these resources and the files they are available in.. and it also extends a generic class called Client that defines the basic get() and post() methods etc, and basically sets up the client remote url and so on (it wraps around the pest library)
so Exp goes something like this:
class Exp extends Client
{
public function story() {
include_once('classes/User.php');
}
//other resource methods
}
I want to create another class that contains all my fake resources.. something like this:
class ExpFake extends Client
{
public function story() {
include_once('classesFake/User.php');
}
//other resource methods
}
Here is the problem I'm facing. I want Experia to be able to extend either Exp or ExpFake depending on its declaration, without any ugliness.. and by ugliness I mean any extra code that developers using my API will have to use. So for example one thing I tried to do was decouple client from Exp and basically do this
$ex = new Experia(/*... */);
$ex->client = new fakeClient(); //I could also do $ex-> client = new realClient();
but then the problem was that every time I wanted to use call a resource.. I had to specify the client:
$this->client->story()->create($args)
the client part is extra code that i cannot include in my api..
so long story short.. what is the design pattern (or direct way if possible.. in php) that achieves the same result as selectively inheriting from one class or another
so like having the option of doing this:
class Experia extends (either Exp or ExpFake depending on Experia's initialization parameters)
A good way would be an adapter pattern. Your main client is the Exp class, which is what developers use to interact with your service. This class depends on an adapter to connect to your service though. This adapter class is required to be injected when instantiating Exp and is the part that can be mocked if necessary.
class Exp {
protected $adapter;
public function __construct(ExpAdapter $adapter) {
$this->adapter = $adapter;
}
public function foo() {
return $this->adapter->doFoo();
}
}
abstract class ExpAdapter {
abstract public function doFoo();
}
You can then create a real ExpAdapter and a mocked one:
class LiveExpAdapter extends ExpAdapter {
public function doFoo() {
// contact the actual service
}
}
class MockExpAdapter extends ExpAdapter {
public function doFoo() {
return true;
}
}
Instead of extending an abstract class, you can also use an interface specification.
To the developer, this will look like:
$exp = new Exp(new LiveExpAdapter);
// if service is down, use instead:
// $exp = new Exp(new MockExpAdapter);
$exp->foo();
depends on your php version, but I would use traits, in that case
trait Exp {
}
trait ExpFake {
}
class Experia {
use Exp;
}
alternative with drivers is fine as well e.g. define interface and separate drivers or implementations (as with db, when you have different driver classes e.g. mysql, psql etc)