Understanding PHP Dependency Injection Container Series (2) What you need
Dec 28, 2016 am 10:24 AMIn the previous article, we used a specific Web case to illustrate dependency injection. Today we will talk about dependency injection container (Container). First, let us start with an important statement:
大Most of the time, when you use dependency injection to decouple components, you don't need a container.
But if you want to manage many different objects and deal with complex dependencies between objects, containers become very useful.
Remember the example in the first article? Before creating a User object, you must first create a SessionStorage object. This is not a big deal, but I still want to say that this is because you clearly know the objects it depends on before you create the object you need. If there are many objects and the dependencies are complicated (assuming that the SessionStorage class depends on the cache class, the cache class depends on the file class and the inputFilter class, and the file class depends on the stdio class), then it's a problem. . . .
$storage = new SessionStorage('SESSION_ID'); $user = new User($storage);
In the following articles we will introduce the way to implement containers in Symfony 2. But for now, in order to explain containers simply and clearly, we will ignore Symfony for now. The following will use an example in Zend Framework to illustrate:
Zend Framework's Zend_Mail class simplifies email management. It uses PHP's mail() function to send emails by default, but its flexibility is not good. Thankfully, this behavior can be easily changed by providing a transport class.
The following code shows how to create the Zend_Mail class and use a Gmail account to send emails
$transport = new Zend_Mail_Transport_Smtp('smtp.gmail.com', array( 'auth' => 'login', 'username' => 'foo', 'password' => 'bar', 'ssl' => 'ssl', 'port' => 465, )); $mailer = new Zend_Mail(); $mailer->setDefaultTransport($transport);
The Dependency Injection Container (Dependency Injection Container) is a large class that can instantiate and configure the various components it manages. and classes. In order to be able to do this, it must know the parameters and dependencies of the constructor methods of these classes.
The following is a hard-coded container, which still implements the work of obtaining the Zend_Mail object mentioned before:
class Container { public function getMailTransport() { return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array( 'auth' => 'login', 'username' => 'foo', 'password' => 'bar', 'ssl' => 'ssl', 'port' => 465, )); } public function getMailer() { $mailer = new Zend_Mail(); $mailer->setDefaultTransport($this->getMailTransport()); return $mailer; } } //容器的使用也很簡單 $container = new Container(); $mailer = $container->getMailer();
When using the container, if you need to obtain a Zend_Mail object, you do not need to know details of creating it, because all the details of creating an object instance are built into the container. Zend_Mail's dependency on the Mail_Transport class can also be automatically injected into the Zend_Mail object through the container.
Obtaining dependent objects is mainly implemented by getMailTransport(). The power of the container is achieved by this simple get call.
But if you are smart, you must have discovered the problem. There are hard codes in the container (such as the account and password information for sending emails, etc.). So we need to go a step further and add parameters to the container to make the container more useful.
class Container { protected $parameters = array(); public function __construct(array $parameters = array()) { $this->parameters = $parameters; } public function getMailTransport() { return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array( 'auth' => 'login', 'username' => $this->parameters['mailer.username'], 'password' => $this->parameters['mailer.password'], 'ssl' => 'ssl', 'port' => 465, )); } public function getMailer() { $mailer = new Zend_Mail(); $mailer->setDefaultTransport($this->getMailTransport()); return $mailer; } }
Now you can easily switch the account and password for sending emails through the parameters of the container constructor
$container = new Container(array( 'mailer.username' => 'foo', 'mailer.password' => 'bar', )); $mailer = $container->getMailer();
If you feel that the Zend_Mail class cannot meet the current needs (for example, when testing, you need to do some logging), If you want to easily switch the mail sending class, you can also pass the class name through the parameters of the container constructor
class Container { // ... public function getMailer() { $class = $this->parameters['mailer.class']; $mailer = new $class(); $mailer->setDefaultTransport($this->getMailTransport()); return $mailer; } } $container = new Container(array( 'mailer.username' => 'foo', 'mailer.password' => 'bar', 'mailer.class' => 'MyTest_Mail', )); $mailer = $container->getMailer();
Finally, considering that the customer does not need to re-instantiate it every time when obtaining the mailer object (occupying overhead), The container should provide the same object instance every time.
Therefore, the program uses the protected static array $shared to store the first instantiated object. In the future, when the user obtains the mailer, the first instantiated object will be returned
class Container { static protected $shared = array(); // ... public function getMailer() { if (isset(self::$shared['mailer'])) { return self::$shared['mailer']; } $class = $this->parameters['mailer.class']; $mailer = new $class(); $mailer->setDefaultTransport($this->getMailTransport()); return self::$shared['mailer'] = $mailer; } }
Container Encapsulating these basic functions, the container needs to manage the instantiation and configuration of objects. These objects themselves do not know that they are managed by the container, and they can ignore the existence of the container. This is why the container can manage any PHP class. It would be better if the object itself uses dependency injection to handle dependencies, but of course this is not necessary.
But manually creating and maintaining containers can quickly become a nightmare. The following article will describe how Symfony 2 implements containers.
The above is what you need to understand the PHP dependency injection container series (2). For more related content, please pay attention to the PHP Chinese website (www.miracleart.cn)!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

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

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

The method to get the current session ID in PHP is to use the session_id() function, but you must call session_start() to successfully obtain it. 1. Call session_start() to start the session; 2. Use session_id() to read the session ID and output a string similar to abc123def456ghi789; 3. If the return is empty, check whether session_start() is missing, whether the user accesses for the first time, or whether the session is destroyed; 4. The session ID can be used for logging, security verification and cross-request communication, but security needs to be paid attention to. Make sure that the session is correctly enabled and the ID can be obtained successfully.

To extract substrings from PHP strings, you can use the substr() function, which is syntax substr(string$string,int$start,?int$length=null), and if the length is not specified, it will be intercepted to the end; when processing multi-byte characters such as Chinese, you should use the mb_substr() function to avoid garbled code; if you need to intercept the string according to a specific separator, you can use exploit() or combine strpos() and substr() to implement it, such as extracting file name extensions or domain names.

UnittestinginPHPinvolvesverifyingindividualcodeunitslikefunctionsormethodstocatchbugsearlyandensurereliablerefactoring.1)SetupPHPUnitviaComposer,createatestdirectory,andconfigureautoloadandphpunit.xml.2)Writetestcasesfollowingthearrange-act-assertpat

