Frameworks give you a rich toolset to do complex tasks very easy and developers all love it. But then you need to update your framework from one version to another and things are falling apart because of the tight coupling with your business logic.
In this talk I show a couple of actual scenarios that went wrong when we moved from one framework to another and the solutions we applied to abstract business logic from framework logic. Even if you're not planning on migrating frameworks yet, decoupling is a good practice that will give you less headaches in the future.
2. MICHELANGELO VAN DAM
CEO at in2it
Lead PHP architect
Community leader
Coach & mentor
FOSS contributor
Public speaker
3. FRAMEWORKS ARE GREAT!
• They abstract common tasks like email, database connectivity, routing
and a ton more…
• They allow us to quickly develop complex applications
• They offer good to great security and robustness
4. BUT…
• Frameworks have a nasty aftertaste when building business logic
• You need to use their database, log or cache adapter everywhere
• View templates are requiring framework components like
translations, escaping and other trivial purposes
• Best practices require to use modules, bundles or features to
separate business logic components
5. IMPROVEMENTS THROUGH STANDARDS
• The PHP-FIG standards motivates frameworks to use great
components to abstract functionality and ensure interoperability with
other frameworks and tools
• Major frameworks already offer this straight off the bat
• But add their own “secret sauce” to link it within their framework,
even when using Dependency Injection
9. BUSINESS LOGIC AND FRAMEWORKS MIXED
Framework X Business Logic
BL DB
FW DB
FW Logging
FW Mail
FW Service
BL Logging
BL Mail
BL Services
10. APPLYING INTERFACES IN BETWEEN
Framework X Business Logic
FW DB
FW
Logging
FW Mail
FW
Service
BL DB
BL
Logging
BL Mail
BL
Services
DB Interface
Logging Interface
Mail Interface
Service Interface
20. YOUR WAITER
• Interfaces with the hostess to get started
• Interfaces with you to take your order
• Interfaces with the bar for drinks
• Interfaces with the cash register to present you a bill
21. YOUR WAITER
• Receives notification you have arrived at your table
• Receives your order from you
• Receives drinks from the bartender
• Receives food from the kitchen
• Receives money from you
24. WHAT ARE INTERFACES
• Interfaces define a requirement without concrete implementation
• There’s no limit on interfaces implemented
• Everyone understands the “contract” immediately
• One interface per goal, feature or purpose
25. COMMON INTERFACES IN PHP
• Countable
• Iterator (and derivates)
• See language.oop5.interfaces on php.net for more details!
27. BONUS: VERY TESTABLE!!!
• No need to implement concrete code, just use interfaces to guide
your development
• A class can implement multiple interfaces, testing can occur on a
single interface functionality at a time.
29. WHAT ARE EVENTS?
• Events allow us to run tasks in the background and call back when
completed.
• Implements the observer pattern (e.g. SplSubject & SplObserver)
• One observer can have many subscribers
• A subscriber can subscribe to many observer objects
37. GLUE CLASS TO INTERACT 1/3
class SilexServiceProvider implements ServiceProviderInterface
{
public function register(Container $container)
{
$dsn = $container['cb_config_db.dsn'] ?: '';
$username = $container['cb_config_db.username'] ?: '';
$password = $container['cb_config_db.password'] ?: '';
$pdo = new PDO($dsn, $username, $password);
$authorTable = new AuthorTable($pdo);
$authorHydrator = new AuthorHydrator();
$author = new Author();
$bookTable = new BookTable($pdo);
$bookHydrator = new BookHydrator();
$book = new Book();
$memberTable = new MemberTable($pdo);
$memberHydrator = new MemberHydrator();
$member = new Member();
38. GLUE CLASS TO INTERACT 2/3
$serviceLocator = new ServiceLocator();
$serviceLocator
->set('CloudbooksAuthorModelAuthorTable', $authorTable)
->set('CloudbooksAuthorModelAuthorHydrator', $authorHydrator)
->set('CloudbooksAuthorEntityAuthor', $author)
->set('CloudbooksBookModelBookTable', $bookTable)
->set('CloudbooksBookModelBookHydrator', $bookHydrator)
->set('CloudbooksBookEntityBook', $book)
->set('CloudbooksMemberModelMemberTable', $memberTable)
->set('CloudbooksMemberModelMemberHydrator', $memberHydrator)
->set('CloudbooksMemberEntityMember', $member);
}
39. GLUE CLASS TO INTERACT 3/3
$container['cb_author_service'] = $container->factory(function () use ($serviceLocator) {
$serviceFactory = new AuthorServiceFactory();
return $serviceFactory->createService($serviceLocator);
});
$container['cb_book_service'] = $container->factory(function () use ($serviceLocator) {
$serviceFactory = new BookServiceFactory();
return $serviceFactory->createService($serviceLocator);
});
$container['cb_member_service'] = $container->factory(function () use ($serviceLocator) {
$serviceFactory = new MemberServiceFactory();
return $serviceFactory->createService($serviceLocator);
});
}