designpatternsphp / designpatternsphp Goto Github PK
View Code? Open in Web Editor NEWSample code for several design patterns in PHP 8.x
License: MIT License
Sample code for several design patterns in PHP 8.x
License: MIT License
The following code doesn't produce the expected output :
<?php
require_once 'Book.php';
require_once 'BookList.php';
require_once 'BookListIterator.php';
use DesignPatterns\Behavioral\Iterator\Book;
use DesignPatterns\Behavioral\Iterator\BookList;
use DesignPatterns\Behavioral\Iterator\BookListIterator;
$list = new BookList();
$list->addBook(new Book('foo', 'bar'));
$list->addBook(new Book('a', '1'));
$list->addBook(new Book('b', '2'));
$list->addBook(new Book('c', '3'));
$list->addBook(new Book('d', '4'));
$list->removeBook(new Book('b', '2'));
$it = new BookListIterator($list);
foreach($it as $i => $b)
echo $b->getAuthorAndTitle(), PHP_EOL;
The output is :
foo by bar
a by 1
When it should be :
foo by bar
a by 1
c by 3
d by 4
The reason why this happens is that after deleting the "b by 2" book, the internal array of BookList looks like this :
Array
(
[0] => DesignPatterns\Behavioral\Iterator\Book Object
(
[author:DesignPatterns\Behavioral\Iterator\Book:private] => bar
[title:DesignPatterns\Behavioral\Iterator\Book:private] => foo
)
[1] => DesignPatterns\Behavioral\Iterator\Book Object
(
[author:DesignPatterns\Behavioral\Iterator\Book:private] => 1
[title:DesignPatterns\Behavioral\Iterator\Book:private] => a
)
[3] => DesignPatterns\Behavioral\Iterator\Book Object
(
[author:DesignPatterns\Behavioral\Iterator\Book:private] => 3
[title:DesignPatterns\Behavioral\Iterator\Book:private] => c
)
[4] => DesignPatterns\Behavioral\Iterator\Book Object
(
[author:DesignPatterns\Behavioral\Iterator\Book:private] => 4
[title:DesignPatterns\Behavioral\Iterator\Book:private] => d
)
)
You'll notice that the index 2 is missing, which makes sense since removeBook calls unset() on that specific book. However, BookListIterator's next() method simply increments the internal index ($currentBook) and BookListIterator::valid() stops when BookList::getBook() returns null
, which happens once BookListIterator::currentBook reaches 2, the book we just removed by calling $list->removeBook(new Book('b', '2')). Because of this, the iterator stops prematurely.
The SimpleFactory pattern is referred both in the documentation and in the code, as both SimpleFactory and ConcreteFactory.
I would make a pull request but I actually don't know what is the correct name.
As Singleton is considered as an Anti-Pattern, I thing that should be removed.
Instead of that, dependency Injection design is best alternative.
Does EAV pattern suitable for this repo? What do you think, guys?
I loved that dark theme diagram..
The command pattern's intent (in the comment text) and the implementation looks much more like a template pattern. What Symfony mean by Command is "CLI Commands" not "Command Pattern". Please take a look at the Intent of the command pattern.
This is a very good repository to explain Design Patterns in PHP but I think it would be better to have a coding standard for it.
Some examples:
Do not add non sens comments in docblocks like:
/** * Class MyClass // this comment should not be here */ class MyClass { // ... }Docblock for constants in classes should not contain
@var
. They are constants, not variables.
Is not necessary to add @abstract
in docblock for a method declared abstract. It can be seen from method's declaration itself.
/**
* @abstract // this should not be here.
* @var int $idSomething
*/
abstract public function doSomething($idSomething);
Do not add empty docblock for classes or methods like in this class https://github.com/domnikl/DesignPatternsPHP/blob/master/Structural/Facade/Facade.php
The list can continue and I believe it could add a lot of improvements to the examples.
Now that GitHub has introduced its topic feature to make projects more searchable; I think it would really help others like me who didn't know about this fantastic project, to add (at least) the following topics:
These are just suggestions for you to take on board if you'd like...
Anyways thanks!
https://github.com/domnikl/DesignPatternsPHP/blob/master/Creational/Multiton/Multiton.php
final class Multiton { ... }
missed or omitted? In Singleton it exists? what difference?
hey dudes, some days ago I was reading codes from this repo I have an idea. Would be nice to have some libraries with abstract implementation of Design Patterns so I can use in real project!
What it means?
Something like PSRs and we could create a organization with some repositories to provide the way to implement one specific pattern
Look like, create a abstract structure to someone implement a Chain of Responsibility? You know...
isn't Service Locator formerly known as anti-pattern ?
Service Locator is an Anti-Pattern since it hides class' dependencies causing issues when you change dependencies, since they are not directly exposed out of the class.
What do you think @domnikl ? :)
What do you think about add method undo in command interface?
What do you think about this proposal?
I reworked the implementation of the pattern so now it has practical usage within php (because on many sites this pattern have amorphous representation, divorced from reality).
Text did not implement MediaInterface's render method in AbstractFactory
UML Diagram of Adapter is not updated
What software are you using for the UML diagrams?
Thank you for this resource! It's awesome!!!!
Error when deploying vagrand.
==> default: Mounting NFS shared folders...
==> default: Running provisioner: ansible...
default: Running ansible-playbook...
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [192.168.11.2]
TASK [server : Update apt] *****************************************************
ok: [192.168.11.2]
TASK [server : Install System Packages] ****************************************
changed: [192.168.11.2] => (item=[u'curl', u'wget', u'python-software-properties'])
TASK [server : Install Extra Packages] *****************************************
changed: [192.168.11.2] => (item=[u'vim', u'htop', u'iotop', u'bwm-ng', u'git'])
TASK [server : Configure the timezone] *****************************************
changed: [192.168.11.2]
TASK [server : More Configure the timezone] ************************************
changed: [192.168.11.2]
TASK [server : Set default system language pack] *******************************
changed: [192.168.11.2]
TASK [vagrant_local : Set the hostname in /etc/hostname] ***********************
changed: [192.168.11.2]
TASK [vagrant_local : Set the hostname] ****************************************
changed: [192.168.11.2]
TASK [vagrant_local : Update /etc/hosts] ***************************************
changed: [192.168.11.2]
TASK [php : Update apt] ********************************************************
fatal: [192.168.11.2]: FAILED! => {"changed": false, "failed": true, "msg":
"unsupported parameter for module: autoremove"}
PLAY RECAP *********************************************************************
192.168.11.2 : ok=10 changed=8 unreachable=0 failed=1
Ansible failed to complete successfully. Any error output should be
visible above. Please fix these errors and try again.
I really appreciate this, and downloaded it so that I can learn it.
Could you improve this only slightly by giving an example explanation where I might use each pattern, in simplistic terms?
For instance, let's say I want to make a plugin architecture for a web app -- which design pattern would you use? Or let's say I want to confirm a login -- which design pattern? You don't have to give those exact examples, however.
It would be great & very useful if this could be converted to a PDF book & to gh-pages ( something like http://couscous.io )
I create design pattern for 5.6 https://github.com/mishbah/DesignPatternsPHP/tree/php5.6
maybe we can create another branch for 5.6
Hi domnikl,
Awesome examples! Learning a lot, thanks.
I have a question, why does your composite pattern uses an abstract class in stead of an interface or trait?
Trait example:
trait RenderableTrait
{
/**
* renders the elements' code.
*
* @param int $indent
*
* @return mixed
*/
abstract public function render($indent = 0);
}
Interface example
interface RenderableInterface
{
/**
* renders the elements' code.
*
* @param int $indent
*
* @return mixed
*/
public function render($indent = 0);
}
Than you can decouple the From class from the FormElement and add the RenderableTrait or RederableInterface to the Form and FormElement class.
Forgive my possible ignorance, I'm still learning and trying to understand the why of programming decisions.
Even if most patterns are self-explaining we should provide usage examples. Any thoughts?
php AbstractFactoryTest.php
PHP Fatal error: Class 'PHPUnit_Framework_TestCase' not found in /Users/shengbinxu/web/DesignPatternsPHP/Creational/AbstractFactory/Tests/AbstractFactoryTest.php on line 13
Fatal error: Class 'PHPUnit_Framework_TestCase' not found in /Users/shengbinxu/web/DesignPatternsPHP/Creational/AbstractFactory/Tests/AbstractFactoryTest.php on line 13
In the builder pattern in Vehicle.php I found line:
"VehicleInterface is a contract for a vehicle" - but don't see any Vehicle Interface anywhere. So the code is missing? what is wrong with this code? Thanks.
I feel a bit confused about it.
I have a thought about Repository pattern. It knows too much about the columns name, if I want to create a Storage for a database where created
is a keyword, so the name of this column in this DB is created_at
. It will break my Repository implementation. Or even so, if in DB 1 my date is in format YYYY-MM-DD
and DB 2 my date is as MM-DD-YYYY
, my Repository should not know how to transform the returned string from storage to a DateTime
, because the String could vary. What you think?
Please, implement a delegate pattern.
It's very simple and cool :)
How do you feel about adding the Presenter Pattern to this repo? Its similar to the Decorator pattern, but has some key differences. Decorators add new functionality to class instances, whereas Presenters are closer to the view and work directly with the view layer and may contain the language of the view (html/css/etc..). It also contains the ui business logic for the View.
Example code:
class PresentableClass{
use PresentableTrait;
protected $presenter = 'ClassPresenter';
}
//Sample class presenter used for this test only
class ClassPresenter extends Presenter{
public function userName(){
if($this->email) return $this->email;
return "{$this->firstName} $this->lastName";
}
}
//An example of a presenter trait
<?php namespace App\Presenters;
trait PresentableTrait {
protected $presenterInstance;
public function present()
{
// Check if the property has been declared on the model and
// the class exists
if (!$this->presenter or !class_exists($this->presenter)) {
throw new Exception('Please set the Presenter path to your Presenter FQN');
}
// The good old Singleton pattern
if (!$this->presenterInstance) {
$this->presenterInstance = new $this->presenter($this);
}
return $this->presenterInstance;
}
}
<?php
namespace App\Presenters;
abstract class Presenter
{
protected $entity; // Store the original model instance
function __construct($entity){
$this->beforeConstruct();
$this->entity = $entity;
$this->afterConstruct();
}
// Call the function if exists, or return the property on the original model
public function __get($property)
{
if (method_exists($this, $property)) {
return $this->{$property}();
}
return $this->entity->{$property};
}
//optional
public function beforeConstruct(){}
public function afterConstruct(){}
}
Some references:
https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter
http://stackoverflow.com/questions/2056/what-are-mvp-and-mvc-and-what-is-the-difference
https://github.com/laracasts/Presenter
Thoughts as this might be closer to the singleton pattern (might be an anti-pattern)?
Hey! Whats'up?!
Is there some version of this repo in other language? I've forked this repo yesterday to translate to portuguese.
[important] Before your start, re-fork this project or synchronize your repo with upstream!(because i just do some change)
example: Russian translation is completed
#: ../../Creational/AbstractFactory/README.rst:22
msgid "You can also find these code on `GitHub`_"
msgstr "在 `GitHub`_ 上查看代码" (`xxx`_ one underscore here)
#: ../../Creational/AbstractFactory/README.rst:24
msgid "AbstractFactory.php"
msgstr "" (do not need translate xxx.php, keep it empty)
if you finished, make one pull request or by "Russian translation part one two..."(maxi five)
i will create project on read the doc and translation will be hosted at http://designpatternsphp.readthedocs.org/{language_slug}/latest/
language(click to preview) | translator |
---|---|
ca – Catalan | @torrentalle |
en – English | @domnikl |
es – Spanish | @torrentalle @desarrolla2 |
pt_BR – Brazilian Portuguese | @leleonam @bgsouza @davispeixoto |
ru – Russian | @KIVagant |
zh_CN – Simplified Chinese | @su-xiaolin @yplam |
It's possible to change english wikipedia link of title to the localized version.
three formats are possible:
//take care of the num of underscore
#: ../../Behavioral/ChainOfResponsibilities/README.rst:2
msgid "`Chain Of Responsibilities`__"
//1. only keep russian title, russian link on russian title
msgstr "`Цепочка обязанностей <https://ru.wikipedia.org/wiki/Цепочка_обязанностей>`_"
or
//2. keep two version titles, russian link on russian title, english link on english title
msgstr "`Цепочка обязанностей <https://ru.wikipedia.org/wiki/Цепочка_обязанностей>`_ (`Chain Of Responsibilities`__)"
or
//3. keep two version titles, russian link on russian title, no english link
msgstr "`Цепочка обязанностей <https://ru.wikipedia.org/wiki/Цепочка_обязанностей>`_ (Chain Of Responsibilities)"
or
//4. if no russian wikipedia page,so english link on russian title
msgstr "`Цепочка обязанностей`__"
// I think 1 and 3 are best way
msgstr "External **hyperlinks**, like
Python http://www.python.org/_."
Hey guys,
What do you think about changing Specification
pattern example? At the moment it has the following issues:
Specification
interface contains plus
, either
and not
methods which put on Specification
object redundant responsibilities. Instead of checking if some certain condition is satisfied it is also responsible for creating new specifications. This is not a good approach and may create wrong impression on people who are not familiar with the pattern.AbstractSpecification
class knows about its children. While sometimes it adds some convenience, in general, it is a bad design.Plus
and Either
specifications have an arity of two while they can operate on any number of specifications (in case we want to show them in the example).Plus
and Either
names were used because and
and or
are reserved words but we can call them AndSpecification
, OrSpecification
, and NotSpecification
. These names look worse if we want our code to look more like a natural language but in this case, in my opinion, they increase readability. Because the name AndSpecification
less likely will confuse somebody.I propose to:
plus
, either
and not
methods from the Specification
interfaceAbstractSpecification
class (it is not needed)Plus
, Either
and Not
specifications to AndSpecification
, OrSpecification
and NotSpecification
correspondinglyAndSpecification
and OrSpecification
to any number of parametersI didn't create a pull request because wanted to discuss this with you guys first. But I can prepare it this weekend if you agree with proposed changes.
Not enough MVC pattern.
The README files should all have a similar structure, so that they're easily readable and users find the important contents right away without much need for searching.
It seems to me that the UML diagram for Creational/Pool a mistake because the source code is not contain Processor class and run method for Worked does not match.
Possibly previously used different source code for example?
hey, guys, please take a look, what happened this error:
wozzup@u1404:~/php/Creational/AbstractFactory$ phpunit Tests/AbstractFactoryTest.php
PHPUnit 3.7.28 by Sebastian Bergmann.
E
Time: 49 ms, Memory: 2.50Mb
There was 1 error:
1) Creational\AbstractFactory\Tests\AbstractFactoryTest::testComponentCreation
Argument 1 passed to Creational\AbstractFactory\Tests\AbstractFactoryTest::testComponentCreation() must be an instance of Creational\AbstractFactory\AbstractFactory, none given
/home/wozzup/php/Creational/AbstractFactory/Tests/AbstractFactoryTest.php:19
FAILURES!
Tests: 1, Assertions: 0, Errors: 1.
do i need to composer autoload "squizlabs/php_codesniffer": "1.5.*"
to get phpunit work?
There is a Bridge
pattern, as demonstrated on http://sourcemaking.com/design_patterns/bridge/php
Hello to all.
I can help to translate some new patterns for RU locale: More/EAV
and Structural/Flyweight
And, as I can imagine, EN documentation should be changed from Sep 8 2015 when I sent last PR with translation.
So, maybe some *.po files in RU locale is now outdated too. Can you check this?
UP: JFYI, here is broken UML image.
Shouldn't the role interface define accept
method, to be sure any Role class can accept RoleVisitor?
Maybe rather than interface use an abstract class to evade repeating accept
method code in every subclass.
Or did I get it all wrong?
https://github.com/domnikl/DesignPatternsPHP/blob/master/Visitor/Visitor.php#L17
I use phpstorm develop;
can you tell me ,how to get classes UML diagram?
hi
where is MVC and HMVC?
they are also good to be in this awesome work.
if you need this tel me i will write them and add to your code later
thanks.
What are you think to restructure this repository?
My proposal:
Create a directory structure with types of Design Patterns, like on my branch restructure:
|-- Creational
| |-- Factory
| | |-- Tests
| |-- ...
|-- Behavioral
| |-- ...
|-- Structural
| |-- ...
There are parse error like this :
https://github.com/domnikl/DesignPatternsPHP/blob/master/DataMapper/UserMapper.php#L80
Namespace does not follow PSR0 and the script Test.php cannot be launched.
This is just a suggestion, but I'd recommend you use https://github.com/StyleCI/StyleCI/
to automate your php linting process that is described in your readme.md
It's free for open source, and you'll get the github health API integration ;)
This is an example:
jadjoubran/laravel5-angular-material-starter#23
Great work, kudos!
If you still want to put more effort into it, you can enhance it with embedded diagrams written in plain text (see http://yuml.me/).
Types become really important here and interesting.
PR: #169
Fork: https://github.com/eddiejaoude/DesignPatternsPHP
I have noticed the following in Structural/Composite/Tests/CompositeTest.php
.
Even though the following test demonstrates the example for this pattern well, technically you cannot nest html forms, that I know of. https://www.w3.org/TR/html5/forms.html#the-form-element
public function testRender()
{
$form = new Composite\Form();
$form->addElement(new Composite\TextElement('Email:'));
$form->addElement(new Composite\InputElement());
$embed = new Composite\Form();
$embed->addElement(new Composite\TextElement('Password:'));
$embed->addElement(new Composite\InputElement());
$form->addElement($embed);
$this->assertEquals(
'<form>Email:<input type="text" /><form>Password:<input type="text" /></form></form>',
$form->render()
);
}
Maybe there could be some notes added as part of the doc block for the test, or an inline comment - something along the lines of the following?
This is just an example, in a real world scenario you are not able to nest HTML forms.
I can create a PR, if this would be welcomed...
Anyways - this repository is awesome, thanks!!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.