I have the following class in PHP with all static methods:
class Foo {
public static function a {
}
public static function b {
}
public static function c {
}
public static function d {
}
public static function e {
}
}
Is there a way to create a hook to fire before calling any of the methods in class Foo i.e. like a before hook? I need some logic, and don't want to have to add that logic to every static function like:
class Foo {
private static function init() {
// pre logic here
}
public static function a {
Foo::init();
}
public static function b {
Foo::init();
}
public static function c {
Foo::init();
}
public static function d {
Foo::init();
}
public static function e {
Foo::init();
}
}
What you want is called an Aspect-Oriented Programming. It allows to define an advice before method call, property access, class initialization, etc.
However, this technique is not used widely in PHP due to its complexity. I can suggest your an example with Go! AOP Framework.
class AutoInitializationAspect implements Aspect
{
/**
* This advice intercepts an execution of static methods
*
* We use "Before" type of advice to initialize the state
*
* #param MethodInvocation $invocation Invocation
*
* #Before("execution(public Foo::*(*))", scope="target")
*/
public function beforeMethodExecution(MethodInvocation $invocation)
{
$class = $invocation->getThis(); // will be the class name
$class::init(); // access to the private scope of class
}
}
Visit http://demo.aopphp.com/?showcase=loggable for demo (see LoggingDemo::runByName() static method intercepted)
I guess you can use __callStatic() magic method to achieve.
public static function __callStatic($name, $arguments)
{
// pre logic here
switch($name)
{
case 'a':
// do something
break;
case 'b':
// do something
break;
}
}
Basic answer: no, there is no such thing in plain PHP.
However, you can try several options:
You can call your methods like aSomeSuffix, bSomeSuffix, etc., and call them via __callStatic method computing that suffixed name on-the-fly.
Pros:
Single handler
Cons:
Your IDE won't see those methods until you explicitly write them down via phpDoc
Extra work and big pile of places to make a mistake (arguments passing by reference, missing method handling, etc.)
You can try Go library that introduces aspect-oriented programming in PHP claims to be able to intercept static calls. I've never used it (though i've heard lots of good responses about it) and don't know anything about performance drops and/or caveats using it, but it seems to be matching your case. I guess, this would still require to write an annotation for every method, but it will result in single handler.
Call initialization method in every method. This is what you're trying to avoid and not an option, i guess, just because it's violates DRY.
Related
I've been trying to understand how static scope works in the context of a trait. A great explanation is here: https://stackoverflow.com/a/56935557/2137316 but it doesn't quite address my concern.
I'm attempting to create a trait for unit tests possessing a property that more or less serves as global flag. The goal is for it to prevent unnecessary reruns of its behavior if a previous test in a given run has already triggered it.
trait CreateDatabase
{
protected static bool $hasRun = false; //We don't want to waste time rebuilding the database in each test
protected runDb(): void
{
if (!self::$hasRun) {
//Do stuff...
}
self::$hasRun = true;
}
}
class SomeTestClass
{
use CreateDatabase;
/**
* #test
**/
public function canRunSomeTest()
{
$this->runDb();
//Test stuff...
}
}
The related post talks about trait context and would seem to suggest that self in this context refers to the 'context' of SomeTestClass, meaning SomeOtherTestClass would have no awareness that the database has already been created. The conclusion would then seem to be that the way to achieve the effect I'm going for would be for is to replace
self::$hasRun = true;
with
CreateDatabase::$hasRun = true;
Even though that line is being executed within the trait explicitly being referenced. The purpose being, to talk to the more-global trait context rather than that of the class using it.
The problem is, Php8, via my IDE, is fussing at me over that decision:
Calling static trait member directly is deprecated. It should only be accessed on a class using the trait.
Usually when my tooling resists me, it means there's something flawed about the overall approach, but I'm not seeing it yet. Wondering if anyone has any insight.
Use trait as proxy here:
class CreateDatabase
{
protected static bool $hasRun = false;
public static function runDb(): void
{
if (!self::$hasRun) {
//Do stuff...
}
self::$hasRun = true;
}
}
trait CreateDatabaseTrait
{
public static function runDb(): void {
CreateDatabaseTrait::runDb();
}
}
class SomeTestClass
{
use CreateDatabaseTrait;
/**
* #test
**/
public function canRunSomeTest()
{
self::runDb();
//Test stuff...
}
}
Im working on a project where we're creating many objects throughout the code base.
For some objects thus we decided to use factories to control the process of creating the objects and all their dependencies. This is an example of what we are trying to do:
class CreateBranchFactory implements CreateBranchInterface {
private $branch;
public function __construct() {
$this->branch = new Branch();
$this->branch->scenario = 'create';
}
public function createBranch($branchForm) {
$this->branch->attributes = $branchForm->attributes;
//Example of all the things that I need to do after creating my object
$this->setOfficialNameAndPrinterName($branchForm->official_name, $branchForm->printer_name, $branchForm->name);
$this->createDependencies1();
$this->someOtherFunction();
return $this->branch;
}
public function setOfficialNameAndPrinterName($offName, $printerName, $branchName) {
$this->branch->official_name = $offName ?? $branchName;
$this->branch->printer_name = $printerName ?? $branchName;
$this->branch->save();
}
public function createDependencies1() {
}
And to have a proper contract I created an interface for this. This interface specifies the functions that should be defined
interface CreateBranchInterface {
public function setOfficialNameAndPrinterName(String $offName, String $printerName, String $branchName);
public function createDependencies1();
}
My problem though, is that the contract is specifying all the functions that should be defined, but isnt controlling which functions should get called. Is there any design pattern that I can use, that makes sure that those functions get called??
You can't create such contract by using interfaces - interfaces specifies which methods and how you can call. Calling all these methods is part of implementation, which cannot be provided by interface. You need to create abstract class with implementation and use final keyword to disallow overriding it:
abstract class CreateBranch {
abstract protected function getBranch(): Branch;
final public function createBranch($branchForm) {
$this->getBranch()->attributes = $branchForm->attributes;
//Example of all the things that I need to do after creating my object
$this->setOfficialNameAndPrinterName($branchForm->official_name, $branchForm->printer_name, $branchForm->name);
$this->createDependencies1();
$this->someOtherFunction();
return $this->getBranch();
}
abstract public function setOfficialNameAndPrinterName(String $offName, String $printerName, String $branchName);
abstract public function createDependencies1();
abstract public function someOtherFunction();
}
consider the following:
class A
{
public static function bark()
{ echo 'woof'; }
}
class B extends A
{
public static function speak()
{ echo 'hello'; }
}
A::speak();
// Fatal error: Call to undefined method A::speak()
How is one supposed to extend a class with methods that you need to be globally available within that class with methods that are not yet known, but are loaded at run-time, depending on the flow of your application?
Yes sure we can make traits and put use in the class like:
trait B
{
public static function speak()
{ echo 'hello'; }
}
class A
{
use B;
public static function bark()
{ echo 'woof'; }
}
A::speak();
// hello
but then use B is not called dynamically, hence you will have to update class A with every new trait available - manually.
This is absurd, why force developers to break their brain in trying to accomplish something so fundamentally simple?
Does anyone have an idea how this can be done in a clean way? I mean I have seen some impressive methods by using Singletons, namespaces, callbacks and the works, but in each case it requires a lot more code and repetitive programming than what is really needed.
Either that or i'm missing the boat completely haha!
Thanks in advance, your help will be appreciated and voted generously.
I think with some creativity you could make use of the __call magic method.
You could do something like this:
class A
{
/**
* #var array
*/
protected $methods = [];
public function __call($name, $arguments)
{
if (!empty($this->methods[$name]) && is_callable($this->methods[$name])) {
return call_user_func_array($this->methods[$name], $arguments);
}
}
public function addMethod($name, Closure $method)
{
$this->methods[$name] = $method;
}
}
// get class instance (A have no methods except of addMethod)
$instance = new A();
// add methods on runtime
$instance->addMethod('sum', function($num1, $num2) {
return $num1 + $num2;
});
$instance->addMethod('sub', function($num1, $num2) {
return $num1 - $num2;
});
// use methods exactly the same way as implemented fixed on class
echo $instance->sum(2, 2);
echo $instance->sub(3, 2);
Of course you could use also __callStatic for static methods. And if you want to get it a bit more complex also could use the concept of Dependency Injection to add objects instead of methods. Then search the called method through the injected objects and call it when it's found.
I hope this give you at least a good idea.
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.
I've been reading through Effective Java by Joshua Bloch. I also develop in PHP and I wanted to implement the builder pattern outlined in item 2, but PHP doesn't have inner classes. Is there any way to achieve this pattern in PHP, keeping the constructor for the product private?
Since PHP does not support inner classes, there must be a public method on the product class that creates an instance of it. Consider the following PHP classes:
<?php
class NutritionalFactsBuilder {
private $sodium;
private $fat;
private $carbo;
/**
* It is preferred to call NutritionalFacts::createBuilder
* to calling this constructor directly.
*/
function __construct($s) {
$this->sodium = $s;
}
function fat($f) {
$this->fat = $f;
return $this;
}
function carbo($c) {
$this->carbo = $c;
return $this;
}
function getSodium() {
return $this->sodium;
}
function getFat() {
return $this->fat;
}
function getCarbo() {
return $this->carbo;
}
function build() {
return new NutritionalFacts($this);
}
}
class NutritionalFacts {
private $sodium;
private $fat;
private $carbo;
static function createBuilder($s) {
return new NutritionalFactsBuilder($s);
}
/**
* It is preferred to call NutritionalFacts::createBuilder
* to calling this constructor directly.
*/
function __construct(NutritionalFactsBuilder $b) {
$this->sodium = $b->getSodium();
$this->fat = $b->getFat();
$this->carbo = $b->getCarbo();
}
}
echo '<pre>';
var_dump(NutritionalFacts::createBuilder(10)->fat(23)->carbo(1)->build());
echo '</pre>';
?>
Note that in the above example the constructor of NutritionalFacts is public. Due to the constraints of the language, however, having a public constructor is not at all bad. Since one must call the constructor with a NutritionalFactsBuilder, there are only a limited number of ways to instantiate NutritionalFacts. Let's compare them:
// NutritionalFacts Instantiation #0
$nfb = new NutritionalFactsBuilder(10);
$nfb = $nfb->fat(23)->carbo(1);
$nf0 = new NutritionalFacts($nfb);
// NutritionalFacts Instantiation #1
$nfb = new NutritionalFactsBuilder(10);
$nf1 = $nfb->fat(23)->carbo(1)->build();
// NutritionalFacts Instantiation #2
$nf2 = NutritionalFacts::createBuilder(10)->fat(23)->carbo(1)->build();
// NutritionalFacts Instantiation #3
// $nf3 = (new NutritionalFactsBuilder(10))->fat(23)->carbo(1)->build();
To leverage function chaining to its fullest extent, "NutritionalFacts Instantiation #2" is the preferred usage.
"NutritionalFacts Instantiation #3" shows another nuance of PHP syntax; one cannot chain a method on a newly instantiated object. Update: In PHP 5.4.0, there is now support for the syntax in "NutritionalFacts Instantiation #3." I haven't tested it yet though.
Making the Constructor Private
You could make the constructor private, but I wouldn't recommend it. If the constructor were made private, a public, static factory method would be necessary, as in the following code snippet. Looking at the below code, we might as well make the constructor public instead of introducing indirection just to make the constructor private.
class NutritionalFacts {
private $sodium;
private $fat;
private $carbo;
static function createBuilder($s) {
return new NutritionalFactsBuilder($s);
}
static function createNutritionalFacts($builder) {
return new NutritionalFacts($builder);
}
private function __construct($b) {
$this->sodium = $b->getSodium();
$this->fat = $b->getFat();
$this->carbo = $b->getCarbo();
}
}
Immutability is good and definitely something to strive for, this applies to PHP as it does to any other language no matter what. Immutability gives you certainty that you do not have to fear that the instance suddenly mutates without you knowing.
That being said, there is an easy way to implement the builder pattern to build immutable objects even without inner classes (although available now with PHP 7).
The first important building block is a common base class for the actual immutable class and the builder. This allows them to access each others properties. Something that is also known as friend classes or solvable through extended access modifiers in other languages, something PHP does not have. Note that the clone ability is restricted, it makes no sense to clone immutable objects but more about the protected modifier later.
abstract class NutritionalFactData {
protected $sodium = 0;
protected $fat = 0;
protected $carbo = 0;
protected function __clone() {}
}
The immutable class is straight forward with stupid example getters and the default constructor. Note the final modifier for the class itself and that it is not aware of the builder class at all.
final class NutritionalFacts extends NutritionalFactData {
public function getSodium() {
return $this->sodium;
}
public function getFat() {
return $this->fat;
}
public function getCarbo() {
return $this->carbo;
}
}
Now the actual builder implementation. Note how we operate directly on an instance of the immutable class and that we simply clone it when the build method is called. This ensures that later calls to the setters of the builder will not alter the instances that were previously built and ensures that no receiver of such an instance has to take care of the cloning on their own.
final class NutritionalFactBuilder extends NutritionalFactData {
private $nutritional_facts;
public function __construct() {
$this->nutritional_facts = new NutritionalFacts;
}
public function build() {
return clone $this->nutritional_facts;
}
public function setSodium($sodium) {
$this->nutritional_facts->sodium = $sodium;
return $this;
}
public function setFat($fat) {
$this->nutritional_facts->fat = $fat;
return $this;
}
public function setCarbo($carbo) {
$this->nutritional_facts->carbo = $carbo;
return $this;
}
}
For completeness a usage example:
var_dump(
(new NutritionalFactBuilder)
->setSodium(21)
->setFat(42)
->build()
);
Here is the runnable example.
I think it is obvious that we can now implement as many builder implementations as we like. Not really needed for this example but we can think of other constructs where many more properties are involved. Like the car example given on (the very bad) builder pattern article of Wikipedia. We might want to have pre-configured builders for known car categories.
abstract class CarParts {}
final class Car extends CarParts {}
abstract class CarBuilder extends CarParts {
abstract public function build(): Car;
}
final class CompactCarBuilder extends CarBuilder {}
final class SportsCarBuilder extends CarBuilder {}
final class RaceCarBuilder extends CarBuilder {}
In the Gang of Four description of the Builder pattern, you'll find no requirement for an inner class. The key feature is the aggregate relationship between the Director and Builder interface that provide a "blueprint" for putting together a series of Product implementations.
You can find lots of examples of the PHP Builder pattern here:
http://www.php5dp.com/category/design-patterns/builder/
Cheers,
Bill