Git Product home page Git Product logo

orm's Introduction

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.

orm's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

orm's Issues

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.

Call to a member function clearContain() on null

Hello, i want override contain with second parameter on "true" on my query, but CakePHP return fatal error : Call to a member function clearContain() on null

Here my query :

$feeds = $this->Feeds->find()
                ->contain([
                    'Users.Profiles.Avatars',
                    'Questions.Categories',
                    'Statuses',
                    'Cities',
                        ], true)
                ->where(['Users.username' => $this->request->data['username']])
                ->order(['Feeds.created' => 'DESC']);

I tested with some query and CakePHP return same error. What is the problem ?

Thank you !

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

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)?

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

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

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?

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.

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?

Breaking change cakephp/database 4.4 vs 4.5

Hey,

I noticed a breaking change in the upgrade of cakephp/database. Composer audit notified me of a CVE in the lib. I updated the package which gave me the 4.5.4 one in my composer.lock.

This results in my app giving exceptions on missing WRITE_ALL constants. This indicates for me that there is a breaking change since this bump is a minor.

After update cakephp/orm to 4.5.4 as well the issue is resolved. This indicates for me that the constraints are not really ok here since it is an independent package.

I understand that you cant revert stuff and cant do anything about it. But i think it is good to raise this to let you know.

Best
Pim

[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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.