A lightweight nearly-zero-configuration object-relational mapper and fluent query builder for PHP5.

Related tags

Database idiorm
Overview

Idiorm

Build Status Latest Stable Version Total Downloads Code Climate

http://j4mie.github.com/idiormandparis/


Feature/API complete

Idiorm is now considered to be feature complete as of version 1.5.0. Whilst it will continue to be maintained with bug fixes there will be no further new features added from this point on. This means that if a pull request makes breaking changes to the API or requires anything other than a patch version bump of the library then it will not be merged.

Please do not submit feature requests or API breaking changes as they will be closed without ceremony.


A lightweight nearly-zero-configuration object-relational mapper and fluent query builder for PHP5 and above.

Tested on PHP 5.2.0+ - may work on earlier versions with PDO and the correct database drivers.

Released under a BSD license.

See Also: Paris, an Active Record implementation built on top of Idiorm.

Features

  • Makes simple queries and simple CRUD operations completely painless.
  • Gets out of the way when more complex SQL is required.
  • Built on top of PDO.
  • Uses prepared statements throughout to protect against SQL injection attacks.
  • Requires no model classes, no XML configuration and no code generation: works out of the box, given only a connection string.
  • Consists of one main class called ORM. Additional classes are prefixed with Idiorm. Minimal global namespace pollution.
  • Database agnostic. Currently supports SQLite, MySQL, Firebird and PostgreSQL. May support others, please give it a try!
  • Supports collections of models with method chaining to filter or apply actions to multiple results at once.
  • Multiple connections supported
  • PSR-1 compliant methods (any method can be called in camelCase instead of underscores eg. find_many() becomes findMany()) - you'll need PHP 5.3+

Documentation

The documentation is hosted on Read the Docs: idiorm.rtfd.org

Building the Docs

You will need to install Sphinx and then in the docs folder run:

make html

The documentation will now be in docs/_build/html/index.html

Let's See Some Code

$user = ORM::for_table('user')
    ->where_equal('username', 'j4mie')
    ->find_one();

$user->first_name = 'Jamie';
$user->save();

$tweets = ORM::for_table('tweet')
    ->select('tweet.*')
    ->join('user', array(
        'user.id', '=', 'tweet.user_id'
    ))
    ->where_equal('user.username', 'j4mie')
    ->find_many();

foreach ($tweets as $tweet) {
    echo $tweet->text;
}

Tests

Tests are written with PHPUnit and be run through composer

composer test

To make testing on PHP 5.2 (Idiorm maintains support back to this version of PHP) there is a Docker setup in ./test/docker_for_php52 - check the readme in there for more.

Changelog

1.5.7 - released 2020-04-29

1.5.6 - released 2018-05-31

  • Assign null to self::$_db on reset_db() to ensure PDO closes the connections [bleakgadfly] - issue #338

1.5.5 - released 2018-01-05

  • Add a docker setup for testing with PHP 5.2 (uses PHPUnit 3.6.12, which is the last version released compatible with PHP 5.2) [Treffynnon]

1.5.4 - released 2018-01-04

1.5.3 - released 2017-03-21

  • Document the raw_execute() method and add a note for get_db() in the querying documentation - [Treffynnon]

1.5.2 - released 2016-12-14

1.5.1 - released 2014-06-23

1.5.0 - released 2014-06-22

1.4.1 - released 2013-12-12

Patch update to remove a broken pull request - may have consequences for users of 1.4.0 that exploited the "find_many() now returns an associative array with the databases primary ID as the array keys" change that was merged in 1.4.0.

  • Back out pull request/issue #133 as it breaks backwards compatibility in previously unexpected ways (see #162, #156 and #133) - sorry for merging this change into Idiorm - closes issue 156

1.4.0 - released 2013-09-05

