[READ-ONLY] A flexible, lightweight and powerful Object-Relational Mapper for PHP, implemented using the DataMapper pattern. This repo is a split of the main code that can be found in https://github.com/cakephp/cakephp

Related tags

Database orm
Overview

Total Downloads License

CakePHP ORM

The CakePHP ORM provides a powerful and flexible way to work with relational databases. Using a datamapper pattern the ORM allows you to manipulate data as entities allowing you to create expressive domain layers in your applications.

Database engines supported

The CakePHP ORM is compatible with:

  • MySQL 5.1+
  • Postgres 8+
  • SQLite3
  • SQLServer 2008+
  • Oracle (through a community plugin)

Connecting to the Database

The first thing you need to do when using this library is register a connection object. Before performing any operations with the connection, you need to specify a driver to use:

use Cake\Datasource\ConnectionManager;

ConnectionManager::setConfig('default', [
	'className' => \Cake\Database\Connection::class,
	'driver' => \Cake\Database\Driver\Mysql::class,
	'database' => 'test',
	'username' => 'root',
	'password' => 'secret',
	'cacheMetadata' => true,
	'quoteIdentifiers' => false,
]);

Once a 'default' connection is registered, it will be used by all the Table mappers if no explicit connection is defined.

Using Table Locator

In order to access table instances you need to use a Table Locator.

use Cake\ORM\Locator\TableLocator;

$locator = new TableLocator();
$articles = $locator->get('Articles');

You can also use a trait for easy access to the locator instance:

use Cake\ORM\Locator\LocatorAwareTrait;

$articles = $this->getTableLocator()->get('Articles');

By default, classes using LocatorAwareTrait will share a global locator instance. You can inject your own locator instance into the object:

use Cake\ORM\Locator\TableLocator;
use Cake\ORM\Locator\LocatorAwareTrait;

$locator = new TableLocator();
$this->setTableLocator($locator);

$articles = $this->getTableLocator()->get('Articles');

Creating Associations

In your table classes you can define the relations between your tables. CakePHP's ORM supports 4 association types out of the box:

  • belongsTo - E.g. Many articles belong to a user.
  • hasOne - E.g. A user has one profile.
  • hasMany - E.g. A user has many articles.
  • belongsToMany - E.g. An article belongsToMany tags.

You define associations in your table's initialize() method. See the documentation for complete examples.

Reading Data

Once you've defined some table classes you can read existing data in your tables:

use Cake\ORM\Locator\LocatorAwareTrait;

$articles = $this->getTableLocator()->get('Articles');
foreach ($articles->find() as $article) {
	echo $article->title;
}

You can use the query builder to create complex queries, and a variety of methods to access your data.

Saving Data

Table objects provide ways to convert request data into entities, and then persist those entities to the database:

use Cake\ORM\Locator\LocatorAwareTrait;

$data = [
	'title' => 'My first article',
	'body' => 'It is a great article',
	'user_id' => 1,
	'tags' => [
		'_ids' => [1, 2, 3]
	],
	'comments' => [
		['comment' => 'Good job'],
		['comment' => 'Awesome work'],
	]
];

$articles = $this->getTableLocator()->get('Articles');
$article = $articles->newEntity($data, [
	'associated' => ['Tags', 'Comments']
]);
$articles->save($article, [
	'associated' => ['Tags', 'Comments']
])

The above shows how you can easily marshal and save an entity and its associations in a simple & powerful way. Consult the ORM documentation for more in-depth examples.

Deleting Data

Once you have a reference to an entity, you can use it to delete data:

$articles = $this->getTableLocator()->get('Articles');
$article = $articles->get(2);
$articles->delete($article);

Meta Data Cache

It is recommended to enable metadata cache for production systems to avoid performance issues. For e.g. file system strategy your bootstrap file could look like this:

use Cake\Cache\Engine\FileEngine;

$cacheConfig = [
   'className' => FileEngine::class,
   'duration' => '+1 year',
   'serialize' => true,
   'prefix'    => 'orm_',
];
Cache::setConfig('_cake_model_', $cacheConfig);

Cache configs are optional, so you must require cachephp/cache to add one.

