Design pattern where child classes have mandatory methods with arbitrary parameters - php

I often come across problems that seem reasonable to be solved in this way - I'll give a concrete fictional example, but I'd like to know the name, best practices - and whether this pattern is a good idea in general.
Problem
I need to notify subscribed users of arbitrary events. Lets say one of the process evaluates "orders" and users subscribe to that event but to only one type of orders.
Usage of solution
I imagine the code should look something along the lines of this:
<?php
// ...
public function processOrders() {
// ...
(new notifications\orders())->send( $typeOfOrderThatWasJustProcessed );
// ...
}
Implementation
So I create the base notification class:
<?php
abstract class notifications {
abstract public function configurationForm();
abstract public function send();
}
and the child class for this particular use case (syntax is invalid, abstract method signature differs from base class, bear with me):
namespace notifications;
class orders extends \notifications {
public function configurationForm() {
// prepare and return a form that will be rendered to HTML
// where the user chooses type of order that he is interested in
}
abstract public function send($type) {
// fetches needed users using the configuration which
// was provided via the form above
}
}
So each type of notification will have to have arbitrary parameters. They inform the notification object about entities that were processed - so that the notification code can decide itself who to send the emails to.
Treat the $type in this example as a dynamic value - any number of types can be added via database.
As previously stated, this is not even possible with abstract classes in PHP, which way should I look?

I would add the parameters needed via the constructor of the concrete notifications classes, then send does not need to receive any....Kind of like a command object inside an observer scenario...
Of course it depends on if the actual values of the parameters are known at instantiation time... if not maybe some kind of parameter object could be passed into the constructor, such that when the parameters change, the parameter object is updated too (as it is a reference in PHP 5)?
namespace notifications;
class orders extends \notifications {
protected $type;
public function __construct($type) {
$this->type = $type;
}
public function configurationForm() {
//...
}
abstract public function send() {
// do stuff with $this->type
}
}
OR
namespace notifications;
class orders extends \notifications {
protected $parameters;
public function __construct(NotificationParameters $parameters) {
//$parameters might be a subclass of NotificationParameters, like OrderNotificationParameters
$this->parameters = $parameters;
}
public function configurationForm() {
//...
}
abstract public function send() {
// do stuff with $this->parameters->getType(); the value of which might have changed since construction time
}
}
What do you reckon?
UPDATE - using sub classes
Command pattern I believe - http://www.sitepoint.com/understanding-the-command-design-pattern/
namespace notifications;
abstract class orders extends \notifications {
abstract public function send() {
// do stuff with $this->type
}
}
class TypeAOrders extends orders {
public function send() {
// do Type A stuff
}
}
class TypeBOrders extends orders {
public function send() {
// do Type B stuff
}
}
....
public function processOrders() {
// ...
$commandBuilder->getNotification(typeOfOrderThatWasJustProcessed)->send();
//$commandBuilder knows which object to build depending on the type and pass any relevant parameters into the constructor...
// ...
}

Related

Can I use autowiring for a private method within a controller class?

In Symfony 5.4, there's the very nimble autowiring that enables to easily access to custom repository methods inside a controller:
private function getPageContent(PageVisiteurRepository $pageVisiteur)
{ /* ... */ }
But now in the getPageContent() method, how can I add the parameter $pageSource? When I call the function, it asks for two parameters now, and counts the dependency injection as a parameter:
private function getPageContent(PageVisiteurRepository $pageVisiteur, $pageSource)
{ /* ... */ }
public function appPage(): Response
{
$pageContent = $this->getPageContent('My Page Source');
// ...
}
Doesn't work.
I stumble on this problem now and then on various cases that call to create a custom class in a controller that needs at the same time to call the repository class and to have parameters.
What's the proper way to deal with this question in recent Symfony versions?
To give some context, here I have an app where I want to include specific page content that is stored in the database as an addendum to the already existing application page, using a custom request stored in my PageVisiteurRepository.
You cannot use autowiring from private methods.
Autowiring the controller methods directly is a special case of autowiring, and works only for controller methods (e.g. methods that handle a "route").
But generally, for autowiring you'd use the constructor:
class Whatever {
public function __construct(private PageVisiteurRepository $repository) {}
private function foo(string $title) {
$something = $this->repository->getSomethingFromTheRepo($title);
// do something with $something
return $foo;
}
public function pageController($pageSource): Response {
return new Response($this->foo($pageSource));
}
}
You could do the same injecting the repo directly in the controller method:
class Whatever {
private function foo(string $title, PageVisiteurRepository $repository) {
$something = $repository->getSomethingFromTheRepo($title);
// do something with $something
return $foo;
}
public function pageController($pageSource, PageVisiteurRepository $repository): Response {
return new Response($this->foo($pageSource, $repository));
}
}