1.3.0 - released 2013-01-31

  • Documentation moved to idiorm.rtfd.org and now built using Sphinx
  • Add support for multiple database connections - closes issue #15 [tag]
  • Add in raw_execute - closes issue #40 [tag]
  • Add get_last_statement() - closes issue #84 [tag]
  • Add HAVING clause functionality - closes issue #50
  • Add is_new method - closes issue #85
  • Add ArrayAccess support to the model instances allowing property access via $model['field'] as well as $model->field - issue #51
  • Add a result set object for collections of models that can support method chains to filter or apply actions to multiple results at once - issue #51 and #22
  • Add support for Firebird with ROWS and TO result set limiting and identifier quoting [mapner] - issue #98
  • Fix last insert ID for PostgreSQL using RETURNING - closes issues #62 and #89 [laacz]
  • Reset Idiorm after performing a query to allow for calling count() and then find_many() [fayland] - issue #97
  • Change Composer to use a classmap so that autoloading is better supported [javierd] - issue #96
  • Add query logging to delete_many [tag]
  • Fix when using set_expr alone it doesn't trigger query creation - closes issue #90
  • Escape quote symbols in "_quote_identifier_part" - close issue #74
  • Fix issue with aggregate functions always returning int when is float sometimes required - closes issue #92
  • Move testing into PHPUnit to unify method testing and query generation testing

1.2.3 - released 2012-11-28

  • Fix issue #78 - remove use of PHP 5.3 static call

1.2.2 - released 2012-11-15

  • Fix bug where input parameters were sent as part-indexed, part associative

1.2.1 - released 2012-11-15

  • Fix minor bug caused by IdiormStringException not extending Exception

1.2.0 - released 2012-11-14

  • Setup composer for installation via packagist (j4mie/idiorm)
  • Add order_by_expr method [sandermarechal]
  • Add support for raw queries without parameters argument [sandermarechal]
  • Add support to set multiple properties at once by passing an associative array to set method [sandermarechal]
  • Allow an associative array to be passed to configure method [jordanlev]
  • Patch to allow empty Paris models to be saved ([j4mie/paris]) - issue #58
  • Add select_many and select_many_expr - closing issues #49 and #69
  • Add support for MIN, AVG, MAX and SUM - closes issue #16
  • Add group_by_expr - closes issue #24
  • Add set_expr to allow database expressions to be set as ORM properties - closes issues #59 and #43 [brianherbert]
  • Prevent ambiguous column names when joining tables - issue #66 [hellogerard]
  • Add delete_many method [CBeerta]
  • Allow unsetting of ORM parameters [CBeerta]
  • Add find_array to get the records as associative arrays [Surt] - closes issue #17
  • Fix bug in _log_query with ? and % supplied in raw where statements etc. - closes issue #57 [ridgerunner]

1.1.1 - released 2011-01-30

  • Fix bug in quoting column wildcard. j4mie/paris#12
  • Small documentation improvements

1.1.0 - released 2011-01-24

  • Add is_dirty method
  • Add basic query caching
  • Add distinct method
  • Add group_by method

1.0.0 - released 2010-12-01

  • Initial release
