interface
MailerInterface {
public function
send
(
$template
,
array
$data
, callable
$callback
);
}
Our adapter would then implement this interface:
class
LaravelMailerAdapter
implements
MailerInterface {
protected
$mailer
;
public function
__construct
(Mailer
$mailer
) {
$this
->
mailer
=
$mailer
;
}
public function
send
(
$template
,
array
$data
, callable
$callback
) {
$this
->
mailer
->
send
(
$template
,
$data
,
$callback
);
}
}
The adapter should then be injected into our controller and used, instead of directly using the
Mail
facade:
Framework Independence
81
class
MailController
extends
BaseController {
protected
$mailer
;
public function
__construct
(MailerInterface
$mailer
) {
$this
->
mailer
=
$mailer
;
}
public function
sendMail
() {
$this
->
mailer
->
send
(
'emails.hello'
,
$data
,
function
(
$message
) {
$message
->
to
(
'you@yoursite.com'
,
'You'
)
->
subject
(
'Hello, You!'
);
});
}
}
To make this work, we’ll register our interface with Laravel’s IoC container so that when the
controller is instantiated, it’ll get a proper instance of
MailerInterface
:
App
::
bind
(
'MailerInterface'
,
function
(
$app
) {
return new
LaravelMailerAdapter(
$foo
[
'mailer'
]);
});
Now the controller gets a concrete instance of
LaravelMailerAdapter
, which conforms to the
controller’s dependency requirement of
MailerInterface
. If we ever decide to switch mailing
mechanisms, we simply write a new adapter and change the binding of
MailerInterface
, and
all our client code that previously got injected with
LaravelMailerAdapter
now gets whatever
this new implementation is.
The popular
Symfony YAML²⁶
component is another great example of where a quick and easy
adapter and interface allow you to be completely decoupled from the concrete implementation
that Symfony provides.
The component is extremely simple to use:
$data
=
Symfony\Component\Yaml\Yaml
::
parse
(
$file
);
That’s all it takes to turn a YAML file into a PHP array. But when using this in our code, we’ll
first want to create an interface to define this functionality that we need:
interface
YamlParserInterface {
public function
parse
(
$fileName
);
}
We then implement this interface with an adapter:
²⁶
http://github.com/symfony/yaml
Framework Independence
82
class
SymfonyYamlAdapter
implements
YamlParserInterface {
public function
parse
(
$fileName
) {
return
Yaml
::
parse
(
$file
);
}
}
Then we simply utilize dependency injection to provide an instance of
SymfonyYamlAdapter
into
any code that needs it:
class
YamlImporter
{
protected
$parser
;
public function
__constructor
(YamlParserInterface
$parser
) {
$this
->
parser
=
$parser
;
}
public function
parseUserFile
(
$fileName
) {
$users
=
$this
->
parser
->
parse
(
$fileName
);
foreach
(
$users
[
'user'
]
as
$user
) {
// ...
}
}
}
Now we’re harnessing the power of Symfony’s YAML parser, without coupling with it. The point
of doing this, again, is so that if we ever need to switch to a different YAML parsing solution in the
future – for whatever reason – we can do so without changing any of our client code. We would
simply write another adapter, and dependency inject that adapter in
SymfonyYamlAdapter
’s
place.
Database Facilities
Most PHP frameworks come bundled with some sort of Database Abstract Library (DBAL),
and sometimes a Query Builder library that makes it easier to build SQL queries, or maybe
an Object Relational Mapping (ORM) library, either conforming to the Active Record or Data
Mapper patterns. Taking advantage of these libraries can lead to easy, and rapid development of
database-powered applications.
As always, though, we want to watch out for coupling too tightly to these database layers.
This is such an important topic, that the entire next chapter, Database Independence
²⁷
is devoted
to it.
²⁷
Framework Independence
83
Do'stlaringiz bilan baham: |