Skip to end of metadata
Go to start of metadata
You are viewing an old version of this page. View the current version. Compare with Current  |   View Page History

General Goals

  • SHOULD do less in each sub-component
  • SHOULD have a more clear and concise API in each sub-componet
  • SHOULD create a set of sub-components that have a small core feature-set, with many opt-in injectable features
  • SHOULD have more reuse of base ZF components (Zend\Registry, Zend\Cache, Zend\SignalSlot to name a few)
  • SHOULD create an API that is open to extension at all times
  • SHOULD favor composition over inheritance for better flexibility and dependency injection
  • SHOULD attempt to keep each components API as minimal as possible to allow for growth over the 2.0 time period
  • SHOULD NOT be dependent on any 3rd party code
  • SHOULD create a set of interfaces and best practices to facilitate plug-ability in all Zend\DB core components
  • SHOULD NOT include features in core components that can be solved by the Plug-in architecture
  • SHOULD NOT attempt to solve problems in the Model domain:
    • like mapping of column names in various components

Motivation & Discussion

  • Plugability is a major step forward for a database abstraction layer. Over the past few years, as the current iteration has become more popular, more features are requested. Each new feature request generally comes with it's own concerns that apply to the project as a whole: "How useful is the feature?", "How does this feature impact performance?", "How wide spread is the need for this feature?". Generally, features are added to the core component bloating the core component and adding a new set of code that has to be maintained. Plugins allow us to keep the core feature set and code base very small, but also allow us to provide new opt-in features. This shifts the onus onto the developer to decide with features they want to use, but also understand the performance impact they impart. Ultimately, this is a good thing since we can offer the feature, but the consumer can have full control over the inclusion of that feature into their project.

MUST have a Zend\Db\Adapter component

  • MUST create a distinct abstraction for interfacing with various PHP db drivers
    • MUST support drivers:
      • PDO/mysql
      • PDO/oracle
      • PDO/db2
      • PDO/postgres
      • PDO/sqlite
      • PDO/sqlserver
      • ext/mysqli
      • ext/ibmdb2
      • ext/oci8
      • ext/sqlsrv from MS
      • ext/postgres
    • SHOULD support drivers
      • PDO/firebird
      • ext/mysql
      • ext/sqlite3
  • MUST contain a registry component to allow for storage of named connections
  • MUST support plug-ablity via callbacks (Zend\SignalSlot) at various times during runtime:
    • pre-prepare & pre-execute
    • post-prepare & post-execute
    • pre-connect & post-connect
    • pre-connect-close & post-connect-close
  • MUST NOT contain any SQL
  • MUST be able to report to consumers the capabilities concerning statement execution and ability to prepare statements
  • MUST be able to run non-prepared queries
  • MUST provide an API for quoting various elements
  • MUST provide an API for retrieving server version information
  • SHOULD be able to successfully wrap ANY driver (past, present or future) regardless of its ability to parse and execute parameritized queries

Motivation & Discussion

  • The main motivation between the role of this component and the one below, the Query component, is to separate the the API's responsible for "how" consumers speak to the database (Adapter) and "what" they speak to the database (Query). This solves the current real world problem of modeling an adapter after two drivers that connect to the same vendor platform. For example ext/mysqli and PDOMySQL. Both have separate database interaction APIS, yet they both share the MySQL dialect. This separation will provide us with the appropriate amount of abstract to grow our adapters when new drivers are created in PHP that use the same SQL dialects.
  • There are some queries that current drivers simply cannot prepare; they must just be executed. That said, each adapter must be able to run prepared and straight queries and return a resultset for each. Being able to run non-prepared statements is a feature request that comes with many votes that has yet to be implemented in the current Zend_Db_Adapter implementation.
  • See main goals for notes on plugability.
  • The registry is an important sub-component of Zend\Db\Adapter since it allows you to store a collection of adapters & connections. IN some situations, it makes a lot of sense to have multiple connections open so that you can create a strategy around how to use them. For example, one might be able to create two connections to different database, and name them "read" and "writer". This then allows them to create a strategy in their appliction as to which one to use when talking to the data store.