Comments
  • findMany() returns only the last record in a set

    findMany() returns only the last record in a set

    I cloned the database one week ago and the latest version of iodiorm would only return the last record in a set.

    The example I used to prove it out was to create table called users and insert 16 users. Using the follow code I could only ever return the last record. A friend of mine working in the same code base confirmed the issue. I am on Linux and he is on OSX.

    \ORM::configure('mysql:host=localhost;dbname=------');
    \ORM::configure('username', '----');
    \ORM::configure('password', '----');
    \ORM::configure('logging', true);
    
    $people = \ORM::forTable('users')->findMany();
    

    I have a little more info on Stackoverflow and this was all done using the latest code from Git.

    Easy Pick 
    opened by risingfish 55
  • [improvement] find_many returns an associative array

    [improvement] find_many returns an associative array

    Pull based on https://github.com/j4mie/idiorm/issues/132

    Added find_many return associative keys. Micro optimizations for Idiorm and Paris. set and set_expr returns the instance, to admit a fluent query

    opened by Surt 24
  • Added a none function that guarantees an empty set.

    Added a none function that guarantees an empty set.

    Hi,

    I added a function.

    ORM::for_table('people')->none()->find_many();
    

    That is guaranteed to return an empty set. This code devolves down to the following query:

    SELECT * FROM `person` WHERE 0;
    

    The reasons for having a dedicated function are:

    • Syntatic sugar: none or a similarly named function makes more sense than where_raw(0)
    • Possibility to optimise (by not actually executing the query)

    An example use of this code in Paris would be:

    class User extends Model {
    
        public static function has_cookie($orm, $cookie_name) {
            if (isset($_COOKIE[$cookie_name]))  {
                $cookie = $_COOKIE[$cookie_name];
                return $orm->where('cookie', $cookie);
            }
            // Return empty set
            //return $orm->where_raw(0);
            return $orm->none();
        }
    
    }
    
    $users = Model::Factory('user')->filter('has_cookie', 'user')->find_many();
    
    opened by markchalloner 16
  • MSSQL TOP Limit style support

    MSSQL TOP Limit style support

    As requested, this is a manual merge of the code that was in pull request #37 with support of multiple connections and forcing the use of the TOP style limit for the dblib driver.

    It is currently in use in it's current form in one my projects so I can attest that it's working.

    opened by numkem 15
  • rowCount

    rowCount

    HI,

    Why not use PDOStatement :: rowCount to get the number of rows affected by the last statement.

    This property could be populated in the _run function after the statement execution like this: $this->_rowCount = $statement->rowCount();

    Regards,

    Enchancement Easy Pick 
    opened by featureless 14
  • Add a RAW JOIN source to the query

    Add a RAW JOIN source to the query

    Hi, I've added the raw_join function to the idiorm class. I find it very useful on optimizing the query and selecting the extra data from composite tables. Let me know if you find it appropriate, it actually copy/pasted version of the function _add_join_source without distinction between $join_operator and $table and skiping the _quote_identifier.

    opened by moiseevigor 13
  • Cache queries in idiorm

    Cache queries in idiorm

    I'm using Paris and idiorm for one of my sites and I've got lots of foreign key relationships expressed like this:

    public function children() {
      return $this->has_many('Child')->find_many();
    }
    

    The problem is that each time I execute the children() function on the same object, idiorm executes the following SQL (for example):

    SELECT * FROM child WHERE parent_id = 1
    

    If I'm using information about the children several times on the same page - e.g. checking whether there are any children using count(), then iterating over them - there are lots of unnecessary queries made. I'm never going to change the data once I've entered a view, so if idiorm was able to cache these queries that would be really helpful for my application.

    opened by pwaring 13
  • Issue with ORM::get_db()->exec() and ORM::raw_execute()

    Issue with ORM::get_db()->exec() and ORM::raw_execute()

    Hello,

    I'm using Idiorm 1.3.0 with MySQL 5.5.9 / PHP 5.3.5, and I'm getting troubles when using both ORM::get_db()->exec() and ORM::raw_execute().

    I'm trying to use this as a raw query : TRUNCATE table_name. But, when using these two methods :

    ORM::get_db()->exec('TRUNCATE table_name');
    ORM::raw_execute('TRUNCATE table_name');
    

    I get the same error :

    Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error: 1 near "TRUNCATE": syntax error'
    

    But I don't have any ideas from where this comes from :/

    Easy Pick 
    opened by EpocDotFr 12
  • Refactor join() to implode() as of warning in PHP 7.4

    Refactor join() to implode() as of warning in PHP 7.4

    Refactor join() to implode() as of deprecated warning in PHP 7.4... therefore some strict unit testing suites (like mine) that turn warnings into errors are going to fail.

    While fixing PHPUnit to support 5.x up to 7.4 it turns out that we cannot support both. PHP 7.4 needs PHPUnit 8 at least - that release enforces return types for setUp and tearDown that will cause syntax error in 5.x...

    So now this is an dead end accept we create a testing suite for 5.x and 7.4+

    • I had to put lot of work into fixing Travis CI - PHP 7.4 is not passing at the moment!
    • HHVM has been removed because composer no longer supports it: https://github.com/composer/composer/issues/8127
    • Added hack to bootstrap to support old and new PHPUnit namespace
    if (class_exists('\PHPUnit\Framework\TestCase')) {
    	class PHPUnit_Framework_TestCase extends \PHPUnit\Framework\TestCase
    	{
    	}
    }
    

    Supported PHPUnit versions: https://phpunit.de/supported-versions.html

    opened by henryruhs 11
  • Formatting - camelCase rather than underscore

    Formatting - camelCase rather than underscore

    How do you feel about having the methods converted to camel case so it is compliant with the PSR-1 spec? (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md)

    If you are open to it I can definitely help with the changes!

    opened by crhayes 11
  • Identifier quoting in Postgres

    Identifier quoting in Postgres

    Hi!

    I was quite impressed by compact and clean code of idiorm - so, I'm giving it a try in project where Postgresql database is be used. Problem I had was with ORM::_quote_identifier_part() - which quotes table/column names with "`", but a SQL statement in postgres commits seppuku when treated that way :) Could quoting character be made as a configuration option?

    .. code-block:: php

    protected function _quote_identifier_part($part) {
       $quote = self::$_config['identifier_quote_ch'];
       return $quote . $part . $quote;
    }
    

    Or - probably, identifier quoting could be called as a callback, leaving ORM::_quote_identifier_part just as a default method for that and be overridable in configuration?

    How do You feel about such changes? What the correct approach would be?

    opened by arcijsg 11
  • PHP8.1 compatibility issue on logging null

    PHP8.1 compatibility issue on logging null

    Version: v1.5.8

    Output Deprecated: PDO::quote(): Passing null to parameter #1 ($string) of type string is deprecated in C:\VHOST\VHOST8\idiorm\vendor\j4mie\idiorm\idiorm.php on line 539

    Testing Code

    <?php
    declare(strict_types=1);
    require_once "vendor/autoload.php";
    date_default_timezone_set('Asia/Hong_Kong');
    ini_set("assert.exception", "1");
    //error_reporting(E_ALL & ~E_DEPRECATED);
    
    /*
    CREATE TABLE `testing` (
    	`id` INT(11) NOT NULL AUTO_INCREMENT,
    	`timestamp` DATETIME NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
    	PRIMARY KEY (`id`) USING BTREE
    ) COLLATE='utf8_general_ci' ENGINE=InnoDB;
    */
    try{
        $hFile = fopen(__DIR__.DIRECTORY_SEPARATOR."run.log", 'w');
        $writeLine = function(string $message) use ($hFile):void{
            fwrite($hFile, $message.PHP_EOL);
        };
        $arrConfig = [
            'connection_string'=>'mysql:host=localhost;dbname=temp',
            'username'=>'root',
            'password'=>'P@ssw0rd',
            'return_result_sets'=>TRUE,
            'driver_options'=>[PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'],
            'error_mode'=>PDO::ERRMODE_EXCEPTION,
            'logging' => TRUE,
            'logger' => function($query, $time) use ($writeLine):void{
                $log = sprintf("[SQL %07.3f] %s", $time, $query);
                $writeLine($log);
            },
        ];
        ORM::configure($arrConfig);
        $orm = ORM::forTable("testing")->create();
        if(!$orm->save()) $writeLine("Create Fails");
        $id = intval($orm->id);
        $orm = ORM::forTable("testing")->findOne($id);
        $writeLine("Id# {$id} and get ".($orm->timestamp??"<NULL>"));
        $orm->timestamp = '2022-12-12 12:12:12';
        $orm->save();
        $writeLine("Id# {$id} and get ".($orm->timestamp??"<NULL>"));
        $orm->timestamp = NULL;
        $orm->save();
        $writeLine("Id# {$id} and get ".($orm->timestamp??"<NULL>"));
        if($hFile) fclose($hFile);
    } catch (Throwable $ex){
        $writeLine("[Throwable] ".$ex->getMessage());
        if($hFile) fclose($hFile);
    }
    

    Beside the notice, the logged SQL is not correct. [SQL 000.007] UPDATEtestingSETtimestamp= '' WHEREid= '8'

    opened by howan4work 0
  • Offset support for MSSQL / SQLSRV

    Offset support for MSSQL / SQLSRV

    MSSQL fails with an SQLSTATE[42000]: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server] syntax error when using offset()...

    1. TOP and OFFSET are not allowed to be used in one SELECT
    2. OFFSET 10 ROWS with FETCH NEXT 10 ROWS ONLY should be used
    3. Therefore _build_limit() and _build_offset() need some rework

    This are my approaches but I think something is missing to work properly:

    protected static function _detect_limit_clause_style($connection_name) {
        switch(self::get_db($connection_name)->getAttribute(PDO::ATTR_DRIVER_NAME)) {
            case 'dblib':
                return ORM::LIMIT_STYLE_TOP_N;
            case 'sqlsrv':
            case 'mssql':
                return ORM::LIMIT_STYLE_FETCH;
            default:
                return ORM::LIMIT_STYLE_LIMIT;
        }
    }
    
    protected function _build_limit() {
        $fragment = '';
        if (!is_null($this->_limit)) {
            if (self::$_config[$this->_connection_name]['limit_clause_style'] == ORM::LIMIT_STYLE_LIMIT) {
                if (self::get_db($this->_connection_name)->getAttribute(PDO::ATTR_DRIVER_NAME) == 'firebird') {
                    $fragment = 'ROWS';
                } else {
                    $fragment = 'LIMIT';
                }
                $fragment .= " {$this->_limit}";
            } else if (self::$_config[$this->_connection_name]['limit_clause_style'] == ORM::LIMIT_STYLE_FETCH) {
                $fragment = 'FETCH NEXT ' . $this->_limit . ' ROWS ONLY';
            }
        }
        return $fragment;
    }
    
    protected function _build_offset() {
        if (!is_null($this->_offset)) {
            $clause = 'OFFSET';
            if (self::get_db($this->_connection_name)->getAttribute(PDO::ATTR_DRIVER_NAME) == 'firebird') {
                $clause = 'TO';
            }
            if (self::$_config[$this->_connection_name]['limit_clause_style'] == ORM::LIMIT_STYLE_FETCH) {
                return $clause . ' ' . $this->_offset . '  ROWS';
            }
            return $clause . ' ' . $this->_offset;
        }
        return '';
    }
    

    Reference: http://www.sqlservertutorial.net/sql-server-basics/sql-server-offset-fetch/ https://stackoverflow.com/questions/2135418/equivalent-of-limit-and-offset-for-sql-server

    Moderate Pick Needs Tests 
    opened by henryruhs 0
