This is the first question I ask from many others to come.
Someone here might call me crazy because I'm following the mentioned book in the question's Title using PHP-OO.
At the first chapter, the authors introduce a simple project called 'SimUDuck' and, although I've reproduced the same in Java, I was wondering to reproduce the same using PHP.
At the end, the SimUDuck's project creates two (2) interfaces (FlyBehavior and QuackBehavior), more than five (5) classes implementing those interfaces (e.g. FlyWithWings(), Quack() etc), an abstract class called Duck and three (3) or four (4) different ducks species classes extending Duck (Mallard, HeadRedDuck, RubberDuck etc), just to demonstrate how important is to program for interface.
To simulate the Java main method environment, I've created a PHP class called MiniDuckSimulator, including the function 'public static function main()' and in the same script I've added "MiniDuckSimulator::main();". The script works without errors.
The intriguing issue is that without call any QuackBehavior::quack() implemented method, the echo 'Quack!quack!' appears. Those who has read this book knows what I'm talking about.
Note: Below is a particular part of the script:
interface FlyBehavior {
public function fly();
}
interface QuackBehavior {
public function quack();
}
include_once 'FlyBehavior.php';
class FlyWithWings implements FlyBehavior {
public function fly() {
echo 'I'm flying!<br />';
}
}
include_once 'QuackBehavior.php';
class Quack implements QuackBehavior {
public function quack() {
echo 'Quack!<br />';
}
}
abstract class Duck {
protected $flyBehavior;
protected $quackBehavior;
function __construct() {
}
public function performFly(){
$this->flyBehavior->fly();
}
public function performQuack(){
$this->quackBehavior->quack();
}
public function setFlyBehavior($flyBehavior){
$this->flyBehavior = $flyBehavior;
}
public function swim(){
echo "All the ducks float, including the decoy!<br />";
}
}
include_once 'Duck.php';
include_once 'FlyWithWings.php';
include_once 'Quack.php';
class Mallard extends Duck {
function __construct() {
$this->flyBehavior = new FlyWithWings();
$this->quackBehavior = new Quack();
}
}
class MiniDuckSimulator {
public static function main(){
$mallard = new Mallard();
$mallard->performFly();
}
}
MiniDuckSimulator::main();
Thanks in advance.
LucDaher.
The reason you are seeing Quack!<br /> output is because of this:
class Quack implements QuackBehavior {
public function quack() {
echo 'Quack!<br />';
}
}
Here's your problem: If you simply run new Quack(); the quack() method is automatically being executed by php as a constructor because it is the same name as your class. -- I see you referenced Java in your question, so this shouldn't be a foreign concept to you.
new Quack(); // => Quack!<br />
A potentially better way
<?php
interface CanFly {
public function fly();
}
interface CanQuack {
public function quack();
}
abstract class Duck implements CanFly, CanQuack {
protected $color = "DEFAULT"
public function fly(){
echo "I'm flying with my {$this->color} wings\n";
}
public function quack(){
echo "I'm quacking\n";
}
public function swim(){
echo "I'm swimming\n";
}
}
class Mallard extends Duck {
public function __construct(){
$this->color = "green";
}
public function quack(){
echo "My quack sounds more like a honk\n";
}
}
$m = new Mallard();
$m->fly();
$m->quack();
$m->swim();
?>
Output
I'm flying with my green wings
My quack sounds more like a honk
I'm swimming
In your situation, I would personally assume that I've overlooked something when saying that an echo is being reached in the code without a call to that method. I can't see a way that this would be possible.
Reanalyze your code and look for a sneaky way that your echo 'Quack!quack!' is being reached.
Comment this line:
echo 'Quack!<br />';
Do you see any more quacks? If so, then there is an echo/exit/die in your code with this string!
It is because when you have the class with the same name of the method, the PHP consider it as a constructor. This is already deprecated in php 7 and it will be discontinued soon. You can see it on the online documentation: http://php.net/manual/en/migration70.deprecated.php
Related
I am trying to make an implementation of the Bridge Design Pattern, following the steps on Tutorials Point. I am converting the code from Java to PHP and changing some names.
The problem is, when I try to pass the concrete bridge implementer class to the concrete class implementing interface, an error is throw.
My code is as follows:
// LaunchApi.php
interface LaunchApi
{
public function launch();
}
// RedEngine.php
class RedEngine implements LaunchApi
{
public function launch()
{
echo "The red engine is really fast!!!";
}
}
// Rocket.php
abstract class Rocket
{
protected $launchApi;
protected function __construct($launchApiImplementer)
{
$this->launchApi = $launchApiImplementer;
}
public abstract function launch();
}
// FullRocket.php
class FullRocket extends Rocket
{
public function __construct($launchApi)
{
parent::__construct($launchApi);
}
public function launch()
{
$this->launchApi->launch();
}
}
// LaunchingScript.php
$redEngine = new RedEngine();
$redEngine->launch(); // this works
$redRocket = new FullRocket($redEngine);
$redRocket.launch(); // this won't work
The error throw is:
design-patterns\Bridge>php LaunchingBridge.php
The red engine is really fast!!!
Fatal error: Call to undefined function launch() in \design-patterns\Bridge\LaunchingBridge.php on line 24
I tried to pass by reference using the &, but it only changes the error.
yeah should be $redRocket->launch(); instead of $redRocket.launch();
like what nigel ren said
I have some handler ("controller") classes and they can process items in some way:
interface IHandler
{
public function execute(Item $item);
}
class FirstHandler implements IHandler
{
public function execute(Item $item) { echo $item->getTitle(); }
}
class SecondHandler implements IHandler
{
public function execute(Item $item) { echo $item->getId() . $item->getTitle(); }
}
class Item
{
public function getId() { return rand(); }
public function getTitle() { return 'title at ' . time(); }
}
But then I need to add some new functionality in child Item class:
class NewItem extends Item
{
public function getAuthor() { return 'author ' . rand(); }
}
and use it in SecondHandler
class SecondHandler implements IHandler
{
public function execute(Item $item) { printf('%d %s, author %s', $item->getId(), $item->getTitle(), $item->getAuthor()); }
}
But Item class actually has not getAuthor method. And, if I try to change signature of accept method in SecondHandler class, I will catch E_STRICT error about declaration compatibility. And, of course, it's sort of LSP violation.
How can I fix this problem? Do I need two interfaces, for example, INewHandler and IHandler, with different signatures of execute method? But it's some sort of code duplicates.
Also, I cannot use __constructor(Item $item) and __construct(NewItem $item) in handlers (and execute method without arguments), which will be seen like a better solution: they must be immutable and only single instance of every strategy allowed in application lifecycle.
As you discovered by yourself, the type hinting implementation of PHP has a lot limitations that make scenarios, like the one described by you, harder than they should be. In other typed languages like Java and Swift your implementation is absolutely licit.
After some thinking on your question I came to the solution presented by Félix but I consider it too much over engineered compared to the problem.
My answer to your question is not a solution but an advice that I give to you after years of development with PHP:
Give up with type hinting in PHP and develop like it should be... in a dynamic way.
PHP is more similar to Ruby/Python/JavaScript than Java/C++, and trying to copy 1 to 1 from static typed languages translates in forced and convolute implementations.
The solution to your implementation problem is easy, so don't over complicate it and keep it easy as it should be (KISS principle).
Declare the methods' arguments without the type and implement a check where you really need (for example throwing an exception).
interface IStrategy
{
public function execute($item);
}
class FirstStrategy implements IStrategy
{
public function execute($item) {
echo $item->getTitle();
}
}
class SecondStrategy implements IStrategy
{
public function execute($item) {
// execute(NewItem $item) is identical to this check.
if (! $item instanceof NewItem) {
throw new Exception('$item must be an instance of NewItem');
}
echo $item->getAuthor();
}
}
class Item
{
public function getId() { return rand(); }
public function getTitle() { return 'title at ' . time(); }
}
class NewItem extends Item
{
public function getAuthor() { return 'author ' . rand(); }
}
Again, don't think in Java but follow as much as possible the duck typing way.
When possible, try to don't strictly force the type of the parameters but adapt the behavior of the code based on the available interfaces (Duck Typing).
class SecondStrategy implements IStrategy
{
public function execute($item) {
$message = $item->getTitle();
// PHP 5 interface availability check.
if (is_callable([$item, 'getAuthor'])) {
$message .= ' ' . $item->getAuthor();
}
// With PHP 7 is even better.
// try {
// $message .= ' ' . $item->getAuthor();
// } catch (Error $e) {}
echo $message;
}
}
I hope to have helped you. ^_^
Both #daniele-orlando and #ihor-burlachenko made valid points.
Consider following approach for method overloading, which is kind of a compromise and should scale well:
interface IHandler
{
/**
* #param $item Item|NewItem
*/
public function execute($item);
// protected function executeItem(Item $item);
// protected function executeNewItem(NewItem $item);
}
trait IHandlerTrait
{
public function execute($item)
{
switch(true) {
case $item instanceof Item:
return $this->executeItem($item);
case $item instanceof NewItem:
return $this->executeNewItem($item);
default:
throw new \InvalidArgumentException("Unsupported parameter type " . get_class($item));
}
}
protected function executeItem(Item $item)
{
throw new \LogicException(__CLASS__ . " cannot handle execute() for type Item");
}
protected function executeNewItem(NewItem $item)
{
throw new \LogicException(__CLASS__ . " cannot handle execute() for type NewItem");
}
}
class FirstHandler implements IHandler
{
use IIHandlerTrait;
protected function executeItem(Item $item) { echo $item->getTitle(); }
}
class SecondHandler implements IHandler
{
use IIHandlerTrait;
// only if SecondHandler still need to support `Item` for backward compatibility
protected function executeItem(Item $item) { echo $item->getId() . $item-> getTitle(); }
protected function executeNewItem(NewItem $item) { printf('%d %s, author %s', $item->getId(), $item->getTitle(), $item->getAuthor()); }
}
Are you sure you want to use Strategy pattern here?
It looks, like the strategy's action here depends on the type of the element it processes. And Visitor pattern might apply here as well in this case.
As it stands, you appear to want to execute an extensible data record (Item and NewItem). Consider instead executing some pluggable behaviour (implemented via an interface).
It's hard from your writing to guess what that behavior would be, because (New)Item is just a glorified data structure in the example you provide.
If you want to work/manipulate with object in another object, you could/should use interfaces.
interface IStrategy
{
public function execute(ItemInterface $item);
}
interface ItemInterface
{
public function getTitle();
.....
}
If you want to extend public functionality of the (New)Item class you can make new interface for newItem
interface NewItemInterface extends ItemInterface
{
...
}
class SecondStrategy implements IStrategy
{
public function execute(NewItemInterface $item)
{ .... }
}
Or you can use some instance checks as others have mentioned.
If your inheritance and suggestion that SecondHandler should handle both Item and NewItem were correct in the first place, then you should be able to hide this functionality behind the common interface. From your examples, it might be called toString() which might be a part the Item interface.
Otherwise, there might be something wrong with your design initially. And you have to change your inheritance or the way you handle items. Or something else we don't know about.
Also, I don't know why you need DTO but it seems there is some misunderstanding of Doctrine. Doctrine is an ORM and it solves your persistence problem. It adds limitations on how you communicate with your storage introducing repositories, but it doesn't define your domain logic.
As per the Interface segregation please find some solution.
```
# based on interface segrigation.
interface BasicInfo
{
public function getId();
public function getTitle();
}
interface AuthorInfo
{
public function getAuthor();
}
interface IHandler
{
public function execute(Item $item);
}
class FirstHandler implements IHandler
{
public function execute(Item $item) { echo $item->getTitle(); }
}
class SecondHandler implements IHandler
{
public function execute(Item $item) { echo $item->getId() . $item->getTitle(); }
}
class Item implements BasicInfo
{
public function getId() { return rand(); }
public function getTitle() { return 'title at ' . time(); }
}
class Item2 extends Item implements AuthorInfo
{
public function getAuthor() { return 'author ' . rand(); }
}
But I think you should not kept the dependency of the Item class. you should write some duplicated code to keep the class pluggable/independent. So the Open/close principle should also there.
I am looking to incorporate a testing framework into a project I am building and came across Enhance PHP which I like but I am having some difficulty finding relevant information on-line since "enhance php" is such a commonly used phrase.
Has anyone worked with this framework that might be able to point me toward some helpful guide? Have you worked with a unit test framework that you think is amazingly better?
Thanks in advance.
In response to Gotzofter, this is the class to be tested:
<?php
include_once('EnhanceTestFramework.php');
class ExampleClass
{
private $OtherClass;
function __construct($mock = null)
{
if ($mock == null)
$this->OtherClass = new OtherExampleClass();
else
$this->OtherClass = $mock;
}
public function doSomething()
{
return $this->OtherClass->getSomething(1, 'Arg2');
}
}
class OtherExampleClass
{
public function getSomething()
{
return "Something";
}
}
class ExampleClassTests extends \Enhance\TestFixture
{
public function setUp()
{
}
public function tearDown()
{
}
public function verifyWithAMock()
{
$mock = \Enhance\MockFactory::createMock('OtherExampleClass');
$mock->addExpectation(
\Enhance\Expect::method('getSomething')
->with(1, 'Arg2')
->returns('Something')
->times(1)
);
$target = new ExampleClass($mock);
$result = $target->doSomething();
\Enhance\Assert::areIdentical("Something", $result);
$mock->verifyExpectations();
}
}
\Enhance\Core::runTests();
look at my constructor for ExampleClass.
Because enhance-php's site example injects the $mock object by calling new ExampleClass($mock), I am forced to change my ExampleClass constructor to handle a $mock as an input parameter.
Do I have to handle this for all classes that I want to subject to unit testing with the framework?
Thanks.
This:
function __construct()
{
$this->OtherClass = new OtherExampleClass;
}
Should be:
function __construct($otherClass)
{
$this->OtherClass = $otherClass;
}
Your mock is never injected at this point in your test:
$target = new ExampleClass($mock);
One thing I would recommend no matter what testing framework you are using is type-hinting against the expected class, or interface.
<?php
class ExampleClass
{
private $OtherClass; // OtherClass instance
public function __construct(OtherClass $OtherClass=null)
{
// ...
}
}
I'm no di expert, but I don't see the problem in letting each class call new if an instance isn't provided for a particular dependency. You could also of course take the approach where you use setter methods to configure dependencies.
<?php
class class ExampleClass
{
private $OtherClass; // OtherClass instance
public function setOtherClass(OtherClass $OtherClass)
{
$this->OtherClass = $OtherClass;
}
}
It is lame that the ExampleClass in the sample code doesn't even define the doSomething method from the ExampleDependencyClassTests, but if I understand correctly it looks like Enhance PHP is not forcing you to take a particular style of dependency injection. You can write the test class however you want, so for example if you took the setter method approach I mentioned above, you could change the example mock code to
<?php
class ExampleDependencyClassTests extends \Enhance\TestFixture
{
public function verifyWithAMock()
{
$mock = \Enhance\MockFactory::createMock('ExampleDependencyClass');
$mock->addExpectation(
\Enhance\Expect::method('getSomething')
->with(1, 'Arg2')
->returns('Something')
->times(1)
);
$target = new ExampleClass();
$target->setExampleDependencyClass($mock);
$result = $target->doSomething();
$mock->verifyExpectations();
}
}
Of course it would probly make sense to make the appropriate revisions to the ExampleClass!
<?php
class ExampleClass
{
private $ExampleDependencyClass;
public function addTwoNumbers($a, $b)
{
return $a + $b;
}
public function setExampleDependencyClass(
ExampleDependencyClass $ExampleDependecyClass
) {
$this->ExampleDependecyClass = $ExampleDependecyClass;
}
public function doSomething($someArg)
{
return 'Something';
}
}
I've worked with PHPUnit quite a bit, and honestly you'll have to face the same challenges with Mocks there. My 2 cents, try to model your tests without Mocks if possible ;)
There is a tutorial on NetTuts titled Testing Your PHP Codebase With Enhance PHP, which will definitely help you to get started.
And there is a Quick Start Guide on Enhance PHP.
I've been into this problem for a while already, and have asked some questions about it here Stackoverflow. I've got some advice, but I just can't understand it. Could someone provide me an example of classes working smoothly together.
I have 3 (maybe more) classes:
mysql
user
alerts
As I said, could someone provide an example, so these classes could use functions from each other class, e.g. user could use mysql's functions. I'm asking for an simple example, for learning-purposes.
And please, no google-suggestions or links to other questions. I've tried to search this for a while already. No success, though.
Martti Laine
I really recommend you read about classes first - http://php.net/manual/en/language.oop5.php because these are basic concepts if you don't understand a single code example won't help you much.
class Mysql {
// Public function accessible from everywhere, with class instance
public function hello() {
echo '<br>Mysql says Hello';
}
// Static function accesible from everywhere, without class instance
static function bye() {
echo '<br>Mysql says Bye';
}
}
class User {
// Public function accessible from everywhere, with class instance
public function hello() {
$mysql = new Mysql();
$mysql->hello();
Mysql::bye();
}
}
class Alert {
// Static function accesible from everywhere, without class instance
static function hello() {
$user = new User();
$user->hello();
}
}
$user = new User();
$user->hello();
Mysql::bye();
Alert::hello();
It's hard to understand exactly what you mean when you say "working smoothly together". Classes can be used together in a myriad of ways. If they couldn't be then object oriented programming wouldn't be much good.
Here is a simple example:
class mysql {
private $alert;
public function __construct(alerts $alert) {
$this->alert = $alert;
}
public function dosomething() {
if(/* something went wrong */ ) {
$this->alert->showAlert();
}
}
}
There are two way you can do it.
1st: Use static methods
<?php
class mysql_database
{
public static function query($q)
{
return mysql_query($q);
}
}
class user
{
public function get()
{
//calling static method from another class
return mysql_database::query("SELECT * FROM users");
}
}
?>
2nd: Give objects instances as a parameters to other objects methods
<?php
class mysql_database
{
public function query($q)
{
return mysql_query($q);
}
}
class user
{
public function get($DB)
{
//calling method using given instance
return $DB->query("SELECT * FROM users");
}
}
$DB = new mysql_database();
$user = new user();
$user->get($DB);
?>
You can smoothly :
Instanciate an object from one class within another one
Pass an object instance into another one : this is called dependency injection
Use static function calls
In all big PHP apps, I see a mix of all 3.
Their use depends of the whole design of application, usage, refactoring an testability needs, etc.
Classes should be working together to achieve a desired result. If you are looking for dependency injection in particular or other methods they are explained in most OOP literature.
But if let's say your Mysql Class exposes a number of functions that will be used by your user class you could inject an instance of the Mysql Class into your user class upon instanstiation:
class User {
private $db = null;
public function __construct($mysql) {
$this->db = $mysql
}
public function getUserName($userID){
$sql = "SQL_QUERY";
$result = $this->db->ExecuteQuery($sql);
}
}
Please make sure you read the CONS of Dependency Injection and understand WHY this method is preferred over others. If you which to change your Mysql Class to DBClass and not break your existing code you will have to implement the same methods. Of cousre this can get more "complicated" so a careful Design might be needed (your classes might have to extend abstract classes or implement interfaces)....
I suggest you spend some time on the literature and study some patterns to get an overall idea..it's enough to get you started (a good starting point in my opinion)
following is another example.
class MySql
{
private function query($q)
{
return mysql_query($q);
}
public function checkCredentials($user, $pass)
{
$query = "" // add code here to check the user credentials
$result = query($query);
$outcome = <true/false>;//based on however you analyze your result
return $outcome;
}
}
class alert
{
public function generateAlert($alert)
{
//code to display your alert
}
}
class user
{
var $mysql;
var $alert;
public function __construct($mysql, $alert)
{
$this->mysql = $mysql;
$this->alert = $alert;
}
public function checkLogin($user, $pass)
{
if (!$this->mysql->checkCredentials($user, $pass))
$this->alert->generateAlert("login failed!");
}
}
There are many ways of doing object oriented design, it really depends on what the requirements for your project are. I also recommend visiting the PHP site and looking their OOP tutorials.
I'm implementing a Log system for PHP, and I'm a bit stuck.
All the configuration is defined in an XML file, that declares every method to be logged. XML is well parsed and converted into a multidimensional array (classname => array of methods). So far, so good.
Let's take a simple example:
#A.php
class A {
public function foo($bar) {
echo ' // Hello there !';
}
public function bar($foo) {
echo " $ù$ùmezf$z !";
}
}
#B.php
class B {
public function far($boo) {
echo $boo;
}
}
Now, let's say I've this configuration file:
<interceptor>
<methods class="__CLASS_DIR__A.php">
<method name="foo">
<log-level>INFO</log-level>
<log-message>Transaction init</log-message>
</method>
</methods>
<methods class="__CLASS_DIR__B.php">
<method name="far">
<log-level>DEBUG</log-level>
<log-message>Useless</log-message>
</method>
</methods>
</interceptor>
The thing I'd like AT RUNTIME ONLY (once the XML parser has done his job) is:
#Logger.php (its definitely NOT a final version) -- generated by the XML parser
class Logger {
public function __call($name,$args) {
$log_level = args[0];
$args = array_slice($args,1);
switch($method_name) {
case 'foo':
case 'far':
//case .....
//write in log files
break;
}
//THEN, RELAY THE CALL TO THE INITIAL METHOD
}
}
#"dynamic" A.php
class A extends Logger {
public function foo($log_level, $bar) {
parent::foo($log_level, $bar);
echo ' // Hello there !';
}
public function bar($foo) {
echo " $ù$ùmezf$z !";
}
}
#"dynamic" B.php
class B extends Logger {
public function far($log_level, $boo) {
parent::far($log_level, $bar);
echo $boo;
}
}
The big challenge here is to transform A and B into their "dynamic" versions, once the XML parser has completed its job.
The ideal would be to achieve that without modifying the code of A and B at all (I mean, in the files) - or at least find a way to come back to their original versions once the program is finished.
To be clear, I wanna find the most proper way to intercept method calls in PHP.
What are your ideas about it?
PS: and of course, there should be NO CONSEQUENCE on the client code (no different if interception is enabled or not).
You could use eval() to actually define the classes, but you should be very careful. The eval() function can be very dangerous.
Something like this:
$parentName = 'Bar';
eval('class Foo extends ' . $parentName . ' { }');
http://php.net/eval
This solution once again uses eval, but I'll post it for your consideration anyway because I think it's a really nice way of dynamic inheritance.
The method here is to use an intermediary class which extends some default class that can be changed (in this instance to a different class also extending the default).
I'm uncertain as to what it is in your setup that is not allowing for this kind of working -- if you clarify this I could perhaps provide a better recommendation.
<?php
/*
* One of the following classes will be the superclass of the Child
*/
class Ancestor {
function speak() {
echo 'Ancestor <br />';
}
}
class Mum extends Ancestor {
function speak() {
parent::speak();
echo 'Mum <br />';
}
}
class Dad extends Ancestor {
function speak() {
parent::speak();
echo 'Dad <br />';
}
}
/*
* Decide on which class we wish to make the superclass of our Child
*/
$parentClass = null;
if (isset($_GET['parent'])) {
$parentClass = $_GET['parent'];
if (!class_exists($parentClass)) {
$parentClass = "Ancestor";
}
}
if (!is_null($parentClass)) {
eval("class ChildParent extends $parentClass {};");
} else {
class ChildParent extends Ancestor {};
}
if (class_exists('ChildParent')) {
class Child extends ChildParent
{
function speak() {
parent::speak();
echo 'Child <br />';
}
}
}
/*
* Show what's going on
*/
echo 'Either | Mum | Dad <br />';
$child = new Child();
$child->speak();*