design pattery strategy with access to parent class

I want to implement the strategy design pattern using php:
interface dummy_function {
public function render();
}
class a implements dummy_function {
public function render() {
echo "class a\n";
// I want to acess x_main::dummy like: echo parent::dummy
}
}
class b implements dummy_function {
public function render() {
echo "class b\n";
// I want to acess x_main::dummy like: echo parent::dummy
}
}
class x_main {
public $dummy = "hello world";
public function setX_Function( dummy_function $funcname ) {
$this->x_function = $funcname;
}
public function render() {
$this->x_function->render();
}
}
$test = new x_main();
$test->setX_Function( new a() );
$test->render();
Inside my classes I want to access to some methods and variables defined in the main class. Unfortunatelly "parent" does not work to access contents from the class "x_main" inside the implementation classes.
A way i found is to give $this as parameter to the method "render", like:
class x_main {
[...]
public function render() {
$this->x_function->render( $this );
}
}
class a implements dummy_function {
public function render( $mainclass ) {
echo "class a\n";
echo $mainclass->dummy;
}
}
The next way i testest is to set the variable from the class main direcly into the implemented function, like:
class x_main {
[ ... ]
public function setX_Function( dummy_function $funcname ) {
$this->x_function = $funcname;
$this->x_function->dummy = $dummy;
}
}
class a implements dummy_function {
public function render() {
echo "class a\n";
echo $this->dummy;
}
}
Both solutions work, but I feel a bit confused if that's the best way to implement my desired idea. It looks extremly like a workaround but not like a real OO-programming.
I'm looking forward for your ideas.
Rehashing the comments above:
The two classes aren't related in any way, they certainly don't have a
parent relationship. One object holding an instance of another object
does not mean these two objects are in any sort of relationship with
one another. You simply need to explicitly pass data into your
dummy_function instance; e.g.: public function render(array $data).
Response:
In my first solution I put the whole mainclass as parameter to the
render function. So this is a solution that will work in any case. But
if there is definitivly no relationship between these two objects I
prefer my second solution by setting the parameters directly with
$this->x_function->dummy = $dummy;
Sorry to tell you that you're wrong there. Implicitly setting a property on an object is in no way a defined interface. And I'm not using this word in the sense of PHP's interface keyword, I mean this in the broader sense of specifying how two pieces of code can interact and cooperate.
You've done a good job of specifying and using an interface for the render() function, this greatly decreases code coupling and increases flexibility and testability. Now you're destroying this again by using undefined and brittle property assignments.
You need to make the passing data into render aspect part of your interface specification. For example:
interface dummy_function {
public function render(array $data);
}
Or:
interface dummy_function {
public function setData(array $data);
public function render();
}
Or better:
interface DummyData {
/**
* #return string
*/
public function getDummyData();
}
interface DummyRenderer {
public function render(DummyData $data);
}
With this you're:
explicitly specifying what format your data is in (string)
codifying where render() can get access to such data (it'll receive a DummyData object which has a getDummyData() method)
You don't need to guess what property names are involved or what structure the passed object has.

Real world implementation of interfaces

This question might sound obvious and might be stupid as well. But I am trying to figure out why do I need to use interfaces? I think I can handle most of the things which interfaces do using classes then what's the point of using them? It's true that I might end up in problems if I don't interfaces but I am trying to figure out what problems are caused by not using interfaces?
One use of interfaces is that they allow us to define behaviors and put restrictions on of classes which implement them.
Another use is that interface work as types and I can use interfaces for type hinting as shown below.
//Java example
public interface IPaintable{
void Paint(System.Drawing.Color color);
}
public void Paint(IPaintable item, System.Drawing.Color color){
item.Paint(color);
}
But are there any other use of interfaces in PHP?
I.e. What advantages do I get by using interfaces in the code below.
//Non interface implementation
<?php
class DBPersonProvider
{
public function getPerson($givenName, $familyName)
{
/* go to the database, get the person... */
$person = new Person();
$person->setPrefix("Mr.");
$person->setGivenName("John");
return $person;
}
}
/* I need to get person data... */
$provider = new DBPersonProvider();
$person = $provider->getPerson("John", "Doe");
echo($person->getPrefix());
echo($person->getGivenName());
?>
//Implementation with interface
<?php
interface PersonProvider
{
public function getPerson($givenName, $familyName);
}
class DBPersonProvider implements PersonProvider
{
public function getPerson($givenName, $familyName)
{
/* pretend to go to the database, get the person... */
$person = new Person();
$person->setPrefix("Mr.");
$person->setGivenName("John");
return $person;
}
}
/* I need to get person data... */
$provider = new DBPersonProvider();
$person = $provider->getPerson("John", "Doe");
echo($person->getPrefix());
echo($person->getGivenName());
?>
I write a nice library that interacts with the database. And I use MySQL. When you purchase my library, you know it's MySQL based but you roll with SQL Server. I was considerate enough to create interfaces for the Database access. And I provided an implementation for MySQL. Now you can implement your own SQL Server wrapper around my database access interface, and then use it as a __construct() argument for the classes in the library you will use to change move storage to SQL Server.
Interfaces are very useful for library / reusable code writers like me :) They are code contracts that have to be obeyed. You know that any class that implements them WILL have a set of functions exactly as the Interface declared them. And you can also statically type them in function arguments like function(MyInterface $Object) which enforces, at PHP compiler level, that $Object must be implementing MyInterface.
PS: Abstract classes are good enough for the rest of self-written code consuming developers...
UPDATE:
/**
* Database Access functionality blueprint.
*/
interface IDatabaseAccess {
public function Connect();
public function Query();
public function Fetch();
}
/**
* Database Access functionality implementation for MySQL.
*/
class MySqlDatabaseAccess implements IDatabaseAccess {
public function Query(){
// do mysql stuff
}
public function Fetch(){
// do mysql stuff
}
}
/**
* Database Access functionality implementation for SQLServer.
*/
class SqlServerDatabaseAccess implements IDatabaseAccess {
public function Query(){
// do sqlserver stuff
}
public function Fetch(){
// do sqlserver stuff
}
}
/**
* Database Access consumer that's database system agnostic.
*/
class DatabaseAccessConsumer {
protected $_Provider = null;
public function __construct(IDatabaseAccess $Provider){
$this->_Provider = $Provider;
$this->_Provider->Connect();
}
public function Query(){
return $this->_Provider->Query();
}
public function Fetch(){
return $this->_Provider->Fetch();
}
}
^ code that should speak for itself.
Interfaces actually provide less features than abstract classes (you cannot implement anything).
But they resolve the problem of multiple inheritance. Most modern language do not allow a class to derive more than one class. By using an interface, which does not implement any method, you are sure there is no ambiguity when you invoke a method from the interface (because there is no implementation).
Example (syntactically not valid):
class A {
public foo() {
echo 'I am A and I foo';
};
public
}
class B {
public foo() {
echo 'I am B and I foo';
}
}
class C extends A, B { // invalid
public bar() {
foo(); // which one? A's or B's?
}
}
Second example:
class A {
public foo() {
echo 'I am A and I foo';
};
}
interface iB {
public foo();
public bar();
}
interface iC {
public foo();
public qux();
}
class D extends A implements iB, iC {
public bar() {
foo(); // no ambiguity, this is A::foo(), even if the method is also declared in the interfaces
}
public qux() {}
}
Interfaces are just blueprints of classes - they are ways of saying "If you are going to be doing something with this type of class, it must have this and do this." It allows you to control - to an extent - what another class will have/do at a minimum for a given situation. Not every situation calls for an iterface. Interfaces are best used in situations when you need to have some control over the basic code of certain classes but you may not be the one writing them. If you know that the extended classes will have x properties and y methods, then you can do basic future class support.