Releases(v1.5.8)
Owner
Jamie Matthews
Web engineer (mostly). Technical director at @dabapps.
Jamie Matthews
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
A SQL query builder with zero dependencies

Latitude Query Builder A SQL query builder with zero dependencies. Attempts to be PSR-1, PSR-2, and PSR-4 compliant. Install composer require latitude

Woody Gilk 618 Dec 30, 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
Low code , Zero Configuration ORM that creates models, config, database and tables on the fly.

?? ARCA ORM ?? Low code , Zero Configuration ORM that creates models, config, database and tables on the fly. ?? ???? Made in India ???? Complete docu

Scrawler Labs 28 Dec 18, 2022
MOP is a php query handling and manipulation library providing easy and reliable way to manipulate query and get result in a fastest way. ( WEBSITE VERSION )

Mysql Optimizer mysql optimizer also known as MOP is a php query handling and manipulation library providing easy and reliable way to manipulate query

null 3 Feb 14, 2022
A MongoDB based Eloquent model and Query builder for Laravel (Moloquent)

Laravel MongoDB This package adds functionalities to the Eloquent model and Query builder for MongoDB, using the original Laravel API. This library ex

Jens Segers 6.3k Jan 5, 2023
SQL to Laravel Query Builder

Marwan - SQL To Laravel Builder SQL to Laravel Query Builder, A Converter written in PHP Features Converts SQL Queries to Laravel Query Builder. Assis

