sample code for several design patterns in PHP 8

Overview

DesignPatternsPHP

Build Status Documentation Status Donate

Read the Docs of DesignPatternsPHP or Download as PDF/Epub

This is a collection of known design patterns and some sample codes on how to implement them in PHP. Every pattern has a small list of examples.

I think the problem with patterns is that often people do know them but don't know when to apply which.

Installation

You should look at and run the tests to see what happens in the example. To do this, you should install dependencies with Composer first:

$ composer install

Read more about how to install and use Composer on your local machine here.

To run the tests use phpunit:

$ ./vendor/bin/phpunit

Using Docker (optional)

You can optionally build and browse the documentation using Docker for Mac, Windows or Linux.

Just run:

$ docker-compose up --build

Go to http://localhost:8080/ to read the generated documentation.

If you want to localize your documentation you can pass the locale as an argument to the docker build:

$ docker-compose build --build-arg language=de
$ docker-compose up

Patterns

The patterns can be structured in roughly three different categories. Please click on the 📓 for a full explanation of the pattern on Wikipedia.

Creational

Structural

Behavioral

More

Localization & Supported Languages

Code Language Documentation
ca Catalan Docs 📓
zh_CN Chinese Docs 📓
nl Dutch Docs 📓
en English Docs 📓
de German Docs 📓
ja Japanese Docs 📓
pl Polish Docs 📓
pt_BR Portuguese-Brazil Docs 📓
ru Russian Docs 📓
es Spanish Docs 📓
es_MX Spanish-Mexican Docs 📓
tr Turkish Docs 📓
bg Bulgarian Docs 📓
fr French Docs 📓
Comments
  • Version in other languages?

    Version in other languages?

    Hey! Whats'up?!

    Is there some version of this repo in other language? I've forked this repo yesterday to translate to portuguese.


    To contribute in translation, check Translation Rule/Hint below

    [important] Before your start, re-fork this project or synchronize your repo with upstream!(because i just do some change)

    Translation Rule/Hint

    1. All po files were generated by all README.rst, Only them (explication of patterns) will be translated, Code and comments should be in English and not change. code is always the core of this repo.
    2. Word for Word translation is not needed, you can add your own explication to make translation much easy to understand.
    3. if you didn't found the language you want to translate, take a look at here, and @shangguokan who will add initial files.
    4. You can use po editor or text editor to translate.
    5. It remain some markup in po files, please be careful not to break reST notation.

    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)
    

    PR

    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

    | 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 |

    Title

    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
    

    FAQ

    1. How can i add some link or bold on the translation string? you can use reST markup. msgstr "External **hyperlinks**, likePython http://www.python.org/_."
    2. How can i test my translation? first, you don't need test your translations. if you want, the repo use Sphinx + reStructuredText a.install sphinx on your computer http://sphinx-doc.org/ b.learn how translation works http://sphinx-doc.org/latest/intl.html c.Install sphinx-intl by pip install sphinx-intl or easy_install sphinx-intl. d.execute $ sphinx-intl build e.execute $ make -e SPHINXOPTS="-D language='pt_BR'" html f.you can find html in folder _build
    opened by leonampd 54
  • Restructure the repository

    Restructure the repository

    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
    |   |-- ...
    
    opened by tonicospinelli 27
  • DesignPatternsPHP available on Read the Docs

    DesignPatternsPHP available on Read the Docs

    address: http://designpatternsphp.readthedocs.org

    | - Q. - | - A. - | | --- | --- | | Tickets | #114 , #115 | | Type | Feature / Documentation | | Techniques | Sphinx + reStructuredText + readthedocs.org | | Participants | @domnikl , @eddiejaoude , @aik099 |

    what has changed and will change:

    • [x] use Pandoc to convert all the README.md to README.rst in script read-the-docs.sh
    • [x] use sphinx tag: literalinclude to embed all related php files in the README.rst of every pattern. in script read-the-docs.sh
    • [x] sphinx-quickstart
    • [x] create TOC tree (index of projet)
    • [x] host on Read the docs
    • [x] add Wikipedia link
    • [x] bug fix
    • [x] reorder php embed files (Top-down)
    • [x] revision
    • [x] finish and ready to merge
    Hello everyone, i found the work in #115 is stop, so i try to continue the work of converting this repo to a documentation/book.
    Do you have any suggestions of the version preview?
    opened by guokan-shang 13
  • docs: add Chinese translation of Interpreter Pattern

    docs: add Chinese translation of Interpreter Pattern

    Translate behavior design patterns into Chinese.

    Translation Content:

    • [x] 3 Behavior design patterns

      • [x] 3.1 Chain of responsibility
      • [x] 3.2. Command
      • [x] 3.3. Interpreter
      • [x] 3.4. Iterator
      • [x] 3.5. Mediator
      • [x] 3.6. Memento
      • [x] 3.7. Null Object
      • [x] 3.8. Observer
      • [x] 3.9. Specification
      • [x] 3.10. State
      • [x] 3.11. Strategy
      • [x] 3.12. Template Method
      • [x] 3.13. Visitor
    opened by autoload 10
  • Iterator bug

    Iterator bug

    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.

    opened by azihassan 10
  • Repository knows about database columns

    Repository knows about database columns

    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?

    Update Illustration

    opened by leocavalcante 10
  • RendererDecorator class should implement RenderableInterface

    RendererDecorator class should implement RenderableInterface

    RendererDecorator.php has this comment but it dosen't implements the interface.

    /**
     * the Decorator MUST implement the RendererInterface contract, this is the key-feature
     * of this design pattern. If not, this is no longer a Decorator but just a dumb
     * wrapper.
     */
    abstract class RendererDecorator {}
    
    opened by adayth 8
  • Composite pattern, why use abstract FormElement?

    Composite pattern, why use abstract FormElement?

    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.

    opened by uteq 8
  • Replace array storage with SplObjectStorage

    Replace array storage with SplObjectStorage

    If you already use SPL interfaces in your example, maybe better to use SplObjectStorage too instead of array to store observers with attach and detach convenient methods? @domnikl What do you think?

    opened by bocharsky-bw 8
  • Presenter Pattern

    Presenter Pattern

    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)?

    opened by michaelachrisco 7
  • Upgrade to PHP7 strict mode

    Upgrade to PHP7 strict mode

    Do NOT merge (yet)

    • [x] Vagrant and Ansible

    Creational

    • [ ] AbstractFactory
    • [ ] Builder
    • [x] FactoryMethod
    • [ ] Multiton
    • [ ] Pool
    • [x] Prototype
    • [ ] SimpleFactory
    • [x] Singleton
    • [x] StaticFactory

    Structural

    • [ ] Adapter
    • [ ] Bridge
    • [ ] Composite
    • [ ] DataMapper
    • [ ] Decorator
    • [ ] DependencyInjection
    • [ ] Facade
    • [ ] FluentInterface
    • [ ] Proxy
    • [ ] Registry

    Behavioral

    • [ ] ChainOfResponsibilities
    • [ ] Command
    • [ ] Iterator
    • [ ] Mediator
    • [ ] Memento
    • [ ] NullObject
    • [ ] Observer
    • [ ] Specification
    • [ ] State
    • [ ] Strategy
    • [ ] TemplateMethod
    • [ ] Visitor

    More

    • [ ] Delegation
    • [ ] ServiceLocator
    • [ ] Repository
    opened by eddiejaoude 7