Creating Custom Table and Entity Classes

By default, the Cake ORM uses the \Cake\ORM\Table and \Cake\ORM\Entity classes to interact with the database. While using the default classes makes sense for quick scripts and small applications, you will often want to use your own classes for adding your custom logic.

When using the ORM as a standalone package, you are free to choose where to store these classes. For example, you could use the Data folder for this:

<?php
// in src/Data/Table/ArticlesTable.php
namespace Acme\Data\Table;

use Acme\Data\Entity\Article;
use Acme\Data\Table\UsersTable;
use Cake\ORM\Table;

class ArticlesTable extends Table
{
    public function initialize()
    {
        $this->setEntityClass(Article::class);
        $this->belongsTo('Users', ['className' => UsersTable::class]);
    }
}

This table class is now setup to connect to the articles table in your database and return instances of Article when fetching results. In order to get an instance of this class, as shown before, you can use the TableLocator:

<?php
use Acme\Data\Table\ArticlesTable;
use Cake\ORM\Locator\TableLocator;

$locator = new TableLocator();
$articles = $locator->get('Articles', ['className' => ArticlesTable::class]);

Using Conventions-Based Loading

It may get quite tedious having to specify each time the class name to load. So the Cake ORM can do most of the work for you if you give it some configuration.

The convention is to have all ORM related classes inside the src/Model folder, that is the Model sub-namespace for your app. So you will usually have the src/Model/Table and src/Model/Entity folders in your project. But first, we need to inform Cake of the namespace your application lives in:

<?php
use Cake\Core\Configure;

Configure::write('App.namespace', 'Acme');

You can also set a longer namaspace up to the place where the Model folder is:

<?php
use Cake\Core\Configure;

Configure::write('App.namespace', 'My\Log\SubNamespace');

Additional Documentation

Consult the CakePHP ORM documentation for more in-depth documentation.

