search
HomeBackend DevelopmentPHP Tutorialphp essence php design pattern

1. Choose the most appropriate design pattern

Nothing is perfect, and no one ever said design patterns were a strict one-size-fits-all solution. So you can change these modes to make them more suitable for the job at hand. For some design patterns, they are inherent in the program they belong to; while for other design patterns, you can change the pattern itself. It is common for modes to cooperate and work together. They form the basis of (at least part of) the entire application.

2. Singleton mode

  1. // The Database class represents our global DB connection

  2. class Database{
  3. // A static variable to hold our single instance
  4. private static $_instance = null;
  5. // Make the constructor private to ensure singleton
  6. private function __construct()
  7. {
  8. echo 'constructor';
  9. }
  10. // A method to get our singleton instance

  11. public static function getInstance()
  12. {
  13. if (!(self::$_instance instanceof Database)) {
  14. self::$_instance = new Database();
  15. }
  16. return self::$_instance;
  17. }
  18. }
  19. var_dump($database);

Copy code

Problem: Two instances cannot be created using singleton mode. Traits can be used to solve the problem of creating two The problem of different types of instances, but still does not solve the problem of creating two identical instances (which can be solved by registry mode).

Create two instances of different classes Code:

  1. trait Singleton {
  2. private static $_instance = null;
  3. public static function getInstance() {
  4. $class = __CLASS__;
  5. if(!(self::$_instance instanceof $class)) {
  6. self::$_instance = new $class;
  7. }
  8. return self::$_instance;
  9. }
  10. }
  11. class DB {
  12. }
  13. class DBWriteConnection extends DB {
  14. use Singleton;
  15. private function __construct() {
  16. echo 'DBWriteConnection
    ';
  17. }
  18. }
  19. class DBReadConnection extends DB {
  20. use Singleton;
  21. private function __construct() {
  22. echo 'DBReadConnection
    ';
  23. }
  24. }
  25. $dbWriteConnection = DBWriteConnection::getInstance();
  26. var_dump($dbWriteConnection);
Copy code

3. Registry mode The registry pattern is simply a single global class that allows code to retrieve the same instance of an object when you need it, and to create another instance when you need it (those global instances will be accessed again on request).

Registry class:

  1. class Registry {

  2. /**
  3. * @var array The store for all of our objects
  4. */
  5. static private $_store = array();
  6. /**
  7. * Add an object to the registry
  8. *
  9. * If you do not specify a name the classname is used
  10. *
  11. * @param mixed $object The object to store
  12. * @param string $name Name used to retrieve the object
  13. * @return void
  14. * @throws Exception
  15. */
  16. static public function add($ object, $name = null)
  17. {
  18. // Use the classname if no name given, simulates singleton
  19. $name = (!is_null($name)) ?$name:get_class($object);
  20. if (isset(self ::$_store[$name])) {
  21. throw new Exception("Object already exists in registry");
  22. }
  23. self::$_store[$name]= $object;
  24. }
  25. /**
  26. * Get an object from the registry
  27. *
  28. * @param string $name Object name, {@see self::set()}
  29. * @return mixed
  30. * @throws Exception
  31. */
  32. static public function get($name)
  33. {
  34. if (!self::contains($name)) {
  35. throw new Exception("Object does not exist in registry");
  36. }> ;
  37. return self::$_store[$name];

  38. }
  39. /**
  40. * Check if an object is in the registry
  41. *
  42. * @param string $name Object name, {@see self::set()}
  43. * @return bool
  44. */
  45. static public function contains($name)
  46. {
  47. if (!isset(self::$ _store[$name])) {
  48. return false;
  49. }
  50. return true;
  51. }
  52. /**
  53. * Remove an object from the registry
  54. *
  55. * @param string $name Object name, {@see self::set()}
  56. * @returns void
  57. */
  58. static public function remove($name)
  59. {
  60. if (self::contains( $name)) {
  61. unset(self::$_store[$name]);
  62. }
  63. }
  64. }
Copy code

Outside the class, use the Registry class:

  1. require 'Registry.php';

  2. class DBReadConnection {}

  3. class DBWriteConnection {}
  4. $read = new DBReadConnection;

  5. Registry::add($read);
  6. $write = new DBWriteConnection;

  7. Registry::add($write);
  8. / / To get the instances, anywhere in our code:

  9. $read = Registry::get('DBReadConnection');
  10. $write = Registry::get('DBWriteConnection');
  11. var_dump ($read);

  12. var_dump($write);
