PHP Data Access Libraries (ORM, ActiveRecord, Persistence)
Le gusta 2
For description on the comparison criteria, please read full
article here:
medium.com/...
Enlace | Doctrine | Agile Data | Eloquent | Yii ORM | Cake ORM | Fuel ORM | Red Bean PHP | Ting | Spiral ORM | .. |
---|---|---|---|---|---|---|---|---|---|---|
Sitio web | doctrine-project.org | git.io/ad | yiiframework.com | redbeanphp.com | ccmbg.com/... | spiral-framework.com/... | ||||
Descripción | Data Access Framework for high-latency databases (Cloud SQL/NoSQL). | RedBeanPHP is an easy to use ORM for PHP. It's a Zero Config ORM lib that 'automagically' builds your database schema. | Simple: no magic inside : it’s basically SQL queries | ORM engine with automatic database scaffolding, strict schemas, code discovery, modular database partitions and various relation loaders. | ||||||
Github / Bitbucket / Sourceforge | github.com/... | git.io/ad | github.com/... | github.com/... | bitbucket.org/... | github.com/... | ||||
License | MIT | MIT | BSD-3 | New BSD / GPL | Apache 2 | MIT | ||||
Latest version | 2.5.5 | 1.2.x | 2.0.10 | 4.3.2 | 3.4.2 | 1.0.8 | ||||
How schema is defined? | PHP, XML, YAML | in PHP. Method init() in Model class defines fields, relations, conditions, etc. | Model class properties | Active record magic properties. | Automatically discovered on the fly. | PHP | PHP Const array. Column class. | |||
Code generation | Sí schema-tool | Sí https://github.com/atk4/schema | Sí Web and console generator https://github.com/yiisoft/yii2-gii | |||||||
Can be used in Any Framework | Sí composer / packagist | Sí Through composer/packagist | Sí Through Capsule | - Planned in 2.1.x | Sí | Sí composer / packagist | ||||
Automated Cache | Sí Frameworks focuses on optimizing queries rather then caching. Still possible with cross-persistence saving. | Sí | Sí | |||||||
Anti-patterns (purposely included) | Model close-coupled with Persistence and Field classes. | Eloquent is a God Class; Global functions; DB Conection is global; | ||||||||
Audience | ||||||||||
Dependencies | Medium: ±5 packages. | Minimal: 2 packages: DSQL Query Builder (git.io/... | Minimal: 3, pimple, doctrine/cache, aura/sqlquery | |||||||
Simplicity | sin puntuaciones | 5.0/5 2 Calificaciones | sin puntuaciones | 5.0/5 2 Calificaciones | 5.0/5 1 Valoración | sin puntuaciones | sin puntuaciones | 5.0/5 1 Valoración | sin puntuaciones | sin puntuaciones |
Enterprise Compliance | 5.0/5 1 Valoración | 5.0/5 2 Calificaciones | 3.0/5 1 Valoración | 4.5/5 2 Calificaciones | 5.0/5 1 Valoración | sin puntuaciones | sin puntuaciones | 5.0/5 1 Valoración | sin puntuaciones | sin puntuaciones |
Minimum PHP Version | 5.4 | 5.6 | 5.4 | 5.5 | ||||||
Basic Features | ||||||||||
PDO Support | Sí Yes | Sí Yes | Sí | Sí | - But made a custom driver to support it is easy | Sí https://spiral-framework.com/guide/database-databases | ||||
Transparent support for NoSQL | - Through 3rd party drivers. | No Eloquent is built on Query Builder. Perhaps moloquent? Also - Through Caching backend, but not as ORM native persistence. | Sí Avialable cross sql and nosql datababase relations (https://github.com/yiisoft/yii2-mongodb) | No Build around plain queries. | No | No No, through ODM (https://spiral-framework.com/guide/odm-databases) | ||||
How to invoke db-vendor-specific extensions? | Sí DBAL | Sí For SQL - save/load/delete operations are expressed in DSQL Queries that can be manipulated: http://git.io/dsql | Sí Through Query Builder / RAW queries. | Sí SQL - Query Builder. | - Can add SQL code chunks. | Sí Ting use native query, you can use everyting of your SGBD | Sí Query models: https://spiral-framework.com/guide/orm-query | |||
Array as a persistence | Sí CRUD operations supported | Sí https://github.com/yii2tech/filedb | No | No | ||||||
RestAPI as a persistence | - Through 3rd party extension. | - To extend BaseActiveRecord | No | No | ||||||
JSON string as a persistence | Sí Supported with few extra lines of code. | - To extend BaseActiveRecord | No | No | ||||||
Same model, multiple persistences | Sí Same class. Different object. | - (no docs) | ||||||||
Basic Single-record operations (C,R,U,D) | ||||||||||
Table Name Mapping | Sí Yes | Sí Yes | Sí Same as model class name by default | Sí Using static method of active record. http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#declaring-ar-classes | No mapping no longer supported. | Sí Yes | ||||
Field Name Mapping | Sí Yes, (Annotations in PHP) | Sí Yes (Field::actual property) | - Through accessors/3rd party extension | Sí | No mapping no longer supported. | Sí Yes | ||||
Map Entity to SubQuery | No Must be physical table | Sí Yes. Extension exist for UNION-models. https://github.com/atk4/report | No Must be physical table. | - table = new Expression(..) | No | No This concept is no-sense for Ting | ||||
Map property to expression | No Must be physical field | Sí $model->addExpression() | No Must be physical table | - (couldn't find docs) | No | No This concept is no-sense for Ting | ||||
Map native types (DateTime) | Sí $field->type = 'date' | Sí Accessors and Mutators | Sí Active record behaviors | Sí | Sí Yes | - No support for DateTime. https://spiral-framework.com/guide/orm-accessors | ||||
User-defined types (e.g. "23 USD") | Sí Type class | Sí Yes. Independent from Model. by extending Field class. | Sí Accessors and Mutators | Sí Active record behaviors | Sí Yes, with custom serializer | |||||
Map field of related Entity ('currency' = currency_id->Model Currency.name) | - Specific record only | Sí Transparently maps into sub-select. | - Relationship, but only single record. | Sí $model->currency->name | No | Sí Yes | ||||
Map field to sub-query on related entity (Client.balance = Client->orders->sum(total)) | No | Sí Yes. hasMany()->addField(..aggregate) | No | - (couldn't find docs) | No | - This concept is no-sense for Ting | ||||
Entity to join multiple tables (adding new record populates both tables) | Sí Associations | Sí $model->join('other_table') | No | No No native support. | No | Sí Yes | ||||
Criteria, Scope, Conditions (Model will refuse to work with records that does not match criteria) | ||||||||||
Support model-level criteria | Sí Yes. Applied on loading / saving / update. | - Global Scope (querying only) | No | No | ||||||
Soft-delete | Sí Extension | Sí Through criteria. Example given in the docs. | Sí Trait and Scope | Sí Events and behaviors | No | |||||
Domain Model Criteria | Sí $m->addCondition('gender','M'); where 'gender' can be arbitrary expression, sub-select, field from association(join) or mapped no another physical field. | - Scopes, but not in domain model. | No Only for specific query: User::find()->byEmail('...')->active()->one() | No | ||||||
Expression-based condition | Sí $m->addCondition($m->expr('..')); | Sí through Query Builder | No Only for query: User::find()->andWhere('...')->all() | No | ||||||
Criteria Compliance (new record must match condition) | Sí Transaction rollback and exception. Automated-rloading. | No | No | |||||||
Dynamic criteria | Sí $user->addCondition('is_expired', false) | No Only Querying: User::find()->where(['a' => '1', 'b' => true])->all(); | No | |||||||
Query Building (Convert Model into Query object for further SQL tweaking) | ||||||||||
Convert Model into Query Object | Sí $q = $model->action('select'); | Sí Model is a Query object. See: Model::where() | Sí \yii\db\ActiveRecord::find() | No | Sí RecordSelector | |||||
Raw expression | Sí new Expression('any sql') | Sí DB::raw() | Sí new \yii\db\Expression('...') | Sí | Sí | |||||
Nested/Composite Queries/Expressions | Sí Expression can be in any part of query | No | Sí Expression can be in any part of query | No | ||||||
Reference domain-model field in query | Sí through Expressionable interface | No No fields. Only properties. | No Field is class property. | No | No | |||||
field, where, order, limit | Sí Expressions and Parametric values | Sí | Sí \yii\db\ActiveQuery | No | Sí | |||||
options, rollup, partition | - Through custom templates, or expressions. | - not sure. | ||||||||
UPDATE, DELETE, INSERT query building | Sí | Sí | No | Sí | ||||||
REPLACE, TRUNCATE | Sí | - Throught raw sql in \yii\db\Command | - wipe(), | |||||||
SHOW, DESCRIBE, CALL | - Supported through Expressions or Custom query template | - Throught raw sql in \yii\db\Command | - Automatic schema alter / discovery. | |||||||
ALTER, CREATE query building | Sí Addon: http://github.com/atk4/schema | Sí | No | |||||||
User-defined query template | Sí Templates for all queries | Sí (please link doc) | No | |||||||
full support for OR conditions | Sí Through Object Composition and Expressions | - Partial | - | No only raw query | ||||||
Use Domain logic in multi-record update | - Supported, but must map fields/values manually. | No | No | No | ||||||
Data Fetching (different ways to retrieve data from database) | ||||||||||
Get All Data (2x array) | Sí | Sí | Sí \yii\db\Query::all() | Sí exportAll() | Sí | |||||
Associative Array (id=>value) | No Planned | Sí lists() | ||||||||
Select only required fields | Sí | |||||||||
Typecasting (e.g. DateTime) | Sí | Sí | ||||||||
Import (multiple records) | Sí | Sí | ||||||||
Respect domain model mapping (and criteria) | Sí | |||||||||
Single row | Sí loadAny | Sí | Sí \yii\db\Query::one() | Sí | ||||||
Single Value | Sí Through action | Sí | Sí \yii\db\Query::scalar() | Sí | ||||||
Single Column | - may need to map resulting array | Sí | Sí \yii\db\Query::column() | Sí | Sí | |||||
Iterator | Sí | Sí | Sí | |||||||
Bypass persistence mapping | Sí action('select')->getAll() | Sí ?? (e..g prevent date from being transformed into Carbon) | ||||||||
Loading and Saving individual records | ||||||||||
Load by ID | Sí load(id) | Sí User::findOne(1) | Sí | Sí get(id) | Sí findByPK | |||||
Load by other field | Sí loadBy('field', $value) | Sí User::findOne(['id' => 1]) | No | Sí getBy(['propertyName' => 'value']); | ||||||
Read-only Models | Sí Yes | No | ||||||||
Model without primary key | Sí Yes, but only in Read-only Mode | No | Sí | |||||||
Specify fields to load | Sí onlyFields() | No Fields load with SELECT * | Sí User::find()->select([])->one() | No | Sí | |||||
Save only sends dirty fields | Sí | Sí | Sí | - (there is Dirty support, so I assuming it is supported) | Sí | Sí | ||||
Guarded / Fillable properties | Sí Conditions and OnlyFields do same thing but more reliably. | Sí Prevents "create($_GET)" from messing up important fields. | ||||||||
Object Hierarchy Model | ||||||||||
Admin extends User, adds criteria (is_admin=1) | Sí Yes, recommended pattern. "User" class adds condition. | No | No Can be done as wrapper: User::findAdmin(..) or custom CDbCriteria | No | ||||||
Admin extends User, adds accessible fields | Sí Yes, recommended pattern. | No | No | No | ||||||
Extend model, add Join (Disjoined SubTypes) | Sí Yes. Unlimited number of joins. | No | No | No | ||||||
Extend model change table | Sí Yes. Used to tweak 3rd party models. | No | ||||||||
Relations/References (One model can relate to another model. NOT A TABLE JOIN) | ||||||||||
Model can define relation to other Model | Sí References are implemented as Objects | Sí Relations | Sí Relations | Sí | ||||||
One-to-Many | Sí $user->hasMany('Orders', new Order()); | Sí | Sí | |||||||
One-to-many traversal strategy | Returns destination model instance with dynamically applied criteria (parent_id=123). No queries are executed. Inserting record into this model will ensure association with parent model. | Returns array of objects that may either be pre-loaded with record data or only contain IDs (lazy-loaded). | Uses classical eager/lazy loading approach. with() can help pre-fetch the data for related entities. | pre-fetch and store objects in an array. | ||||||
Lazy/Eager-loading | No Anti-pattern | Sí | Sí | Sí | ||||||
One-to-One | Sí $order->hasOne('user_id', new User()); | Sí | Sí | |||||||
Many-to-Many | Sí $user->addCondition('vip', true)->ref('Orders'); | Sí relations() method of an entity can define. | ||||||||
Deep Many-to-Many traversal. | No | Sí $user->ref('Orders')->ref('Payments')->action('count'); No intermediate queries. | - only with "to-one" references: $book->author->address->street; Executes multiple queries. | - only with to-one references. Executes multiple queries. | ||||||
Cross-Persistence traversal | Sí $user->hasMany('Log', new Log($mongodb)); | - No docs. | No | |||||||
Cross-persistence joins, aggregation, reporting | ||||||||||
Multi-persistence join | No | No | No | No | ||||||
UNION existing models | No | Sí Yes, in add-on https://github.com/atk4/report/. Can join UNION result with more tables. | No | No | ||||||
Domain-model Aggregation | Sí Group by multiple fields. Apply aggregation functions. Preserve types. | No | ||||||||
Model to Model join | No Planned. | No | ||||||||
Multi-persistence UNION | No | No | No | No | ||||||
Behaviours / Hooks | ||||||||||
Before/After operation | Sí | Sí | ||||||||
Override standard C,R,U,D operations | Sí | Sí | ||||||||
Persistence-specific hooks (to modify Query) | Sí | - (no docs) | ||||||||
User-defined hooks | Sí | Sí | ||||||||
Auditing | ||||||||||
Global Auditing | Sí http://www.agiletoolkit.org/data/extensions/audit | No | ||||||||
Store old/new field values | Sí Yes in JSON and user-readable string. | Sí | ||||||||
Revert action (undo) and replay (redo) | Sí | No | No | |||||||
Reactive actions | Sí Each action will be automatically linked with sub-actions which may be invoked through Hooks. | |||||||||
Store log in any persistence | Sí | No | ||||||||
Override, Add fields to audit log | Record dirty fields before persisting. Type-cast into JSON string and store in a single field of AuditLog Model. This model can be persisted anywhere, table, file, etc. | |||||||||
Custom events | Sí | Sí | ||||||||
Access to record-specific history | Sí $item->ref('AuditLog'); | - Through a custom query. | ||||||||
Date of creation, modification | - No but easy to add through hook. | Sí \yii\behaviors\TimestampBehavior | Sí TimestampTrait | |||||||
User/IP creation, modification | - Easy to add through a hook. | Sí \yii\behaviors\BlameableBehavior | ||||||||
Store incremental revisions | - Easy to add through a hook | Sí | ||||||||
Integration | ||||||||||
Field meta-information provided | Type, caption, possible values, mapped field, join table spec, encryption, serialization, UI-specific settings, validation rules. | |||||||||
UI extensions | No | Sí CRUD, Form, Table, Grid, Entity-manager. (see https://github.com/atk4/ad) | No | No | No | |||||
API extensions | Sí RestFULL API, automated CRUD operations + RPC https://github.com/atk4/api | |||||||||
Me gusta | Le gusta 0 | Le gusta 3 | Le gusta 0 | Le gusta 1 | Le gusta 1 | Le gusta 0 | Le gusta 0 | Le gusta 0 | Le gusta 0 | Le gusta 0 |
User reviews and comments
Probably the easiest at using without up front configuration
Easiest ORM, I think!
Using in Recent modules of our ERP
Most simple among what I used (almost all popular ones)