SlideShare a Scribd company logo
1 of 38
Download to read offline
Modularity and
Layered Data Model
Attila Jenei
2014.
!
www.attilajenei.com
Modularity
Modularity
Our problems:
• Long development time
• Generic functionality in all projects
• Near identical operation of same features
• Hard maintainability
Modularity
What we need?
• Compatible components
• High reusability
• Exchangeable parts
• Configurable system
• Improved maintainability
High-level Modularity
We can
• Remove hard-coded class calls
• Turn Singletons into services
• Use dynamic table names for data layer
• Define keys for soft referencing
Soft References
Keys to
• Class names - simple “new”
• Factories - complex initialization
• Aliases - reusability
• Initializers - additional initialization
Soft References
Managers
• Handling references
• Lazy loading for performance and low-memory
profile
• Shared or own instances
• We can use cloning to prevent recurring
initializations
PHP Example
$user = new User;
!
// turns to
!
$user = clone $services->get(‘ModelUser’);
PHP Example
$path = Config::get(‘ViewPath’);
!
// turns to
!
$path = $services->get(‘MyConfig’)->get(‘ViewPath’);
Example Config
array(

‘invokables’ => array(

‘ModelUser’ => ‘ProjectModelUser’

),

‘factories’ => array(

‘ModelUserTable’ => function ($sm) {

return ProjectModelUserTable(

$sm->get(‘ModelUserTableGateway’));

},

‘ModelUserTableGateway’ => function ($sm) {

return ProjectModelUserTableGateway(

$sm->get(‘ZendDbAdapterAdapter’),

‘user’,

$sm->get(‘ModelUser’));

},

‘ZendDbAdapterAdapter’ => ‘ZendDbAdapterAdapterServiceFactory’,

),

);
A Simple Service Manager
public function get($name)