Copy code

Use the Registry table class inside the class, and the user does not interact with the Registry.

Sample code:

  1. require 'Registry.php';

  2. abstract class DBConnection {

  3. static public function getInstance($name = null)
  4. {
  5. // Get the late-static-binding version of __CLASS__
  6. $class = get_called_class();
  7. // Allow passing in a name to get multiple instances
  8. // If you do not pass a name, it functions as a singleton
  9. $name = (! is_null($name)) ? $name:$class;
  10. if (!Registry::contains($name)) {
  11. $instance = new $class();
  12. Registry::add($instance, $name);
  13. }
  14. return Registry::get($name);
  15. }
  16. }
  17. class DBWriteConnection extends DBConnection {

  18. public function __construct()
  19. {
  20. echo 'DBWriteConnection
    ' ;
  21. }
  22. }
  23. class DBReadConnection extends DBConnection {

  24. public function __construct()
  25. {
  26. echo 'DBReadConnection
    ';
  27. }
  28. }
  29. < ;p>$dbWriteConnection = DBWriteConnection::getInstance('abc');
  30. var_dump($dbWriteConnection);
  31. $dbReadConnection = DBReadConnection::getInstance();
  32. var_dump($dbReadConnection);
Copy code

4.Factory mode The factory pattern manufactures objects, just like its namesake steel and concrete industry. Usually, we use the factory pattern to initialize concrete implementations of the same abstract class or interface.

In general, although factory mode is rarely used, it is still the most suitable for initializing many variants of driver-based installation. For example different configurations, sessions or caching storage engines. The greatest value of the factory pattern is that it can encapsulate multiple object settings into a single, simple method call.

  1. /**
  2. * Log Factory
  3. *
  4. * Setup and return a file, mysql, or sqlite logger
  5. */
  6. class Log_Factory {
  7. /**
  8. * Get a log object
  9. *
  10. * @param string $type The type of logging backend, file, mysql or sqlite
  11. * @param array $options Log class options
  12. */
  13. public function getLog($type = 'file', array $options)
  14. {
  15. // Normalize the type to lowercase
  16. $type = strtolower($type);
  17. // Figure out the class name and include it
  18. $class = "Log_" .ucfirst($type);
  19. require_once str_replace('_', DIRECTORY_SEPARATOR, $ class) . '.php';
  20. // Instantiate the class and set the appropriate options
  21. $log = new $class($options);
  22. switch ($type) {
  23. case 'file':
  24. $log-> ;setPath($options['location']);
  25. break;
  26. case 'mysql':
  27. $log->setUser($options['username']);
  28. $log->setPassword($options[' password']);
  29. $log->setDBName($options['location']);
  30. break;
  31. case 'sqlite':
  32. $log->setDBPath($otions['location']);
  33. break ;
  34. }
  35. return $log;
  36. }
  37. }
Copy code

5. Iteration mode The iteration pattern allows us to add the performance of foreach to the internally stored data of any object, not just to public properties. It overrides the default foreach behavior and allows us to inject business logic into the loop.

(1) Use Iterator interface

  1. class BasicIterator implements Iterator {

  2. private $key = 0;
  3. private $data = array(
  4. "hello",
  5. "world",
  6. );
  7. < ;p> public function __construct() {
  8. $this->key = 0;
  9. }
  10. public function rewind() {

  11. $this->key = 0;
  12. }< ;/p>
  13. public function current() {

  14. return $this->data[$this->key];
  15. }
  16. public function key() {

  17. return $this->key;
  18. }
  19. public function next() {

  20. $this->key++;
  21. return true;
  22. }
  23. return isset($this->data[$this->key]);

  24. }
  25. }
  26. $iterator = new BasicIterator();

  27. $iterator->rewind();
  28. do {

  29. $key = $iterator->key();
  30. $value = $iterator->current();
  31. echo $ key .': ' .$value . PHP_EOL;
  32. } while ($iterator->next() && $iterator->valid());
  33. $iterator = new BasicIterator ();
  34. foreach ($iterator as $key => $value) {
  35. echo $key .': ' .$value . PHP_EOL;
  36. }
Copy code

