This is the presentation was given at ConFoo on March 11th by Nate Abele and Joël Perras, and is an introduction to the architectural problems with other frameworks that Lithium was designed to address, and how it addresses them. It also introduces programming paradigms like functional and aspect-oriented programming which address issues that OOP doesn't account for.
Finally, the talk provides a quick overview of the innovative and unparalleled features that Lithium provides, including the data layer, which supports both relational and non-relational databases.
29. Show that object who’s boss.
class User {
function __construct($storage) {
$this->storage = $storage;
}
}
$storage = new SessionStorage('SESSION_ID');
$user = new User($storage);
30. Of course, we want this to abstract this.
Frameworks adore abstractions.
39. And for good measure, have our configurations
for Service Containers in XML files.
40. So....
We have Dependency Injection.
Managed by a Service Container.
Parametrized with XML data.
And the whole thing configured by a Builder.
...to fix one problem.
47. class User {
public function create() {
$logger = new Logger();
$logger->write('Creating a new user...');
$this->_doSomeInitialization();
$this->_databaseConnection->doATransaction($this)->create();
$logger->write('Finished creating user');
}
}
$user = new User();
$user->create();
48. class User {
public $logger;
public function create() {
$this->logger->write('Creating a new user...');
$this->_doSomeInitialization();
$this->_databaseConnection->doATransaction($this)->create();
$this->logger->write('Finished creating user');
}
}
$user = new User();
$user->logger = new Logger();
$user->create();
49. Dependency Injection
• Fixes the problem of static dependencies
• Ignores the problem of static relationships
• Same methods called on injected classes
• No way to introduce new relationships
• Higher overhead, more boilerplate code
61. Design patterns
• Each pattern is only useful in a limited
context
• Layering many design patterns on top of
each other often indicates poor design
choices
• Mis-application arises from trying to run
before you can walk
66. Aspect-Oriented Design
• Separation of concerns
• Domain classes should not know or care about cross-
cutting concerns
• Examples:
• Caching
• Logging
• Access Control, etc.
67. Functional Programming
• Only possible when functions are first-class
citizens
• Referential transparency
• Function purity
74. <?php
namespace applicationbar;
use lithiumutilString;
use lithiumutilCollection;
class Foo extends lithiumcoreObject {
protected $_classes = array(
'cache' => 'lithiumstorageCache',
'logger' => 'lithiumanalysisLogger'
);
public function __construct(array $config = array()) {
// ...
}
protected function _init() {
// ...
}
}
?>
75. <?php
namespace applicationbar;
use lithiumutilString;
use lithiumutilCollection;
class Foo extends lithiumcoreObject {
protected $_classes = array(
'cache' => 'lithiumstorageCache',
'logger' => 'lithiumanalysisLogger'
);
public function __construct(array $config = array()) {
// ...
1
}
protected function _init() {
// ...
}
}
?>
76. public function __construct(array $config = array())
<?php
public function __construct(array $config = array())
namespace applicationbar;
public function __construct(array $config = array())
use public function __construct(array $config =
lithiumutilString; array())
use lithiumutilCollection;
public function __construct(array $config = array())
class Foo extends lithiumcoreObject {
public function __construct(array $config = array())
protected $_classes = array(
public function'lithiumstorageCache', =
'cache' => __construct(array $config array())
'logger' => 'lithiumanalysisLogger'
public function __construct(array $config =
); array())
public function __construct(array $config = array()) {
// ...
}
public function __construct(array $config = array())
protected function _init() {
public function __construct(array $config = array())
// ...
}
public function __construct(array $config = array())
}
public function __construct(array $config = array())
?>
public function __construct(array $config = array())
77. <?php
<?php
namespace applicationbar;
class Foo extends lithiumcoreObject {
use lithiumutilString;
use lithiumutilCollection;
protected function _init() {
class Foo extends lithiumcoreObject {
$or = $some->highOverHead($operation);
$or()->otherwise(HARD_TO_TEST)->code();
protected $_classes = array(
}
'cache' => 'lithiumstorageCache',
} 'logger' => 'lithiumanalysisLogger'
);
?>
public function __construct(array $config = array()) {
// ...
}
protected function _init() {
// ...
2
}
}
?>
78. <?php
<?php
namespace applicationbar;
class Foo extends lithiumcoreObject {
use lithiumutilString;
use lithiumutilCollection;
protected function _init() {
class Foo extends lithiumcoreObject {
$or = $some->highOverHead($operation);
$or()->otherwise(HARD_TO_TEST)->code();
protected $_classes = array(
}
'cache' => 'lithiumstorageCache',
} 'logger' => 'lithiumanalysisLogger'
);
?>
public function __construct(array $config = array()) {
// ...
}
protected function _init() {
// ...
2
}
}
$foo = new Foo(array('init' => false));
?>
79. <?php
namespace applicationbar; 3
use lithiumutilString;
use lithiumutilCollection;
new applicationbarFoo();
// loads app/bar/Foo.php
class Foo extends lithiumcoreObject {
protected $_classes = array(
'cache' => 'lithiumstorageCache',
'logger' => 'lithiumanalysisLogger'
);
public function __construct(array $config = array()) {
// ...
}
protected function _init() {
// ...
}
}
?>
80. <?php
namespace applicationbar;
4
use lithiumutilString;
use lithiumutilCollection;
class Foo extends lithiumcoreObject {
protected $_classes = array(
'cache' => 'lithiumstorageCache',
'logger' => 'lithiumanalysisLogger'
);
public function __construct(array $config = array()) {
// ...
}
protected function _init() {
// ...
}
}
?>
81. <?php
namespace applicationbar;
use lithiumutilString;
use lithiumutilCollection;
class Foo extends lithiumcoreObject {
protected $_classes = array(
'cache' => 'lithiumstorageCache',
'logger' => 'lithiumanalysisLogger' 5
);
public function __construct(array $config = array()) {
// ...
}
protected function _init() {
// ... = $this->_classes['cache'];
$cache
} $cache::write(__CLASS__, $this->_someGeneratedValue());
} }
}
?>
?>
82. <?php
namespace applicationbar;
use lithiumutilString;
use lithiumutilCollection;
class Foo extends lithiumcoreObject {
protected $_classes = array(
'cache' => 'lithiumstorageCache',
'logger' => 'lithiumanalysisLogger' 5
);
$foo = new Foo(array('classes' => array(
public function __construct(array $config = array()) {
'cache' => 'applicationextensionsCache'
// ...
)));
}
protected function _init() {
// ... = $this->_classes['cache'];
$cache
} $cache::write(__CLASS__, $this->_someGeneratedValue());
} }
}
?>
?>
115. Databases
• 1st-class support for document-oriented
databases
• MongoDB & CouchDB: production ready
• Relational databases coming soon
116. <?php
$post = Post::create(array(
'title' => 'Forget the words and sing along',
'body' => 'Everything you know is wrong'
));
$post->save();
$post = Post::find($id);
?>
<h2><?=$post->title; ?></h2>
<p><?=$post->body; ?></p>