Option Type for PHP

PHP Option Type This package implements the Option type for PHP! Motivation The Option type is intended for cases where you sometimes might return a v

Johannes 2.4k Dec 26, 2022
A Simple PHP Finite State Machine

Finite, A Simple PHP Finite State Machine Finite is a Simple State Machine, written in PHP. It can manage any Stateful object by defining states and t

Yohan Giarelli 1.3k Dec 31, 2022
A simple stateless production rules engine for PHP 5.3+

Ruler Ruler is a simple stateless production rules engine for PHP 5.3+. Ruler has an easy, straightforward DSL ... provided by the RuleBuilder: $rb =

Justin Hileman 1k Dec 28, 2022
Powerful implementation of the Specification pattern in PHP

RulerZ The central idea of Specification is to separate the statement of how to match a candidate, from the candidate object that it is matched agains

Kévin Gomez 865 Dec 22, 2022
A simple Monad library for PHP

MonadPHP This is a basic Monad library for PHP. Usage Values are "wrapped" in the monad via either the constructor: new MonadPHP\Identity($value) or t

Anthony Ferrara 283 Dec 29, 2022
Sample code for several design patterns in PHP 8

DesignPatternsPHP Read the Docs of DesignPatternsPHP or Download as PDF/Epub This is a collection of known design patterns and some sample codes on ho