(2 ) Traverse the array using the RecursiveIteratorIterator iterator

  1. $array = array(

  2. "Hello", // Level 1
  3. array(
  4. "World" // Level 2
  5. ),
  6. array(
  7. "How", // Level 2
  8. array(
  9. "are", // Level 3
  10. "you" // Level 3
  11. )
  12. ),
  13. "doing?" // Level 1
  14. );
  15. $recursiveIterator = new RecursiveArrayIterator($array);

  16. $recursiveIteratorIterator = new RecursiveIteratorIterator($recursiveIterator);

  17. foreach ($recursiveIteratorIterator as $key => $value ) {

  18. echo "Depth: " . $recursiveIteratorIterator->getDepth() . PHP_EOL;
  19. echo "Key: " . $key . PHP_EOL;
  20. echo "Value: " .$value . PHP_EOL;
  21. }> ;
Copy code

(3)用FilterIterator迭代器实现过滤

  1. class EvenFilterIterator extends FilterIterator {

  2. /**
  3. * Accept only even-keyed values
  4. *
  5. * @return bool
  6. */
  7. public function accept()
  8. {
  9. // Get the actual iterator
  10. $iterator = $this->getInnerIterator();
  11. // Get the current key
  12. $key = $iterator->key();
  13. // Check for even keys
  14. if ($key % 2 == 0) {
  15. return true;
  16. }
  17. return false;
  18. }
  19. }
  20. $array = array(

  21. 0 => "Hello",
  22. 1 => "Everybody Is",
  23. 2 => "I'm",
  24. 3 => "Amazing",
  25. 4 => "The",
  26. 5 => "Who",
  27. 6 => "Doctor",
  28. 7 => "Lives"
  29. );
  30. // Create an iterator from our array

  31. $iterator = new ArrayIterator($array);
  32. // Create our FilterIterator

  33. $filterIterator = new EvenFilterIterator($iterator);
  34. // Iterate

  35. foreach ($filterIterator as $key => $value) {
  36. echo $key .': '. $value . PHP_EOL;
  37. }
  38. ?>
复制代码

(4)RegexIterator迭代器

  1. // Create a RecursiveDirectoryIterator

  2. $directoryIterator = new RecursiveDirectoryIterator("./");
  3. // Create a RecursiveIteratorIterator to recursively iterate

  4. $recursiveIterator = new RecursiveIteratorIterator($directoryIterator);
  5. // Createa filter for *Iterator*.php files

  6. $regexFilter = new RegexIterator($recursiveIterator, '/(.*?)Iterator(.*?).php$/');
  7. // Iterate

  8. foreach ($regexFilter as $key => $file) {
  9. /* @var SplFileInfo $file */
  10. echo $file->getFilename() . PHP_EOL;
  11. }
复制代码

功能:找到所有的php文件

(4)LimitItertor迭代器,像SQL中的LIMIT

  1. // Define the array

  2. $array = array(
  3. 'Hello',
  4. 'World',
  5. 'How',
  6. 'are',
  7. 'you',
  8. 'doing?'
  9. );
  10. // Create the iterator

  11. $iterator = new ArrayIterator($array);
  12. // Create the limiting iterator, to get the first 2 elements

  13. $limitIterator = new LimitIterator($iterator, 0, 2);
  14. // Iterate

  15. foreach ($limitIterator as $key => $value) {
  16. echo $key .': '. $value . PHP_EOL;
  17. }
复制代码

6. Observer mode (observer)

