"Seven-day self-made PHP framework" has begun to serial, thank you for your attention and support! Click here
Before reading this article you need to master: PHP syntax, object-oriented
In the process of completing the development of the whole software project, sometimes need to cooperate with many people, sometimes they can do their own independent, no matter what kind, along with the increase in code, write "Out of control", gradually "ugly interface, dirty realization", the project maintenance costs and difficulty rise, to the degree of difficulty to maintain, only reconstruction or redevelopment.
The first Realm
Hypothetical scenario: We need to write a processing class that can manipulate sessions, databases, and file systems at the same time. We might write it that way.
Boundary features: can be run, but seriously coupled
12345678910111213141516171819202122232425262728 |
class
DB{
public
function
DB(
$arg1
,
$arg2
){
echo
‘constructed!‘
.PHP_EOL;
}
}
class
FileSystem{
public
function
FileSystem(
$arg1
,
$arg2
){
echo
‘constructed!‘
.PHP_EOL;
}
}
class
Session{
public
function
Session(
$arg1
,
$arg2
){
echo
‘constructed!‘
.PHP_EOL;
}
}
class
Writer{
public function
Write(){
$db
=
new
DB(1,2);
$filesystem
=
new
FileSystem(3,4);
$session
=
new
Session(5,6);
}
}
$writer
=
new Writer();
$writer
->write();
|
Disadvantages of wording:
1. Constructs the object in the public function, once involves the change as the database parameter, the modification will have the very heavy work
2. The person responsible for designing the writer class needs to be familiar with various APIs such as DB
Is there a way to reduce the coupling degree?
Second realm (parametric dependency)
Hypothetical scenario: The database address needs to be changed frequently because of the customer, and there are a lot of calls to the DB Class (if there are dozens of), I hope you don't have to modify the code of these classes even if you change the database address.
123456789101112131415161718192021222324252627282930313233343536373839 |
class
DB{
public
function
DB(
$arg1
,
$arg2
){
echo
‘constructed!‘
.PHP_EOL;
}
}
class
FileSystem{
public
function
FileSystem(
$arg1
,
$arg2
){
echo
‘constructed!‘
.PHP_EOL;
}
}
class Session{
public
function
Session(
$arg1
,
$arg2
){
echo
‘constructed!‘
.PHP_EOL;
}
}
class
Writer{
protected
$_db
;
protected $_filesystem
;
protected
$_session
;
public
function
Set(
$db
,
$filesystem
,
$session
){
$this
->_db=
$db
;
$this
->_filesystem=
$filesystem
;
$this
->_session=
$session
;
}
public
function
Write(){
}
}
$db
=
new
DB(1,2);
$filesystem
=
new FileSystem(3,4);
$session
=
new
Session(5,6);
$writer
=
new
Writer();
$writer
->Set(
$db
,
$filesystem
,
$session
);
$writer
->write();
|
Although the construction of the DB class is moved to the client, and once the modification is involved, the workload is greatly reduced, but the new problem comes: In order to create a writer class, we need to first create a good DB class, FileSystem class, which is responsible for the writer class, the requirements are very high, He needs to look at a lot of other classes of documents, create them (and possibly initialize them), and then create the writer variables that he wants.
Therefore, we hope that there is a better way of writing, so that the writer class, with a more efficient interface, you can create and invoke the class he wants, even the parameters are not filled.
Third Realm (IOC container)
After the first two realms, we hope to add the following benefits:
1. I hope that the DB class, session class, FileSystem class "Take to be used", without each tedious initialization, such as write $db=new db (ARG1,ARG2), such statements.
2. You want the objects of type db to be "global" and can be called at any time during the entire program run.
3. Programmers who call a type such as db do not have to know too much about this class, and can even create an object with an alias for a string.
The IOC container, which is able to achieve the above objectives, can simply look at the IOC container as a global variable and bind the string and constructor with an associative array.
Let's first implement a container class
123456789 |
class
Container{
public
$bindings
;
public
function
bind(
$abstract
,
$concrete
){
$this
->bindings[
$abstract
]=
$concrete
;
}
public
function
make(
$abstract
,
$parameters
=[]){
return
call_user_func_array(
$this
->bindings[
$abstract
],
$parameters
);
}
}
|
Service Registration (binding)
123456789101112 |
$container
=
new
Container();
$container
->bind(
‘db‘
,
function
(
$arg1
,
$arg2
){
return
new
DB(
$arg1
,
$arg2
);
});
$container
->bind(
‘session‘
,
function
(
$arg1
,
$arg2
){
return
new
Session(
$arg1
,
$arg2
);
});
$container
->bind(
‘fs‘
,
function
(
$arg1
,
$arg2
){
return
new
FileSystem(
$arg1
,
$arg2
);
});
|
Container dependency
12345678910111213 |
class
Writer{
protected
$_db
;
protected
$_filesystem
;
protected
$_session
;
protected
$container
;
public
function
Writer(Container
$container
){
$this
->_db=
$container
->make(
‘db‘
,[1,2]);
$this
->_filesystem=
$container
->make(
‘session‘
,[3,4]);
$this
->_session=
$container
->make(
‘fs‘
,[5,6]);
}
}
$writer
=
new
Writer(
$container
);
|
The triple realm of PHP decoupling (a brief introduction to service containers)