MUST have a Zend\Db\Query component

  • MUST create a distinct abstraction layer for creating DML (Data Manipulation Language) for:
    • MUST support SELECT
    • MUST support INSERT
    • MUST support UPDATE
    • MUST support DELETE
  • MUST create a distinct abstraction layer for creating DDL (Data Definition Language) for:
    • MUST support CREATE
    • MUST support ALTER
    • MUST support DROP
    • MUST support TRUNCATE
    • SHOULD support RENAME
    • SHOULD support COMMENT
  • MUST support a distinct abstraction layer for creating TCL (Transaction Control Language) for:
    • MUST support COMMIT
    • MUST support ROLLBACK
    • SHOULD support SAVEPOINT
  • MUST support Vendor specific variances when generating SQL
  • SHOULD support Vendor specific features for query generation via Vendor object API
  • MUST support the following Vendor specific Dialects:
    • MUST support vendor neutral SQL92 dialect
    • MUST support MySQL dialect
    • MUST support Postgres dialect
    • MUST support SQLite dialect
    • MUST support Oracle dialect
    • MUST support SQLServer dialect
    • MUST support DB2 on i5 dialect
    • MUST supoort DB2 (general) dialect
    • SHOULD support Firebird and Informix variant dialect
  • MUST support the ability to serialize queries
  • MUST be able to produce full bound statements (bound in userland) as well as parameritized statements
  • MUST be able to interrogate the Adapter for parameritization capabilities and provide statements capable of being executed

Motivation & Discussion

  • See above in Zend\Db\Adapter for the motivation in Adapter/Query separation.
  • It is important that we are able to create, for as much as possible, a DDL query generation component. This will set the framework such that we can utilize this component during unit testing time (see more notes in the ZendTest\Db section). This also fulfills the long-standing request for a schema management component.

MUST have a Zend\Db\ResultSet component

  • MUST model a database result set in a vendor and driver neutral way
  • SHOULD be capable of modeling rows as arrays or row objects
  • MUST support positional keys as well as column name keys in rows
  • MUST be pluggable at various points in runtime:
    • pre-populate and post-populate
  • MUST be serializable and cacheable
  • SHOULD utilize all facilities of PHP to be able to always get row objects as array
  • SHOULD be capable of creating Row objects from arrays of data

Motivation & Discussion

  • This resultSet component should be capable of modeling the results as they come back from various databases. This allow consumers a flexible and standard way of storing their result sets. By having this component, consumers will be able to apply array operations to their collection. They will also be able to choose the type of the rows inside of the collect: they can be plain old PHP arrays, or they can be a particular object

MUST have a Zend\Db\Metadata component

  • MUST create a component that is capable of interrogating a database for schema information
  • MUST be able to describe schema to consumers in a vendor neutral way
  • MUST contain the various Vendor specific queries (Created by Zend\Db\Query) for interrogating database
  • MUST be cacheable via Zend\Cache
  • MUST be serializable
  • MUST be able to describe the capabilities

Motivation & Discussion

  • The main motivation here is to be able to capture information about the structure of the database and present it in a standardized API for other components and consumers to be able to interrogate. Currently, we do this to some extent in the describeTable() calls of Zend_Db_Adapter. By having this standard API, developers will be able to harness this to be able to create more interesting ORM or simply better Modeling solutions.

MUST have a Zend\Db\TableGateway component

  • MUST implement a component that subscribes to the Table Gateway pattern described in PoEAA
    • API: insert(), update(), delete(), select()
  • MUST accept Zend\Db\Query objects
  • MUST be vendor and driver neutral
  • SHOULD be pluggable at various points in the runtime:
    • pre-insert & post-insert
    • pre-update & post-update
    • pre-delete & post-delete
    • pre-select & post-select
  • MUST return Zend\Db\ResultSet object
  • Currently, we have table like operations located in two places, both the Zend_Db_Adapter as well as the Zend_Db_Table. The benefit of having them in the adapter is that you do not have to subscribe to Zend_Db_Table, which has its performance implications as well as its hard coupling with Zend_Db_Table_Row & Rowset. By creating a more lightweight Table Gateway component, the "table API" can be contained in one place and it will be a more attractive API to adopt for those "table only" operations. Furthermore, the "table API" is out of place currently in Zend_Db_Adapter.