The core of the observer pattern is that your application registers a callback, which will trigger it when a specific event occurs.

  1. /**

  2. * The Event Class
  3. *
  4. * With this class you can register callbacks that will
  5. * be called (FIFO) for a given event.
  6. */
  7. class Event {
  8. /**
  9. * @var array A multi-dimentional array of events => callbacks
  10. */
  11. static protected $callbacks = array();
  12. / **
  13. * Register a callback
  14. *
  15. * @param string $eventName Name of the triggering event
  16. * @param mixed $callback An instance of Event_Callback or a Closure
  17. */
  18. static public function registerCallback($eventName, $callback)
  19. {
  20. if (!($callback instanceof Event_Callback) && !($callback instanceof Closure)) {
  21. throw new Exception("Invalid callback! ");
  22. }
  23. $eventName = strtolower($eventName);
  24. self::$callbacks[$eventName][] = $callback;
  25. }
  26. /**
  27. * Trigger an event
  28. *
  29. * @param string $eventName Name of the event to be triggered
  30. * @param mixed $data The data to be sent to the callback
  31. */
  32. static public function trigger ($eventName, $data)
  33. {
  34. $eventName = strtolower($eventName);
  35. if (isset(self::$callbacks[$eventName])) {
  36. foreach (self::$callbacks[$eventName] as $callback) {
  37. self::callback($callback, $data);
  38. }
  39. }
  40. }
  41. /**
  42. * Perform the callback
  43. *
  44. * @param mixed $callback An instance of Event_Callback or a Closure
  45. * @param mixed $data The data sent to the callback
  46. */
  47. static protected function callback($callback, $data)
  48. {
  49. if ( $callback instanceof Closure) {
  50. $callback($data);
  51. } else {
  52. $callback->run($data);
  53. }
  54. }
  55. }
  56. /**

  57. * The Event Callback interface
  58. *
  59. * If you do not wish to use a closure
  60. * you can define a class that extends
  61. * this instead. The run method will be
  62. * called when the event is triggered.
  63. */
  64. interface Event_Callback {
  65. public function run($data);
  66. }
  67. /**

  68. * Logger callback
  69. */
  70. class LogCallback implements Event_Callback {
  71. public function run($data )
  72. {
  73. echo "Log Data" . PHP_EOL;
  74. var_dump($data);
  75. }
  76. }
  77. // Register the log callback

  78. Event::registerCallback('save', new LogCallback());
  79. // Register the clear cache callback as a closure

  80. Event::registerCallback('save', function ($data) {
  81. echo "Clear Cache" . PHP_EOL;
  82. var_dump($data);
  83. });
  84. class MyDataRecord {

  85. public function save()
  86. {
  87. // Save data
  88. // Trigger the save event
  89. Event::trigger ('save', array("Hello", "World"));
  90. }
  91. }
  92. // Instantiate a new data record

  93. $data = new MyDataRecord();
  94. $data ->save(); // 'save' Event is triggered here
Copy code

7. Dependency injection mode Dependency injection pattern allows classes to use this behavior to inject dependencies into this class.

  1. /**

  2. * Log Class
  3. */
  4. class Log {
  5. /**
  6. * @var Log_Engine_Interface
  7. */
  8. protected $engine = false;
  9. /**
  10. * Add an event to the log
  11. *
  12. * @param string $message
  13. */
  14. public function add($message)
  15. {
  16. if (!$this->engine) {
  17. throw new Exception('Unable to write log. No Engine set.');
  18. }
  19. $data['datetime'] = time();
  20. $data['message'] = $message;
  21. $session = Registry::get('session');
  22. $data['user'] = $session->getUserId();
  23. $this->engine->add($data);
  24. }
  25. /**
  26. * Set the log data storage engine
  27. *
  28. * @param Log_Engine_Interface $Engine
  29. */
  30. public function setEngine(Log_Engine_Interface $engine)
  31. {
  32. $this->engine = $engine ;
  33. }
  34. /**
  35. * Retrieve the data storage engine
  36. *
  37. * @return Log_Engine_Interface
  38. */
  39. public function getEngine()
  40. {
  41. return $this->engine;
  42. }
  43. }
  44. interface Log_Engine_Interface {

  45. /* *
  46. * Add an event to the log
  47. *
  48. * @param string $message
  49. */
  50. public function add(array $data);
  51. }
  52. class Log_Engine_File implements Log_Engine_Interface {

  53. /**
  54. * Add an event to the log
  55. *
  56. * @param string $message
  57. */
  58. public function add(array $data )
  59. {
  60. $line = '[' .data('r', $data['datetime']). '] ' .$data['message']. ' User: ' .$data['user'] . PHP_EOL;
  61. $config = Registry::get('site-config');
  62. if (!file_put_contents($config['location'], $line, FILE_APPEND)) {
  63. throw new Exception("An error occurred writing to file.");
  64. }
  65. }
  66. }
  67. $engine = new Log_Engine_File();

  68. $log = new Log();

  69. $log->setEngine($engine);
  70. // Add it to the registry

  71. Registry::add($log);
Copy code

Dependency injection does not require factory mode, and there is no need to understand the relevant knowledge of each different storage engine. This means that any developer using the logging class can add their own storage engine and simply compose the interface.

8. Model-View-Controller Model-View-Controller, also known as the MVC pattern, is a way of describing the relationship between three different levels of an application. Model-Data Layer All output data comes from the model. It may be a database, web service or file. View-presentation layer is responsible for taking data out of the model and outputting it to the user. The controller-application flow layer calls the corresponding model according to the user's request to retrieve the requested data, and then calls the view to display the results of the operation to the user.

