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 📓
it Italian 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
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
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
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
Live chat with several people.

chat What can you do on this application? you can create an account you can talk live with several people you can edit any information on your account

Narcis Lazar 8 Nov 10, 2022
🐋 This project aims to broaden knowledge of system administration by using Docker: virtualizing several Docker images, creating them in a new personal virtual machine.

?? This project aims to broaden knowledge of system administration by using Docker: virtualizing several Docker images, creating them in a new personal virtual machine.

Anton Kliek 1 Jan 26, 2022
Invo - Sample application for the Phalcon PHP Framework

INVO Application Phalcon is a web framework delivered as a C extension providing high performance and lower resource consumption. This is a sample app

The Phalcon PHP Framework 344 Dec 14, 2022
Album-o-rama - Sample application for the Phalcon PHP Framework.

Album O'Rama Phalcon PHP is a web framework delivered as a C extension providing high performance and lower resource consumption. This is a sample app

The Phalcon PHP Framework 84 Oct 7, 2022
Sample application to bookmark links, where interface build with Angular.js + Twitter Bootstrap and server powered by PHP with Slim Framework

RESTful Bookmarks PHP Slim TODO: review and update FrontEnd Sample application to bookmark links, where interface build with Angular.js + Twitter Boot

Erko Bridee 50 Dec 15, 2021
A sample project to showcase a real world example and benchmarks for crowphp

CrowPHP Sample project This project is to showcase an example of how a real world project might look like. It has two basic endpoints to show-case the

Crow PHP 3 Aug 16, 2021
Sample Web Application in Laravel with tailwind css

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Mulindwa Denis 1 Nov 26, 2021
A highly compressed version of the magento 1.9 sample data and a script to create it.

Compressed Magento 1.9 Sample Data The following variations are available: 65M compressed-magento-sample-data-1.9.2.4.tgz 64M compressed-magento-sampl

Vinai Kopp 120 Sep 9, 2022
The easiest way to match data structures like JSON/PlainText/XML against readable patterns. Sandbox:

PHP Matcher Library created for testing all kinds of JSON/XML/TXT/Scalar values against patterns. API: PHPMatcher::match($value = '{"foo": "bar"}', $p

Coduo 774 Dec 31, 2022
CDK patterns for serverless container with AWS Fargate

cdk-fargate-patterns CDK patterns for serverless container with AWS Fargate DualAlbFargateService Inspired by Vijay Menon from the AWS blog post intro

Pahud Hsieh 48 Sep 1, 2021
the examples of head first object oriented analysis & design - in PHP

Head First object oriented analysis & design in (PHP) after cloning the repository, you have to install the project's dependancies by running the foll

Muhammed ElFeqy 3 Oct 16, 2021
Design Pattern Examples in PHP

Design Patterns in PHP This repository is part of the Refactoring.Guru project. It contains PHP examples for all classic GoF design patterns. Each pat

Refactoring.Guru 909 Dec 22, 2022