MUST have a Zend\Db\RowGateway component

  • MUST implement a component that subscribes to the Row Gateway pattern described in PoEAA
  • MUST be able to accept Zend\Db\Metadata to understand the database schema in order to process row operations
  • SHOULD be injectable into any Zend\Db\ResultSet such that any row can become a Row Gateway
  • SHOULD be pluggable at various point in the runtime:
    • pre-save & post-save
    • pre-delete & post-delete
    • pre-populate & post-populate

Motivation & Discussion

  • Currently, the Row Gateway is hard coupled to the Zend_Db_Table component. If Row were decoupled from TableGateway, that would mean it can be used in any situation where a developer has retrieved a row from the database.. even in situations where they have issued SQL directly as a statement or to the adapter (prepared or not). This would allow the Zend\Db\ResultSet component to cast any row to a RowGateway object that supports the RowGateway pattern thus giving the developer the opportunity to have row objects delete() and save() themselves to/in persistent storage.
  • Moreover, the RowGateway should also have the ability to be pluggable. This allows developers the maximum amount of flexibility in cases where they would like to use these row objects as the model or the subject of a model, OR the target for a mapper.

MUST have a ZendTest\Db component

  • MUST create a base schema that the majority of unit tests can share
  • MUST have cleanup mechanism so that schema's can return to their original state without having to "rebuild" entities
  • MUST have the capability to dynamically create schema when base schema does not model a particular problem
  • SHOULD create better facilities for mock adapters to be used by components that are driver and dialect agnostic

Motivation & Discussion

  • Currently, on some systems, it takes upwards of 4 hours to run the full test suite. Other systems might be quicker, but slowness is a noticeable quality across all major databases. This is primarily due to the fact that DDL operations, specifically creating and dropping schemas is extremely expensive. That said, it is important that we have a base schema that most unit tests can share, and a schema we can get back to a "clean" state. Furthermore, for tests that the base schema does not satisfy, there will be operations they can use to create a temporary schema that will be destroyed during cleanup of that particular test.
  • By creating a query and adatper abstraction layer that is well tested, and by creating components that are both driver/adapter neutral and vendor query neutral, we can avoid having to create mutliple tests for each flavor of database we intend to test on. For example, currently Zend_Db_Table has an implementation of all its tests for each database platform that Zend_Db supports. This in and of itself creates a maintenance nightmare as for each new unit test that is created, it actually creates n tests where n is the number of currently supported platforms. In most cases, developers do not have the means to be able to test some platforms, thus they can never be sure if their solution is completely safe across all platoforms. Since we are creating Zend\Db\TableGateway and Zend\Db\RowGateway with standard API's that are vendor neutral, this will get rid of the need for developers to have to test against various plaforms in their consuming components (like Zend\Paginator).

MUST have a Zend\Db\Plugin\Profiler component plugin

  • MUST create a plugin that is capable of providing introspection into the "running" of a query
  • MUST be able to determine how long a query took to run
  • MUST be able to demonstrate the full state of the query: query and bound parameters if necessary

Motivation & Discussion

  • We currently have a profiler which is very good. There are a few BC issues with the current one with regards to returning bound parameters that we will attempt to fix in this plugin.
  • Since this is a plugin, it will be opt in in a way that does not bloat code.

SHOULD have a Zend\Db\Plugin\TypeCaster component plugin

  • MUST create a plugin that is capable of casting the values of a row result from the database type (represented as a string in PHP) to a PHP type
  • MUST be able to have an internal pre-defined casting rules
  • SHOULD be vendor datatype aware for most common types
  • MUST be able to accept a user definition for casting

Motivation & Discussion

  • This is a highly requested feature in Zend_Db but due to BC, it is very hard to implement. Moreover, this kind of solution can be considered very heavy in terms of CPU and performance costs, so making it a plugin allows developers to opt-in to this feature why the need these capabilities in their application.

COULD have a Zend\Db\ActiveRecord component

  • COULD create a component that subscribes and implements the ActiveRecord pattern as described in PoEAA

Motivation & Discussion

  • Not a requirement, but now that we have late static binding, and separate API's for table operations and row operations, it would be trivial to wrap those components into a class that could satisfy the ActiveRecord pattern. This would allow developers a one-stop-shop when it comes to the quick solution to their table and row needs in one class.
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.