In PHP, the most common method is to split the string into an array using the exploit() function. This function divides the string into multiple parts through the specified delimiter and returns an array. The syntax is exploit(separator, string, limit), where separator is the separator, string is the original string, and limit is an optional parameter to control the maximum number of segments. For example $str="apple,banana,orange";$arr=explode(",",$str); The result is ["apple","bana

JavaScript data types are divided into primitive types and reference types. Primitive types include string, number, boolean, null, undefined, and symbol. The values are immutable and copies are copied when assigning values, so they do not affect each other; reference types such as objects, arrays and functions store memory addresses, and variables pointing to the same object will affect each other. Typeof and instanceof can be used to determine types, but pay attention to the historical issues of typeofnull. Understanding these two types of differences can help write more stable and reliable code.

std::chrono is used in C to process time, including obtaining the current time, measuring execution time, operation time point and duration, and formatting analysis time. 1. Use std::chrono::system_clock::now() to obtain the current time, which can be converted into a readable string, but the system clock may not be monotonous; 2. Use std::chrono::steady_clock to measure the execution time to ensure monotony, and convert it into milliseconds, seconds and other units through duration_cast; 3. Time point (time_point) and duration (duration) can be interoperable, but attention should be paid to unit compatibility and clock epoch (epoch)

ToaccessenvironmentvariablesinPHP,usegetenv()orthe$_ENVsuperglobal.1.getenv('VAR_NAME')retrievesaspecificvariable.2.$_ENV['VAR_NAME']accessesvariablesifvariables_orderinphp.iniincludes"E".SetvariablesviaCLIwithVAR=valuephpscript.php,inApach

LateStaticBindinginPHPallowsstatic::torefertotheclassinitiallycalledatruntimeininheritancescenarios.BeforePHP5.3,self::alwaysreferencedtheclasswherethemethodwasdefined,causingChildClass::sayHello()tooutput"ParentClass".Withlatestaticbinding