null 21k Jan 5, 2023
Mind is the PHP code framework designed for developers. It offers a variety of solutions for creating design patterns, applications and code frameworks.

Mind Mind is the PHP code framework designed for developers. It offers a variety of solutions for creating design patterns, applications and code fram

null 0 Dec 13, 2021
YCOM Impersonate. Login as selected YCOM user 🧙‍♂️in frontend.

YCOM Impersonate Login as selected YCOM user in frontend. Features: Backend users with admin rights or YCOM[] rights, can be automatically logged in v

Friends Of REDAXO 17 Sep 12, 2022
PHP Library that implements several messaging patterns for RabbitMQ

Thumper Thumper is a PHP library that aims to abstract several messaging patterns that can be implemented over RabbitMQ. Inside the examples folder yo

php-amqplib 276 Nov 20, 2022
PHP Library that implements several messaging patterns for RabbitMQ

Thumper Thumper is a PHP library that aims to abstract several messaging patterns that can be implemented over RabbitMQ. Inside the examples folder yo

php-amqplib 276 Nov 20, 2022
Detection of design patterns in PHP code

Pattern Detector for PHP Detects design pattern in your code

Jean-François Lépine 105 Aug 23, 2022
Magento sample data includes a sample store, complete with more than 250 products

Magento sample data includes a sample store, complete with more than 250 products (about 200 of them are configurable products), categories, promotional price rules, CMS pages, banners, and so on. Sample data uses the Luma theme on the storefront.

Magento 203 Dec 16, 2022
Learn how to implement the most important Design Patterns into your PHP application, uses PHP 8.1

Learn how to implement the most important Design Patterns into your PHP application. This project uses PHP 8.1. it has examples for each Pattern and an Article explaining how to use them step by step, their advantages, and disadvantages.

Gabriel Anhaia 203 Dec 15, 2022
Examples of some common design patterns implemented in php

What is a Design Pattern? Design patterns are typical solutions to common problems in software design. Each pattern is like a blueprint that you can c

Bakhtiyor Bahritidinov 4 Feb 11, 2022
Repo do vídeo do youtube de Design Patterns - Decorator

DesignPatternsPHP-Decorator Repo do vídeo do Youtube de Design Patterns - Decorator Link do vídeo Decorator em PHP 8 Imagem de exemplo Link do cadastr

Leonardo Tumadjian 10 Aug 18, 2022
Learning design patterns by implementing them in various programming languages.

design-patterns Learning design patterns by implementing them in various programming languages. Creational design patterns Creational design patterns

Paweł Tryfon 1 Dec 13, 2021
`phplint` is a tool that can speed up linting of php files by running several lint processes at once.

`phplint` is a tool that can speed up linting of php files by running several lint processes at once.

安正超 887 Dec 30, 2022
PHP Email address validator - A library for validating emails against several RFC.

EmailValidator A library for validating emails against several RFC. Supported RFCs This library aims to support RFCs: 5321, 5322, 6530, 6531, 6532, 10

Eduardo Gulias Davis 10.7k Jun 13, 2022
Xenon\LaravelBDSms is a sms gateway package for sending text message to Bangladeshi mobile numbers using several gateways like sslcommerz, greenweb, dianahost,metronet in Laravel framework

Xenon\LaravelBDSms is a sms gateway package for sending text message to Bangladeshi mobile numbers using several gateways for Laravel. You should use

Ariful Islam 95 Jan 3, 2023
a laravel package to create dynamically dashboard views in several templates ( in development)

Laravel Dashboarder A laravel package for generate admin dashboard dynamically based on Tabler template use livewire - alpinejs Installation Run the c

Laravel Iran Community 7 Dec 12, 2022