Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have the following code in place.
Interface Vehicle which has a method calculateDistance.
Class Car implements Vehicle
Class Bicycle implements Vehicle
Class MotorCycle implements Vehicle
What I want to do next is a method in my controller that calls every class that implements Vehicle and get the values from calculateDistance.
What would be the best way/design pattern to achieve this?
At this moment I am just calling all the classes that implement the interface Vehicle (via ReflectionClass) and loop over them to call this method.
The best way is to implement CompilerPass. Here is an example .
So, create a registry class (TransportChain class in that example), interface, and all classes that implements that interface, define them as services and give them tag name.
After that, you can call that registry service in your action, and call your desired method by each service.
Basic example:
interface
interface SomeInterface {
public function doSomething();
}
Service 1:
class First implement SomeInterface {
public function doSomething() {
// do smth
}
}
Service 2:
class Second implement SomeInterface {
public function doSomething() {
// do smth
}
}
Registry class:
class MyRegistry
{
private $services = [];
public function addMyService($service)
{
$this->services[] = $service;
}
public function all()
{
return $this->services;
}
}
CompilerPass:
...
$myServices = $container->findTaggedServiceIds('my_tag');
if (empty($myServices)) {
return;
}
$registry = $container->getDefinition('my_registry');
foreach ($myServices as $key => $myService) {
$registry->addMethodCall('add', [new Reference($key)]);
}
...
After clearign the cache, you can call them in your action:
...
foreach ($this->get('my_registry')->all() as $myService) {
$myService->doSomething();
}
...
The whole other stuff, like declaring services, give them tag name, registering your compiler pass has been written here.
Related
I was wondering if you could help me with the following question. First of all, I would like to tell you that if I am asking this question here, it is because I have already tried many options and none have worked for me. It turns out that I am developing a package with Laravel and I am using Laravel's dependency injection. But I am at a crossroads from which I have not found a way out. I'm trying to get the instance of a class in an intermediate method from a method chain, let me explain. Here is the code very similar to what I have:
PackageServiceProvider.php
<?php
class PackageServiceProvider extends ServiceProvider
{
public function register()
{
$this->configureBindings();
}
private function configureBindings()
{
$this->app->when(A_Class::class)->needs(B_Interface::class)->give(function () {
return new B_Class();
});
}
...
A_Class.php
<?php
class A_Class implements A_Interface
{
private $b_interface;
public function __construct(B_Interface $b_interface)
{
$this->b_interface = $b_interface;
}
public function create($arg1, $arg2)
{
return $this->b_interface->method_1()->call_another_method_from_another_class();
}
}
A_Interface.php
<?php
interface A_Interface extends Arrayable, Rendereable
{
public function create($arg1, $arg2);
...
}
<?php
class B_Class implements B_Interface
{
public function __construct()
{
// Here is the question...
// How could I get here the instance of the class A_Class?
}
public function method_1()
{
// should return another class instance
}
public function method_2()
{
// should return another class instance
}
}
B_Interface.php
<?php
interface B_Interface
{
public function method_1();
public function method_2();
...
}
If you look at class B_Class``, in the __constructmethod I'm trying to get the instance of classA_Class``` from where that class is being called. I have tried the following:
class B_Class implements B_Interface
{
public function __construct(A_Interface $a_interface)
{
// Here is the question...
// How could I get here the instance of the class A_Class?
}
But I get the following error:
Segmentation fault
I guess there must be some way I can achieve what I need. I would appreciate any help in advance.
Because you are referring to class A inside your class B constructor, and class B in your class A constructor, you have introduced a cyclic dependency.
This will resolve to the error you are experiencing, which is the segmentation fault, as outlined here:
https://laravel.io/forum/11-08-2016-circular-dependency-causes-segmentation-fault-error-when-running-php-artisan-optimize
So the answer is to remove the cyclic dependency if possible, as you can have methods from A calling B that calls A for infinity at runtime, and you will get the above error above again.
If your class A and B are relatively small, I would recommend combining them before using a cyclic dependency.
For interest and prosperity, if you want achieve a cyclic dependency, this is possible by registering your Class A with a singleton from inside A's constructor, and putting the reference to the incomplete object into Class B with your code above. I try with laravels singleton here, its untested, but hopefully you'll get the idea.
class A_Class implements A_Interface
{
public function __construct(B_Interface $b_interface)
{
//I dont think you can pass $this to a function when construction is incomplete, hence $that.
$that = $this;
App::singleton('A_Class', function($that){
return $that;
});
$this->b_interface = $b_interface;
}
}
class B_Class implements B_Interface
{
public function __construct(A_Interface $a_interface)
{
//unfinished object, but no more error.
$this->aClass = App::make('A_Class')
}
}
When developing in C#, and you had many classes that used the same exact code, you could rely on another class to hold the generic information, making it easier to modify these classes.
I was wondering if there was anything like that in PHP?
class Dog extends Animal {
private $animalManager
public function __construct(AnimalManager $animalManager) {
$this->animalManager = $animalManager;
}
}
class Cat extends Animal {
private $animalManager
public function __construct(AnimalManager $animalManager) {
$this->animalManager = $animalManager;
}
}
class Fish extends Animal {
private $animalManager
public function __construct(AnimalManager $animalManager) {
$this->animalManager = $animalManager;
}
}
class Animal {
// Nothing, yet...
}
What C# would allow you to do is, store the $animalManager and the constructor assignement in the 'Animal' class somehow, making it constant in 1 place if you ever needed to change it.
The thing is, PHP does this quite neatly.Every extending class inherits everything from the extended class. This means the parent's (in this case animal) construct will run whenever you call one of the extending classes.
However, you overwrite your parent's class when you call __construct() within the child. Therefore you'd need to specifically call parent::__construct() to run the parent constructor.
class Animal {
//Private vars can't be directly accessed by children.
//You'd have to create a function in the parent return it.
public $animalManager
//This function will automatically be called if you leave the
//constructor out of the extended class
public function __construct($animalManager) {
$this->animalManager = $animalManager;
}
//If you want $animalManager to be private
//Call like $fish->getAnimalManager();
//Though I do not see the use of this.
public function getAnimalManager(){
return $this->animalManager
}
}
class Fish extends Animal {
//You do not need to do this if you leave the construct out of this class
public function __construct($animalManager) {
parent::__construct($animalManager);
//Do whatever you like here
}
}
Example with only the parent constructor:
class Fish extends Animal {
//The parent's constructor is called automatically as it's not
//Being overwritten by this class
public function test(){
var_dump($this->animalManager);
}
}
Note that you would also not need to initiate the parent class seperately. Just call it like so;
$fish = new Fish(myAnimalManager);
$am = $fish->animalManager;
echo $am;
A draft has been added by Ben Scholzen for generics here.
But all I can see is type parameters and no wildcards. It supports generic functions and generic constructors. It also supports Bounds.
Unlike C# and Java, PHP will have its type arguments fully reified, which means we can reflectively know the run time parameter of desired function/constructor.
Backward compatibility is not a concern here, because type parameters and raw types can never be compatible. So the legacy code won't be compatible with Generics.
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...
// ...
}
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.
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.