Overriding methods in PHP?

In other OO languages like Java we can override a function, possible using keywords/annotations like implements, #override etc.
Is there a way to do so in PHP? I mean, for example:
class myClass {
public static function reImplmentThis() { //this method should be overriden by user
}
}
I want user to implement their own myClass::reImplementThis() method.
How can I do that in PHP? If it is possible, can I make it optional?
I mean, if the user is not implementing the method, can I specify a default method or can I identify that the method is not defined (can I do this using method_exists)?
<?php
abstract class Test
{
abstract protected function test();
protected function anotherTest() {
}
}
class TestTest extends Test
{
protected function test() {
}
}
$test = new TestTest();
?>
This way the class TestTest must override the function test.
Yes, there is. You have the option to override a method by extending the class and defining a method with the same name, function signature and access specifier (either public or protected) it had in the base class. The method should not be declared abstract in the base class or you will be required to implement it in the derived class. In you example it would look something like this:
class MyClass {
public static function reImplmentThis() { //this method should be overriden by user
}
}
class MyDerivedClass extends MyClass {
public static function reImplmentThis() { //the method you want to call
}
}
If the user does not overrides it, MyDerivedClass will still have a reImplmentThis() method, the one inherited from MyClass.
That said, you need to be very careful when invoking extended static methods from your derived class to stay out of trouble. I encourage you to refactor your code to extend instance methods unless you have a very specific need to extend static classes. And if you decide there is no better way than extending static classes please be sure to understand Late Static Binding pretty well.
Yes, its possible to check if the method is implemented or not and get a whole lot more of information about a class using PHP Reflection.
This touches on several OOP subjects.
First, simply overriding an method declared in a parent class is as simple as re-declaring the method in an inheriting class.
E.g:
class Person {
public function greet(string $whom) {
echo "hello $whom!";
}
}
class Tommy extends Person {
public function greet(string $whom = "everyone") {
echo "Howdy $whom! How are you?";
}
}
$a = new Tommy();
$a->greet('World');
// outputs:
// Howdy World! How are you?
If on the overriding method you wan to reuse the logic of the overriden one, it's just a matter of calling the parent's method from the extending class::
class Tommy
{
public function greet(string $whom)
{
// now with more emphasis!!!
echo parent::greet(strtoupper($whom)) . "!!!!";
}
}
Now Tommy::greet() calls Person::greet(), but modifies the result before returning it.
One thing to note is that overriding methods have to be compatible with the overriden one: the method visibility can't be more restrictive than the original one (it's OK to increase visibility), and the number and type of required arguments can't conflict with the original delcaration.
This works, because the type of the arguments does not clash with the original, and we have less required arguments than on the parent:
class Leo extends Person {
public function greet(string $whom = "gorgeous", string $greet = "Whatsup" ) {
echo "$greet $whom. How are you?";
}
}
But this doesn't, since there are additional required arguments. This would make impossible to switch the original class for this one transparently, and thus would throw a Warning:
class BadBob extends Person {
public function greet(string $whom, string $greet ) {
echo "$greet $whom. How are you?";
}
}
Additionally, you mention in your question that "this method should be overriden by the user". If you require client classes to actually implement the method, you have a couple of options:
Abstract classes & methods
These are methods where the implementation is left empty, and that extending classes have to implement to be valid. In we changed our original class Person to:
abstract class Person {
public function greet(string $whom) {
echo "hello $whom!";
}
public abstract function hide();
}
Since now the class contains an abstract method, it needs to be declared as an abstract class as well.
Now it is not possible to instantiate Person directly, you can only extend it in other classes.
Now all our existing Person extending classes would be wrong, and trying to execute the previous code would throw a fatal error.
An example of a valid class extending Person now would be:
class Archie extends Person {
public function hide() {
echo "Hides behind a bush";
}
}
Any class that extends Person must declare a public hide() method.
Interfaces
Finally, you mention interfaces. Interfaces are contracts that implementing classes have to fulfill. They declare a group of public methods without an implementation body.
E.g.:
interface Policeman {
public function arrest(Person $person) : bool;
public function help($what): bool;
}
Now we could have class that extended Person and implemented Policeman:
class Jane extends Person implements Policeman {
public function hide() {
echo "Jane hides in her patrol-car";
}
public function arrest(Person $person): bool{
// implement arrest method
return false;
}
public function shoot($what): bool {
// implements shoot() method
return false;
}
}
Importantly, while it's possible to extend only one class (there is no multiple inheritance in PHP), it is possible to implement multiple interfaces, and the requirements for each of those have to be fulfilled for the class to be valid.