{

if (isset($this->instances[$name])

{

return $this->instances[$name];

}



if (isset($this->invokables[$name]))

{

$className = $this->invokables[$name];

if (class_exists($className))

{

$instance = new $className;

}

else

{

throw new Exception(‘Unknown class: ’ . $className);

} 

}
A Simple Service Manager
else

if (isset($this->factories[$name])

{

$factory = $this->factories[$name];

if ($factory instanceof FactoryInterface)

{

$factory = array($factory, ‘createService’);

}



if (is_callable($factory)

{

$instance = call_user_func($factory, $this, $name);

}

else

{

throw new Exception(‘Wrong factory: ’ . $name);

}

}
A Simple Service Manager
else

{

throw new Exception(‘Unknown key: ’ . $name);

}



if ($instance)

{

$this->instances[$name] = $instance;



return $instance;

}



throw new Exception(‘No instance: ’ . $name);

}
Data
&
Responsibility
Higher-level OOP
• Database engine independent
• Unknown “outside world”
• Focus (only) on own tasks
• An entity class holds the information and has its
related methods
Entity
• Represents the information
• ≠ database record
• Takes part in execution
Entity
An Object represents
a Database Record.
A Database Record stores
the information of an Object.
Example: CMS
• Page as entity
• Control flow
!
• Column as entity
• Display flow
Data Model
Layers
ENTITY Information
TABLE Entities
TABLE GATEWAY Database Interface
HYDRATOR Object - Information
Entity Class
abstract class Entity

{

protected $serviceLocator;

protected $storedPrimaryKey;

protected $table;



final public function getServiceLocator()

{

return $this->serviceLocator;

}



final public function getStoredPrimaryKey()

{

return $this->storedPrimaryKey;

}



final public function getTable()

{

return $this->table;

}
Entity Class
final public function setServiceLocator(Ser…ace $serviceLocator)

{

$this->serviceLocator = $serviceLocator;

return $this;

}



final public function setStoredPrimaryKey(array $storedPrimaryKey)

{

$this->storedPrimaryKey = $storedPrimaryKey;

return $this;

}



final public function setTable(Table $table)

{

$this->table = $table;

return $this;

}
Entity Class
public function delete()

{

if (!$this->storedPrimaryKey)

{

throw new Exception(‘Entity is not stored’);

}



$this->table->delete($this->storedPrimaryKey);

$this->storedPrimaryKey = array();



return $this;

}



abstract public function exchangeArray(array $data);
Entity Class
public function save()

{

$this->table->save($this);

$reloaded = $this->table->fetchAll($this->storedPrimaryKey)->current();



if ($reloaded)

{

$this->exchangeEntity($reloaded);

}

else

{

throw new Exception(‘Error on reload’);

}

}

}
Example: User Entity
class User extends Entity

{

protected $name;

protected $userID;



public function getName() {…}



public function getUserID() {…}



public function setName($name) {…}



public function setUserID($userID) {…}



.

.

.

Example: User Entity
public function exchangeArray(array $data)

{

$this->name = isset($data[‘name’]) ? $data[‘name’] : null;

$this->userID = isset($data[‘userID’]) ? $data[‘userID’] : null;

$this->storedPrimaryKey = array(‘userID’ => $this->userID);



return $this;

}



public function exchangeEntity(User $entity)

{

$this->name = $entity->name;

$this->userID = $entity->userID;

$this->storedPrimaryKey = $entity->storedPrimaryKey;



return $this;

}
Example: User Entity
public function exchangeArray(array $data)

{

$this->name = isset($data[‘name’]) ? $data[‘name’] : null;

$this->userID = isset($data[‘userID’]) ? $data[‘userID’] : null;

$this->storedPrimaryKey = array(‘userID’ => $this->userID);



return $this;

}



public function exchangeEntity(User $entity)

{

$this->name = $entity->name;

$this->userID = $entity->userID;

$this->storedPrimaryKey = $entity->storedPrimaryKey;



return $this;

}
Hydrator
Table Class
abstract class Table

{

protected $serviceLocator;

protected $tableGateway;



public function __construct(TableGateway $tableGateway)

{

$this->tableGateway = $tableGateway;

}



final public function getServiceLocator() {…}



final public function getTableGateway() {…}



final public function setServiceLocator(…tor) {…}



.

.

.
Table Class
public function delete($where)

{

$this->tableGateway->delete($where);



return $this;

}



final public function fetchAll($where = null)

{

return $this->tableGateway->select($where);

}

}
Example: User Table
class UserTable extends Table

{

public function save(User $entity)

{

$data = array(‘userID’ => $entity->getUserID(), ‘name’ => $entity->getName());



if ($entity->getStoredPrimaryKey())

{

$this->tableGateway->update($data, $entity->getStoredPrimaryKey());

}

else

{

$this->tableGateway->insert($data);

$data[‘userID’] = $this->tableGateway->getLastInsertValue();

}



$entity->setStoredPrimaryKey(array(‘userID’ => $data[‘userID’]));

}
Example: User Table
class UserTable extends Table

{

public function save(User $entity)

{

$data = array(‘userID’ => $entity->getUserID(), ‘name’ => $entity->getName());



if ($entity->getStoredPrimaryKey())

{

$this->tableGateway->update($data, $entity->getStoredPrimaryKey());

}

else

{

$this->tableGateway->insert($data);

$data[‘userID’] = $this->tableGateway->getLastInsertValue();

}



$entity->setStoredPrimaryKey(array(‘userID’ => $data[‘userID’]));

}
Hydrator
TableGateway Class
abstract class TableGateway extends AbstractTableGateway

{

protected $entityPrototype;

protected $serviceLocator;



public function __construct(Adapter $adapter, $table, $entityPrototype)

{

$this->adapter = $adapter;

$this->table = $table;

$this->entityPrototype = $entityPrototype;

$this->resultSetPrototype = new ResultSet;

$this->resultSetPrototype->setArrayObjectPrototype($entityPrototype);

$this->sql = new Sql($adapter, $table);

}



.

.

.
TableGateway Class
final public function getServiceLocator() {…}



final public function setServiceLocator(…) {…}



public function create()

{

return clone $this->entityPrototype;

}

}
AbstractTableGateway Class
Have to implement basic operations:
• select()
• insert()
• update()
• delete()
Example: User - Group
Relation
class User extends Entity

{

.

.

.



protected $group;



public function getGroup()

{

if (!is_object($this->group) && !empty($this->group))

{

$this->group = $this->serviceLocator->get(‘ModelGroupTable’)

->fetchAll(array(‘groupID’ => $this->group))->current();

}



return $this->group;

}
Example: User - Group
Relation
public function getGroupID()

{

return is_object($this->group) ? $this->group->getGroupID() : $this->group;

}
public function setGroup($group) {…}

}
Summary
• Modules - maintainability, reusability
• Network of simpler components - complex system
• Entity-based - focus on information
• Layered Data Model - thinnest database engine related
layer, more portability
http://www.attilajenei.com
www@attilajenei.com
Attila Jenei
2014.

More Related Content

What's hot

Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3
Fabien Potencier
 
Zf Zend Db by aida
Zf Zend Db by aidaZf Zend Db by aida
Zf Zend Db by aida
waraiotoko
 
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Fabien Potencier
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010
Fabien Potencier
 

What's hot (20)

Dependency Injection in Laravel
Dependency Injection in LaravelDependency Injection in Laravel
Dependency Injection in Laravel
 
Mysql & Php
Mysql & PhpMysql & Php
Mysql & Php
 
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for PerformanceMeet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate Frameworks
 
Drupal II: The SQL
Drupal II: The SQLDrupal II: The SQL
Drupal II: The SQL
 
Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3
 
The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of Lithium
 
Drupal 8: Fields reborn
Drupal 8: Fields rebornDrupal 8: Fields reborn
Drupal 8: Fields reborn
 
PHP Data Objects
PHP Data ObjectsPHP Data Objects
PHP Data Objects
 
Zf Zend Db by aida
Zf Zend Db by aidaZf Zend Db by aida
Zf Zend Db by aida
 
CakeFest 2013 keynote
CakeFest 2013 keynoteCakeFest 2013 keynote
CakeFest 2013 keynote
 
PHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php frameworkPHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php framework
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
 
Drupal 8: Forms
Drupal 8: FormsDrupal 8: Forms
Drupal 8: Forms
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010
 

Viewers also liked

Slides for language speech thought..
Slides for language speech thought..Slides for language speech thought..
Slides for language speech thought..
shafiqahshukri
 
High Dynamic Range color grading and display in Frostbite
High Dynamic Range color grading and display in FrostbiteHigh Dynamic Range color grading and display in Frostbite
High Dynamic Range color grading and display in Frostbite
Electronic Arts / DICE
 

Viewers also liked (9)

iOS Home Screen Concept
iOS Home Screen ConceptiOS Home Screen Concept
iOS Home Screen Concept
 
Slides for language speech thought..
Slides for language speech thought..Slides for language speech thought..
Slides for language speech thought..
 
Theories of Speech Perception
Theories of Speech PerceptionTheories of Speech Perception
Theories of Speech Perception
 
Game Engine Architecture
Game Engine ArchitectureGame Engine Architecture
Game Engine Architecture
 
Stochastic Screen-Space Reflections
Stochastic Screen-Space ReflectionsStochastic Screen-Space Reflections
Stochastic Screen-Space Reflections
 
FrameGraph: Extensible Rendering Architecture in Frostbite
FrameGraph: Extensible Rendering Architecture in FrostbiteFrameGraph: Extensible Rendering Architecture in Frostbite
FrameGraph: Extensible Rendering Architecture in Frostbite
 
4K Checkerboard in Battlefield 1 and Mass Effect Andromeda
4K Checkerboard in Battlefield 1 and Mass Effect Andromeda4K Checkerboard in Battlefield 1 and Mass Effect Andromeda
4K Checkerboard in Battlefield 1 and Mass Effect Andromeda
 
High Dynamic Range color grading and display in Frostbite
High Dynamic Range color grading and display in FrostbiteHigh Dynamic Range color grading and display in Frostbite
High Dynamic Range color grading and display in Frostbite
 
Photogrammetry and Star Wars Battlefront
Photogrammetry and Star Wars BattlefrontPhotogrammetry and Star Wars Battlefront
Photogrammetry and Star Wars Battlefront
 

Similar to Modularity and Layered Data Model

Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.js
Jarod Ferguson
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf Conference
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
jsmith92
 

Similar to Modularity and Layered Data Model (20)

Drupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionDrupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency Injection
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.js
 
Php on the desktop and php gtk2
Php on the desktop and php gtk2Php on the desktop and php gtk2
Php on the desktop and php gtk2
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
 
Resource Routing in ExpressionEngine
Resource Routing in ExpressionEngineResource Routing in ExpressionEngine
Resource Routing in ExpressionEngine
 
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
 
What is DDD and how could it help you
What is DDD and how could it help youWhat is DDD and how could it help you
What is DDD and how could it help you
 
Staying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHPStaying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHP
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
 
Your Entity, Your Code
Your Entity, Your CodeYour Entity, Your Code
Your Entity, Your Code
 
Your Entity, Your Code
Your Entity, Your CodeYour Entity, Your Code
Your Entity, Your Code
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 

Recently uploaded

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Recently uploaded (20)

Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 

Modularity and Layered Data Model

  • 1. Modularity and Layered Data Model Attila Jenei 2014. ! www.attilajenei.com
  • 3. Modularity Our problems: • Long development time • Generic functionality in all projects • Near identical operation of same features • Hard maintainability
  • 4. Modularity What we need? • Compatible components • High reusability • Exchangeable parts • Configurable system • Improved maintainability
  • 5. High-level Modularity We can • Remove hard-coded class calls • Turn Singletons into services • Use dynamic table names for data layer • Define keys for soft referencing
  • 6. Soft References Keys to • Class names - simple “new” • Factories - complex initialization • Aliases - reusability • Initializers - additional initialization
  • 7. Soft References Managers • Handling references • Lazy loading for performance and low-memory profile • Shared or own instances • We can use cloning to prevent recurring initializations
  • 8. PHP Example $user = new User; ! // turns to ! $user = clone $services->get(‘ModelUser’);
  • 9. PHP Example $path = Config::get(‘ViewPath’); ! // turns to ! $path = $services->get(‘MyConfig’)->get(‘ViewPath’);
  • 10. Example Config array(
 ‘invokables’ => array(
 ‘ModelUser’ => ‘ProjectModelUser’
 ),
 ‘factories’ => array(
 ‘ModelUserTable’ => function ($sm) {
 return ProjectModelUserTable(
 $sm->get(‘ModelUserTableGateway’));
 },
 ‘ModelUserTableGateway’ => function ($sm) {
 return ProjectModelUserTableGateway(
 $sm->get(‘ZendDbAdapterAdapter’),
 ‘user’,
 $sm->get(‘ModelUser’));
 },
 ‘ZendDbAdapterAdapter’ => ‘ZendDbAdapterAdapterServiceFactory’,
 ),
 );
  • 11. A Simple Service Manager public function get($name)
 {
 if (isset($this->instances[$name])
 {
 return $this->instances[$name];
 }
 
 if (isset($this->invokables[$name]))
 {
 $className = $this->invokables[$name];
 if (class_exists($className))
 {
 $instance = new $className;
 }
 else
 {
 throw new Exception(‘Unknown class: ’ . $className);
 } 
 }
  • 12. A Simple Service Manager else
 if (isset($this->factories[$name])
 {
 $factory = $this->factories[$name];
 if ($factory instanceof FactoryInterface)
 {
 $factory = array($factory, ‘createService’);
 }
 
 if (is_callable($factory)
 {
 $instance = call_user_func($factory, $this, $name);
 }
 else
 {
 throw new Exception(‘Wrong factory: ’ . $name);
 }
 }
  • 13. A Simple Service Manager else
 {
 throw new Exception(‘Unknown key: ’ . $name);
 }
 
 if ($instance)
 {
 $this->instances[$name] = $instance;
 
 return $instance;
 }
 
 throw new Exception(‘No instance: ’ . $name);
 }
  • 15. Higher-level OOP • Database engine independent • Unknown “outside world” • Focus (only) on own tasks • An entity class holds the information and has its related methods
  • 16. Entity • Represents the information • ≠ database record • Takes part in execution
  • 17. Entity An Object represents a Database Record. A Database Record stores the information of an Object.
  • 18. Example: CMS • Page as entity • Control flow ! • Column as entity • Display flow
  • 20. Layers ENTITY Information TABLE Entities TABLE GATEWAY Database Interface HYDRATOR Object - Information
  • 21. Entity Class abstract class Entity
 {
 protected $serviceLocator;
 protected $storedPrimaryKey;
 protected $table;
 
 final public function getServiceLocator()
 {
 return $this->serviceLocator;
 }
 
 final public function getStoredPrimaryKey()
 {
 return $this->storedPrimaryKey;
 }
 
 final public function getTable()
 {
 return $this->table;
 }
  • 22. Entity Class final public function setServiceLocator(Ser…ace $serviceLocator)
 {
 $this->serviceLocator = $serviceLocator;
 return $this;
 }
 
 final public function setStoredPrimaryKey(array $storedPrimaryKey)
 {
 $this->storedPrimaryKey = $storedPrimaryKey;
 return $this;
 }
 
 final public function setTable(Table $table)
 {
 $this->table = $table;
 return $this;
 }
  • 23. Entity Class public function delete()
 {
 if (!$this->storedPrimaryKey)
 {
 throw new Exception(‘Entity is not stored’);
 }
 
 $this->table->delete($this->storedPrimaryKey);
 $this->storedPrimaryKey = array();
 
 return $this;
 }
 
 abstract public function exchangeArray(array $data);
  • 24. Entity Class public function save()
 {
 $this->table->save($this);
 $reloaded = $this->table->fetchAll($this->storedPrimaryKey)->current();
 
 if ($reloaded)
 {
 $this->exchangeEntity($reloaded);
 }
 else
 {
 throw new Exception(‘Error on reload’);
 }
 }
 }
  • 25. Example: User Entity class User extends Entity
 {
 protected $name;
 protected $userID;
 
 public function getName() {…}
 
 public function getUserID() {…}
 
 public function setName($name) {…}
 
 public function setUserID($userID) {…}
 
 .
 .
 .

  • 26. Example: User Entity public function exchangeArray(array $data)
 {
 $this->name = isset($data[‘name’]) ? $data[‘name’] : null;
 $this->userID = isset($data[‘userID’]) ? $data[‘userID’] : null;
 $this->storedPrimaryKey = array(‘userID’ => $this->userID);
 
 return $this;
 }
 
 public function exchangeEntity(User $entity)
 {
 $this->name = $entity->name;
 $this->userID = $entity->userID;
 $this->storedPrimaryKey = $entity->storedPrimaryKey;
 
 return $this;
 }
  • 27. Example: User Entity public function exchangeArray(array $data)
 {
 $this->name = isset($data[‘name’]) ? $data[‘name’] : null;
 $this->userID = isset($data[‘userID’]) ? $data[‘userID’] : null;
 $this->storedPrimaryKey = array(‘userID’ => $this->userID);
 
 return $this;
 }
 
 public function exchangeEntity(User $entity)
 {
 $this->name = $entity->name;
 $this->userID = $entity->userID;
 $this->storedPrimaryKey = $entity->storedPrimaryKey;
 
 return $this;
 } Hydrator
  • 28. Table Class abstract class Table
 {
 protected $serviceLocator;
 protected $tableGateway;
 
 public function __construct(TableGateway $tableGateway)
 {
 $this->tableGateway = $tableGateway;
 }
 
 final public function getServiceLocator() {…}
 
 final public function getTableGateway() {…}
 
 final public function setServiceLocator(…tor) {…}
 
 .
 .
 .
  • 29. Table Class public function delete($where)
 {
 $this->tableGateway->delete($where);
 
 return $this;
 }
 
 final public function fetchAll($where = null)
 {
 return $this->tableGateway->select($where);
 }
 }
  • 30. Example: User Table class UserTable extends Table
 {
 public function save(User $entity)
 {
 $data = array(‘userID’ => $entity->getUserID(), ‘name’ => $entity->getName());
 
 if ($entity->getStoredPrimaryKey())
 {
 $this->tableGateway->update($data, $entity->getStoredPrimaryKey());
 }
 else
 {
 $this->tableGateway->insert($data);
 $data[‘userID’] = $this->tableGateway->getLastInsertValue();
 }
 
 $entity->setStoredPrimaryKey(array(‘userID’ => $data[‘userID’]));
 }
  • 31. Example: User Table class UserTable extends Table
 {
 public function save(User $entity)
 {
 $data = array(‘userID’ => $entity->getUserID(), ‘name’ => $entity->getName());
 
 if ($entity->getStoredPrimaryKey())
 {
 $this->tableGateway->update($data, $entity->getStoredPrimaryKey());
 }
 else
 {
 $this->tableGateway->insert($data);
 $data[‘userID’] = $this->tableGateway->getLastInsertValue();
 }
 
 $entity->setStoredPrimaryKey(array(‘userID’ => $data[‘userID’]));
 } Hydrator
  • 32. TableGateway Class abstract class TableGateway extends AbstractTableGateway
 {
 protected $entityPrototype;
 protected $serviceLocator;
 
 public function __construct(Adapter $adapter, $table, $entityPrototype)
 {
 $this->adapter = $adapter;
 $this->table = $table;
 $this->entityPrototype = $entityPrototype;
 $this->resultSetPrototype = new ResultSet;
 $this->resultSetPrototype->setArrayObjectPrototype($entityPrototype);
 $this->sql = new Sql($adapter, $table);
 }
 
 .
 .
 .
  • 33. TableGateway Class final public function getServiceLocator() {…}
 
 final public function setServiceLocator(…) {…}
 
 public function create()
 {
 return clone $this->entityPrototype;
 }
 }
  • 34. AbstractTableGateway Class Have to implement basic operations: • select() • insert() • update() • delete()
  • 35. Example: User - Group Relation class User extends Entity
 {
 .
 .
 .
 
 protected $group;
 
 public function getGroup()
 {
 if (!is_object($this->group) && !empty($this->group))
 {
 $this->group = $this->serviceLocator->get(‘ModelGroupTable’)
 ->fetchAll(array(‘groupID’ => $this->group))->current();
 }
 
 return $this->group;
 }
  • 36. Example: User - Group Relation public function getGroupID()
 {
 return is_object($this->group) ? $this->group->getGroupID() : $this->group;
 } public function setGroup($group) {…}
 }
  • 37. Summary • Modules - maintainability, reusability • Network of simpler components - complex system • Entity-based - focus on information • Layered Data Model - thinnest database engine related layer, more portability