A typical MVC architecture diagram: php mvc架构图

9. Understanding of patterns
Patterns are the best solutions to many common problems.

Articles you may be interested in:

  • php design patterns: singleton mode, factory mode and observer mode
  • In-depth explanation of PHP design pattern examples
  • php design pattern example command pattern
  • php design pattern example observer pattern (2)
  • PHP Design Pattern Example Observer Pattern
  • php design pattern example factory pattern
  • php design pattern example singleton pattern
  • Example of Observer pattern in PHP design pattern
  • PHP design pattern factory pattern example code
  • PHP design pattern singleton pattern example code
  • Introduction to common PHP design patterns: factory pattern and singleton pattern
  • Learn PHP design pattern singleton pattern
  • Study notes on three commonly used design patterns in PHP
  • Learning the Singleton Pattern of PHP Design Pattern


Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
What data can be stored in a PHP session?What data can be stored in a PHP session?May 02, 2025 am 12:17 AM

PHPsessionscanstorestrings,numbers,arrays,andobjects.1.Strings:textdatalikeusernames.2.Numbers:integersorfloatsforcounters.3.Arrays:listslikeshoppingcarts.4.Objects:complexstructuresthatareserialized.

How do you start a PHP session?How do you start a PHP session?May 02, 2025 am 12:16 AM

TostartaPHPsession,usesession_start()atthescript'sbeginning.1)Placeitbeforeanyoutputtosetthesessioncookie.2)Usesessionsforuserdatalikeloginstatusorshoppingcarts.3)RegeneratesessionIDstopreventfixationattacks.4)Considerusingadatabaseforsessionstoragei

What is session regeneration, and how does it improve security?What is session regeneration, and how does it improve security?May 02, 2025 am 12:15 AM

Session regeneration refers to generating a new session ID and invalidating the old ID when the user performs sensitive operations in case of session fixed attacks. The implementation steps include: 1. Detect sensitive operations, 2. Generate new session ID, 3. Destroy old session ID, 4. Update user-side session information.

What are some performance considerations when using PHP sessions?What are some performance considerations when using PHP sessions?May 02, 2025 am 12:11 AM

PHP sessions have a significant impact on application performance. Optimization methods include: 1. Use a database to store session data to improve response speed; 2. Reduce the use of session data and only store necessary information; 3. Use a non-blocking session processor to improve concurrency capabilities; 4. Adjust the session expiration time to balance user experience and server burden; 5. Use persistent sessions to reduce the number of data read and write times.

How do PHP sessions differ from cookies?How do PHP sessions differ from cookies?May 02, 2025 am 12:03 AM

PHPsessionsareserver-side,whilecookiesareclient-side.1)Sessionsstoredataontheserver,aremoresecure,andhandlelargerdata.2)Cookiesstoredataontheclient,arelesssecure,andlimitedinsize.Usesessionsforsensitivedataandcookiesfornon-sensitive,client-sidedata.

How does PHP identify a user's session?How does PHP identify a user's session?May 01, 2025 am 12:23 AM

PHPidentifiesauser'ssessionusingsessioncookiesandsessionIDs.1)Whensession_start()iscalled,PHPgeneratesauniquesessionIDstoredinacookienamedPHPSESSIDontheuser'sbrowser.2)ThisIDallowsPHPtoretrievesessiondatafromtheserver.

What are some best practices for securing PHP sessions?What are some best practices for securing PHP sessions?May 01, 2025 am 12:22 AM

The security of PHP sessions can be achieved through the following measures: 1. Use session_regenerate_id() to regenerate the session ID when the user logs in or is an important operation. 2. Encrypt the transmission session ID through the HTTPS protocol. 3. Use session_save_path() to specify the secure directory to store session data and set permissions correctly.

Where are PHP session files stored by default?Where are PHP session files stored by default?May 01, 2025 am 12:15 AM

PHPsessionfilesarestoredinthedirectoryspecifiedbysession.save_path,typically/tmponUnix-likesystemsorC:\Windows\TemponWindows.Tocustomizethis:1)Usesession_save_path()tosetacustomdirectory,ensuringit'swritable;2)Verifythecustomdirectoryexistsandiswrita

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

MantisBT

MantisBT

Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.