Rexhep Shijaku 162 Dec 19, 2022
Get MYSQL statement from query builder in laravel helper

Get MYSQL statement laravel This package allows to get mysql statement that query builder in laravel made it for debugging purposes. Basic usage Dump

Ahmed Helal 9 Jul 15, 2022
Simple MySQL library for PHP 5.4+ includes Query Builder, PDO Native functions, Helper functions for quick use.

Simple MySQL library for PHP 5.4+ includes Query Builder, PDO Native functions, Helper functions for quick use.

Kodols 9 Dec 22, 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
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
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
Independent query builders for MySQL, PostgreSQL, SQLite, and Microsoft SQL Server.

Aura.SqlQuery Provides query builders for MySQL, Postgres, SQLite, and Microsoft SQL Server. These builders are independent of any particular database

Aura for PHP 424 Dec 12, 2022
Eloquent Filter is a package for filter data of models by the query strings. Easy to use and fully dynamic.

Eloquent Filter Eloquent Filter adds custom filters to your Eloquent Models in Laravel. It's easy to use and fully dynamic. Table of Content Introduct

Mehdi Fathi 327 Dec 28, 2022
The query filter bundle allows you to filter data from QueryBuilder and the Database

The query filter bundle allows you to filter data from QueryBuilder and the Database. you can filter multiple columns at the same time and also you can filter relation fields with two-level deep and without any join in your query builder.

Milad Ghofrani 0 Apr 8, 2022
A simple program to query mysql data and display the queried data in JSON format

A simple program to query mysql data and display the queried data in JSON format. The data displayed in JSON format will change and update as the data in your mysql database changes.

null 2 Mar 7, 2022
The query sorting bundle allows you to sort data from QueryBuilder and the Database

The query sorting bundle allows you to sort data from QueryBuilder and the Database. you can sort multiple columns at the same time and also you can sort relation fields with two-level deep and without any join in your query builder.

Bugloos 12 Oct 6, 2022