Enforcing call to parent method

Is there anyway (or a pattern) to enforce a call to a parent method?
I have an abstract class like so:
abstract class APrimitive{
public function validate(){
//Do some stuff that applies all classes that extend APrimitive
}
}
Then I have classes that extend upon the APrimitive "base":
class CSophisticated extends APrimitive{
public function validate(){
//First call the parent version:
parent::validate();
//Then do something more sophisticated here.
}
}
The problem is that if we come back to the code in a few months time, and create a few more classes like CSophisticated with a validate() method, there is a possibility that we might forget to make a call to parent::validate() in that method.
Note that some CSophisticated classes may not have the validate() method, so the parent version will be called.
I understand that it is possible to just put in a comment somewhere, to remind the programmer to call parent::validate(), but is there a better way? Perhaps an automated way to throw an exception if the call to parent::validate() was not made in the validate() method would be nice.
You can enforce the call with the following:
abstract class APrimitive{
final public function validate(){
//do the logic in validate
overrideValidate();
}
protected function overrideValidate(){
}
}
class CSophisticated extends APrimitive{
protected function overrideValidate(){
}
}
Now only calls to validate are permitted, which will in turn call your overridden method. The syntax may be a little off (PHP is not my language of choice) but the principle is applyable to most OOP languages.
FURTHER EXPLANATION:
abstract class APrimitive{
public function validate(){
echo 'APrimitive validate call.';
overrideValidate();
}
protected function overrideValidate(){
}
}
class CSophisticated extends APrimitive{
protected function overrideValidate(){
echo 'CSophisticated call.';
}
}
CSophisticated foo;
foo.overrideValidate(); //error - overrideValidate is protected
foo.validate(); //
Output:
APrimitive validate call.
CSophisticated call.
The function call basically does the following:
foo.validate() -> APrimitive.validate() -> ASophisticated.overrideValidate() (or APrimitive.overrideValidate() if it wasn't overriden)
You're looking for The Template Method pattern.
This pattern allows you to modify an operation in some way through sub-classing but ensures that the base class is always involved.
class Base {
//declared final so it can't be overridden
public final function validate() {
//perform base class operations here
//then forward to the sub class
$this->doValidate();
//do some more base class stuff here if needed
}
//override this method to alter validate operation
protected function doValidate(){
//no-op in base
}
}
class Sub {
protected function doValidate() {
//if required
//make the sub-class contribution to validate here
}
}

Categories