Comments
  • Are there any way to retrieve several type of entities from one table object?

    Are there any way to retrieve several type of entities from one table object?

    My situation

    I have been developing a kind of RPG game. I am hanging up about modeling and database design for items with CakePHP3 ORM.

    Modeling

    • Healing items
    • Key items
    • Leveling items
    • Ticket items

    In the game, there are some kind of items. These can be an Item entity. but I think it is better to split 4 type of entities like above. Each entity will have few different methods.

    Database design

    All items store in an items table. Healing items and Leveling items have effect column which how much healing or leveling up when it is used. Key items and Ticket items is the same as Healing item except effect column. I have no reason to create tables for each entities.

    What I did

    class ItemsTable extends Table
    
    class HealingItemsTable extends ItemsTable{
        const TYPE = 1;
    
        public function beforeFind(Event $event, Query $query, \ArrayObject $option, $primary){
            $query->where(['type' => self::TYPE]);
            return $query;
        }
    }
    
    • Create ItemsTable class.
    • Create 4 Table class inherit ItemsTable like HealingItemsTable.
    class HealingItem extends Item{
        public function someMedhotForHealingItem(){}
    }
    

    Same as Table class for entity classes.

    This seams working good. But I want to find better way.

    Question

    Q1

        public function beforeFind(Event $event, Query $query, \ArrayObject $option, $primary){
            parent::beforeFind($event, $query, $option, $primay); // Got error!
            $query->where(['type' => self::TYPE]);
            return $query;
        }
    

    I got an error becase of no beforeFind method on ItemsTable class. Is it not excpected that the Table class is to be super class?

    Q2

    I want to retrieve 4 type of item entities from one ItemsTable. ItemsTable returns a collection that contains several subclass of Item entity. Some entites own original methods, but almost same interface as oop polymorphism. It this possible with CakePHP3 ORM?

    question 
    opened by kanonji 14
  • Documentation part missing

    Documentation part missing

    Dear all,

    the part where to put the Model / Table / Entities files is missing and how to put it in the autoloading. It is not self explanatory if you are new to CakePHP-ORM and especially not if you don't have any background knowledge of CakePHP.

    In this regards I opened an question on Stackoverflow which was correctly answered by the user ndm. StackOverflow question

    It would be nice if you can add this to the documentation :) .

    Kind regards, Marius

    opened by nekkid 8
  • Aliases X propertyName problems

    Aliases X propertyName problems

    Hi, I guess that Cake isn't preserving table alias when creating some associations like in the case below.

    I have the following Table objects

    PessoasTable

    class PessoasTable extends AppTable
    {
        public function initialize(array $config)
        {
            parent::initialize($config);
    
            $this->setAlias('Pessoa');
            $this->setEntityClass('Pessoa');
            $this->setTable('pessoas');
            $this->setPrimaryKey('id');
            $this->setDisplayField('ds_nome');
    
            $this->addAssociations([
                'hasOne' => [
                    'Usuarios' => [
                        'className' => 'Usuarios',
                        'propertyName' => 'Usuario',
                        'foreignKey' => 'id',
                        'joinType' => 'LEFT',
                        'dependent' => true,
                    ],
                    'Pessoafisicas' => [
                        'className' => 'Pessoafisicas',
                        'propertyName' => 'Pessoafisica',
                        'foreignKey' => 'id',
                        'joinType' => 'LEFT',
                        'dependent' => true,
                    ],
                    ...
    

    UsuariosTable

    class UsuariosTable extends AppTable
    {
        public function initialize(array $config)
        {
            parent::initialize($config);
    
            $this->setAlias('Usuario');
            $this->setEntityClass('Usuario');
            $this->setTable('usuarios');
            $this->setPrimaryKey('id');
            $this->setDisplayField('ds_login');
    
            $this->addAssociations([
                'belongsTo' => [
                    'Pessoas' => [
                        'className' => 'Pessoas',
                        'propertyName' => 'Pessoa',
                        'foreignKey' => 'id',
                        'joinType' => 'INNER',
                    ]
                ],
            ]);
        }
    ...

    PessoafisicasTable

    class PessoafisicasTable extends AppTable
    {
        public function initialize(array $config)
        {
            parent::initialize($config);
    
            $this->setAlias('Pessoafisica');
            $this->setEntityClass('Pessoafisica');
            $this->setTable('pessoafisicas');
            $this->setDisplayField('nr_cpf');
            $this->setPrimaryKey('id');
    
            $this->addAssociations([
                'belongsTo' => [
                    'Pessoas' => [
                        'className' => 'Pessoas',
                        'propertyName' => 'Pessoa',
                        'foreignKey' => 'id',
                        'joinType' => 'INNER',
                    ],
                ]
            ]);
        }
        ...
    

    In UsuariosController the following find is producing the SQL query bellow

    $usuario = $this->Usuarios->get($id, [
                'fields' => ['id', 'ds_login'],
                'contain' => [
                    'Pessoas' => [
                        'fields' => ['id', 'ds_nome'],
                        'Pessoafisicas'
                    ],
                ]);
    

    SQL output

    SELECT 
      Usuario.id AS `Usuario__id`, 
      Usuario.ds_login AS `Usuario__ds_login`, 
      Pessoas.id AS `Pessoas__id`, 
      Pessoas.ds_nome AS `Pessoas__ds_nome` 
    FROM 
      usuarios Usuario 
      INNER JOIN pessoas Pessoas ON Pessoas.id = (Usuario.id) 
      LEFT JOIN pessoafisicas Pessoafisicas ON Pessoa.id = (Pessoafisicas.id) 
    WHERE 
      Usuario.id = 4 
    LIMIT 
      1
    

    Error Note that CakePHP isn't respecting my table Alias name in Pessoas and neither in Pessoafisicas but in ON condition thru Pessoa and Pessoafisica it is.

    opened by gildonei 8
  • Change i18n package dependency from suggest to require

    Change i18n package dependency from suggest to require

    Hi,

    first of all I'm sorry if this is the wrong repo to file a bug report because of the read-only mark.

    Nevertheless: After I installed cakephp\orm package and setup a mysql connection I experienced missing dependency error for Cake\i18n\Date class.

    The documentation at http://book.cakephp.org/3.0/en/orm/database-basics.html#configuration states that Cake\i18n\Date will be used as a return value for columns of the type "DATE".

    Have I overlooked something or is Cake\i18n really a critical dependency and should be moved to the require block in composer.json (Because if I think I some use an ORM-Package it should handle Date-Operations out of the box)?

    opened by devkev16 5
  • Can I use this ORM with Cake 2.x?

    Can I use this ORM with Cake 2.x?

    I have a huge Cakephp project with almost 200 tables using cake 2.x. I want to do gradual upgrade to cake 3.x, so i want that some models use cake 3 ORM while others still use cake2.x models.

    Is it possible to work like this? if so, is there any tutorial on how to do this?

    Thanks in advance

    question 
    opened by backstageel 5
  • Created the method getAssociationsName() in AssociationCollection class

    Created the method getAssociationsName() in AssociationCollection class

    I created a small function to get the association _name property of all the associations. I needed this to customize the plugin friendsofcake/crud to contain others models on View action.

    opened by keomaborges 2
  • README incorrect info

    README incorrect info

    Hi,

    As pointed out in this topic : http://discourse.cakephp.org/t/orm-cache-metadata-issue/1071/4 there is a problem with the default Configuration in the README.

    The parameter 'cacheMetaData' should be 'cacheMetadata'.

    I don't know if packagist.org pulls the README from Github, but if not, you may want to change it also there because that's where I used it :-)

    Thank you,

    kinkaz

    opened by kinkaz 2
  • MS SQL Server Schemas

    MS SQL Server Schemas

    CakePHP only seems to see tables from my default dbo schema on SQL Server 2012 database. When I try to bake the model for tables from other schemas I get an error saying:

    Exception: Cannot describe content. It has 0 columns.

    Also when I fetch the list of tables in schema using:

    $collection = $db->schemaCollection(); $tables = $collection->listTables();

    It only lists tables from dbo schema in the array. How do I use other schemas?

    question 
    opened by sdanko 2
  • [Standalone] Unnecessary queries

    [Standalone] Unnecessary queries

    I post this issue here since I'm trying to use CakePHP ORM without Cakephp Core.

    Is there a way to avoid unnecessary queries ? If I try to get 10 rows from a table CakePHP ORM will do 4 queries to get the structure of my table, even if log is turned off.

    Is there a way to prevent this ? If so it would be nice to document it (I tried setting various informations in my Table class but nothing worked so far). Here is the code I tried and the queries that it generates

    ConnectionManager::config('default', [
        .....
        'log' => true
    ]);
    $connection = ConnectionManager::get('default');
    $logger = new QueryLogger();
    $connection->logger($logger);
    
    $tutoriels = new TutorielsTable(['connection' => $connection]);
    $tutoriels->find()->limit(10)->toArray();
    var_dump($logger->getQueries());
    
    Array (size=5)
      0 => 
        array (size=3)
          'query' => string 'SHOW FULL COLUMNS FROM `tutoriels`' (length=34)
          'took' => float 2
          'rows' => int 26
      1 => 
        array (size=3)
          'query' => string 'SHOW INDEXES FROM `tutoriels`' (length=29)
          'took' => float 0
          'rows' => int 5
      2 => 
        array (size=3)
          'query' => string 'SELECT * FROM information_schema.key_column_usage AS kcu
                INNER JOIN information_schema.referential_constraints AS rc
                ON (kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME)
                WHERE kcu.TABLE_SCHEMA = 'my_table' AND kcu.TABLE_NAME = 'tutoriels' and rc.TABLE_NAME = 'tutoriels'' (length=301)
          'took' => float 0
          'rows' => int 0
      3 => 
        array (size=3)
          'query' => string 'SHOW TABLE STATUS WHERE Name = 'tutoriels'' (length=42)
          'took' => float 0
          'rows' => int 1
      4 => 
        array (size=3)
          'query' => string 'SELECT Tutoriels.id AS `Tutoriels__id`, Tutoriels.name AS `Tutoriels__name`, Tutoriels.content AS `Tutoriels__content`, Tutoriels.content_markdown AS `Tutoriels__content_markdown`, Tutoriels.tp AS `Tutoriels__tp`, Tutoriels.duration AS `Tutoriels__duration`, Tutoriels.vimeo AS `Tutoriels__vimeo`, Tutoriels.daily AS `Tutoriels__daily`, Tutoriels.youtube AS `Tutoriels__youtube`, Tutoriels.blip AS `Tutoriels__blip`, Tutoriels.video AS `Tutoriels__video`, Tutoriels.video_size AS `Tutoriels__video_size`, Tutoriels.source AS `Tutoriels__source`, Tutoriels.demo AS `Tutoriels__demo`, Tutoriels.slug AS `Tutoriels__slug`, Tutoriels.category_id AS `Tutoriels__category_id`, Tutoriels.created AS `Tutoriels__created`, Tutoriels.comment_count AS `Tutoriels__comment_count`, Tutoriels.online AS `Tutoriels__online`, Tutoriels.premium AS `Tutoriels__premium`, Tutoriels.relative AS `Tutoriels__relative`, Tutoriels.serie AS `Tutoriels__serie`, Tutoriels.user_id AS `Tutoriels__user_id`, Tutoriels.lvl AS `Tutoriels__lvl`, Tutoriels.formation_id AS `Tutoriels__formation_id`, Tutoriels.color AS `Tutoriels__color` FROM tutoriels Tutoriels LIMIT 10' (length=1139)
          'took' => float 0
          'rows' => int 10
    
    opened by Grafikart 2
  • Cake\I18n\Time is used in TimestampBehavior.php but does not exist in cakephp/orm

    Cake\I18n\Time is used in TimestampBehavior.php but does not exist in cakephp/orm

    opened by elovin 1
  • Composer.json dependencies need to be updated

    Composer.json dependencies need to be updated

    The current version of cakephp/orm has it's dependencies set to

        "require": {
            "cakephp/collection": "~3.0",
            "cakephp/core": "~3.0",
            "cakephp/datasource": "~3.0",
            "cakephp/database": "~3.0",
            "cakephp/event": "~3.0",
            "cakephp/utility": "~3.0",
            "cakephp/validation": "~3.0"
        }
    

    But this isn't right. When I updates from 3.1.1 to 3.2.7, with the command composer update cakephp/orm, I found myself getting errors from cakephp/datasource and cakephp/database.

    cakephp/orm/Query implements cakephp/datasource/QueryInterface, which doesn't exist in cakephp/datasource 3.1.1, and somewhere (I didn't catch the error) cakephp/orm also relies on cakephp/database/Schema/Table::typeMap() which doesn't exist until cakephp/database 3.1.4.

    However, since the composer.json only requires all packages at ~3.0, they didn't get updated with cakephp/orm, causing errors on update. Updating the version dependencies to match what the package actually depends on would fix this issue. The world around I used was to do a composer remove cakephp/orm and then do a composer require cakephp/orm

    opened by Garethp 1
  • CakePHP ORM pulls incompatible dependencies

    CakePHP ORM pulls incompatible dependencies

    Steps Install cakephp/orm 3.0 via composer on PHP 5.6.

    Expected All installed dependencies compatible with that orm version.

    Actual Installed dependency cakephp/event 3.10 throws a deprecation.

    Temporary workaround Manually set version of dependencies (cakephp/event, cakephp/validation) to 3.0.

    opened by afilina 0
Owner
CakePHP
CakePHP
Doctrine Object Relational Mapper (ORM)

3.0.x 2.9.x 2.8.x Doctrine 2 is an object-relational mapper (ORM) for PHP 7.1+ that provides transparent persistence for PHP objects. It sits on top o

Doctrine 9.5k Jan 2, 2023
Convention-based Object-Relational Mapper

Corma Corma is a high-performance, convention-based ORM based on Doctrine DBAL. Corma is great because: No complex and difficult to verify annotations

Michael O'Connell 30 Dec 20, 2022
[READ ONLY] Subtree split of the Illuminate Database component (see laravel/framework)

Illuminate Database The Illuminate Database component is a full database toolkit for PHP, providing an expressive query builder, ActiveRecord style OR

The Laravel Components 2.5k Dec 27, 2022
Articulate - An alternative ORM for Laravel, making use of the data mapper pattern

Articulate Laravel: 8.* PHP: 8.* License: MIT Author: Ollie Read Author Homepage: https://ollie.codes Articulate is an alternative ORM for Laravel bas

Ollie Codes 4 Jan 4, 2022
Propel2 is an open-source high-performance Object-Relational Mapping (ORM) for modern PHP

Propel2 Propel2 is an open-source Object-Relational Mapping (ORM) for PHP. Requirements Propel uses the following Symfony Components: Config Console F

Propel 1.2k Dec 27, 2022
PHP DataMapper, ORM

Cycle ORM Cycle is PHP DataMapper, ORM and Data Modelling engine designed to safely work in classic and daemonized PHP applications (like RoadRunner).

Cycle ORM 1.1k Jan 8, 2023
Spot v2.x DataMapper built on top of Doctrine's Database Abstraction Layer

Spot DataMapper ORM v2.0 Spot v2.x is built on the Doctrine DBAL, and targets PHP 5.4+. The aim of Spot is to be a lightweight DataMapper alternative

Spot ORM 602 Dec 27, 2022
A data mapper implementation for your persistence model in PHP.

Atlas.Orm Atlas is a data mapper implementation for persistence models (not domain models). As such, Atlas uses the term "record" to indicate that its

null 427 Dec 30, 2022
Analogue ORM : Data Mapper ORM for Laravel/PHP

(this project is looking for a new maintainer) Analogue ORM Analogue is a flexible, easy-to-use ORM for PHP. It is a transposition of the Eloquent ORM

Analogue ORM 632 Dec 13, 2022
A simple PHP library to transfer data from a source (object or array) to an object.

SimplexMapper A simple PHP library to transfer data from a source (object or array) to an object. $dbData = [ 'username' => 'pfazzi', 'emailAd

Patrick Luca Fazzi 4 Sep 22, 2022
A drop-in library for certain database functionality in Laravel, that allows for extra features that may never make it into the main project.

Eloquence Eloquence is a package to extend Laravel's base Eloquent models and functionality. It provides a number of utilities and classes to work wit

Kirk Bushell 470 Dec 8, 2022
Read and write CSV files with PHP.

Read and write CSV files with PHP. This package provides a minimalistic wrapper around the excellent league/csv package. The API is heavily inspired b

Ryan Chandler 6 Nov 16, 2022
The fastest pure PHP database framework with a powerful static code generator, supports horizontal scale up, designed for PHP7

Maghead 4.0.x IS CURRENTLY UNDER HEAVY DEVELOPMENT, API IS NOT STABLE Maghead is an open-source Object-Relational Mapping (ORM) designed for PHP7. Mag

Maghead 477 Dec 24, 2022
Baum is an implementation of the Nested Set pattern for Laravel's Eloquent ORM.

Baum Baum is an implementation of the Nested Set pattern for Laravel 5's Eloquent ORM. For Laravel 4.2.x compatibility, check the 1.0.x branch branch

Estanislau Trepat 2.2k Jan 3, 2023
Adjacency List’ed Closure Table database design pattern implementation for the Laravel framework.

ClosureTable This is a database manipulation package for the Laravel 5.4+ framework. You may want to use it when you need to store and operate hierarc

Yan Ivanov 441 Dec 11, 2022
PHP Object Model Manager for Postgresql

POMM: The PHP Object Model Manager for Postgresql Note This is the 1,x version of Pomm. This package is not maintained anymore, the stable Pomm 2.0 is

Grégoire HUBERT 161 Oct 17, 2022
A complete, simple and powerful database framework written in PHP

BaseSQL BaseSQL is a complete database framework written in PHP. It was built to accelerate projects development by handle database connections and qu

Willian Pinheiro 2 Sep 21, 2021
The lightweight PHP database framework to accelerate development

The lightweight PHP database framework to accelerate development Features Lightweight - Less than 100 KB, portable with only one file Easy - Extremely

Angel Lai 4.6k Dec 28, 2022
Connect and work with MySQL/MariaDB database through MySQLi in PHP. This is an introductory project, If you need a simple and straightforward example that takes you straight to the point, you can check out these examples.

First MySQLi PHP Connect and work with MySQL/MariaDB database through MySQLi in PHP. The above exercises are designed for students. This is an introdu

Max Base 4 Feb 22, 2022