PHPackages                             surt/granada - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. surt/granada

Abandoned → [granadaorm/granada](/?search=granadaorm%2Fgranada)Library[Database &amp; ORM](/categories/database)

surt/granada
============

Active Record / ORM with eager loading, lazy loading and more

1.5.2(12y ago)451.4k12[1 PRs](https://github.com/Surt/Granada/pulls)BSD-2-ClausePHPPHP &gt;=5.3.0

Since Jun 24Pushed 5y ago11 watchersCompare

[ Source](https://github.com/Surt/Granada)[ Packagist](https://packagist.org/packages/surt/granada)[ Docs](https://github.com/Surt/Granada)[ RSS](/packages/surt-granada/feed)WikiDiscussions master Synced 5d ago

READMEChangelog (3)DependenciesVersions (8)Used By (0)

Granada
=======

[](#granada)

[![Latest Stable Version](https://camo.githubusercontent.com/5f99bf9d52dd75b558474d7e7e35f28086852644ec258819ed406ba56cda0516/68747470733a2f2f706f7365722e707567782e6f72672f737572742f6772616e6164612f762f737461626c652e706e67)](https://packagist.org/packages/surt/granada)[![Build Status](https://camo.githubusercontent.com/8ec30ade34cd39a74414fc00bd8505ace90b5398b1e6fef3f6bcc9ebbac49a0e/68747470733a2f2f7472617669732d63692e6f72672f537572742f4772616e6164612e706e673f6272616e63683d646576656c6f70)](https://travis-ci.org/Surt/Granada)[![deprecated](https://camo.githubusercontent.com/7e3f6f0da0a7ff8a445fec6cdab50a2a9d76f2b1a2e4f1cfe5047d4099b16655/687474703a2f2f6261646765732e6769746875622e696f2f73746162696c6974792d6261646765732f646973742f646570726563617465642e737667)](http://github.com/badges/stability-badges)

\[DEPRECATED\] This package is deprecated in favor of

Description
-----------

[](#description)

Granada is a easy to use Active Record implementation based on Idiorm/Paris with eager loading, lazy loading, query filters, mutators, etc.

A quick view:
-------------

[](#a-quick-view)

```
use Granada\Model;

class User extends Model {
    public function posts() {
        return $this->has_many('Post');
    }
}

class Post extends Model {}

// select
$user = User::where('name', 'John')->find_one();

// modify
$user->first_name = 'Doe';
$user->save();

// select relationship
$posts = $user->posts()->find_many();
foreach ($posts as $post) {
    echo $post->content;
}
```

You can read the Paris Docs on [paris.readthedocs.org](http://paris.rtfd.org) but be sure to read the additions below.

Install
-------

[](#install)

Using composer:

```
  "require": {

        "surt/granada": "dev-master"

    }

```

Configure it:

```
require 'vendor/autoload.php';

use Granada\ORM;

ORM::configure('mysql:host=localhost;dbname=my_database');
ORM::configure('username', 'database_user');
ORM::configure('password', 'top_secret');
```

As always, you can check it in detail on [Paris documentation](http://idiorm.readthedocs.org/en/latest/configuration.html#setup)

Aditions
--------

[](#aditions)

### Eager loading

[](#eager-loading)

You can use the "with" method to add relationships eager loading to the query.

```
  $results = User::with('avatar', 'posts')->find_many();
```

will use 3 querys to fetch the users and the relationships:

```
  SELECT * FROM user
  SELECT * FROM avatar WHERE user_id IN (....)
  SELECT * FROM posts WHERE user_id IN (....)
```

It is possible to get the relationships results for each result, this way

```
  foreach($results as $result){
      echo $result->avatar->img;
      foreach($result->posts as $post){
         echo $post->title;
      }
  }
```

---

### Lazy loading

[](#lazy-loading)

Triying to access to a not fetched relationship will call and return it

```
  $results = User::find_many();
  foreach($results as $result){
      echo $result->avatar->img;
  }
```

Notice that if there is no result for `avatar` on the above example it will throw a `Notice: Trying to get property of non-object...`Note: Maybe worth the effort to create a NULL object for this use case and others.

---

### Chained relationships with arguments for eager loading!

[](#chained-relationships-with-arguments-for-eager-loading)

It is possible to chain relationships and add arguments to the relationships calls

```
   // chained relationships with dot notation
   $results = User::with('posts.comments')->find_many();

   // OR

   // chained relationships use the "with" reserved word. (usefull if you want to pass arguments to the relationships)
   $results = User::with(array('posts'=>array('with'=>array('comments'))))->find_many();

    // SELECT * FROM user
    // SELECT * FROM post WHERE user_id IN (....)
    // SELECT * FROM comments WHERE post_id IN (....)

   foreach($results as $result){
      foreach($posts as $post){
         echo $post->title;
         foreach($post->comments as $comment){
            echo $comment->subject;
         }
      }
   }

   // you can use arguments (one or more) to call the models relationships
   $results = User::with(array('posts'=>array('arg1')))->find_many();
   // will call the relationship defined in the user model with the argument "arg1"
```

---

### Custom query filters

[](#custom-query-filters)

It's possible to create static functions on the model to work as filter in queries. Prepended it with "filter\_":

```
use Granada\Model;

class ModelName extends Model {
    ....
    public static function filter_aname($query, $argument1, $argument2...){
        return $query->where('property', 'value')->limit('X')......;
    }
    ....
}
```

and call it on a static call

```
ModelName::aname($argument1, $argument2)->....
```

---

### Multiple additions names for Granada

[](#multiple-additions-names-for-granada)

- select\_raw
- group\_by\_raw
- order\_by\_raw
- raw\_join
- insert : To create and save multiple elements from an array
- pluck : returns a single column from the result.
- find\_pairs : Return array of key=&gt;value as result
- save : accepts a boolean to use "ON DUPLICATE KEY UPDATE" (just for Mysql)
- delete\_many (accept join clauses)

---

### Overload SET

[](#overload-set)

```
    // In the Model
    protected function set_title($value)
    {
        $this->alias = Str::slug($value);
        return $value;
    }
```

```
    // outside of the model
    $content_instance->set('title', 'A title');

    // works with multiple set too
    $properties = array(
      'title'   => 'A title',
      'content' => 'Some content'
    );
    $content_instance->set($properties);

    // try it with a direct assignement
    $content_instance->title = 'A title';
```

---

### Overload GET and MISSING property

[](#overload-get-and-missing-property)

```
    // In the Model

    // Work on defined
    protected function get_path($value)
    {
        return strtolower($value);
    }

    // and non-defined attributes.
    protected function mising_testing()
    {
        return 'whatever';
    }
    ...

    // outside of the model
    echo $content_instance->path; // returns the lowercase path value of $content_instance
    echo $content_instance->testing; // returns 'whatever' since we defined a missing_{attribute_name}
```

Of course, you still can define functions with the property name if you want to overload it completely.

---

### Define resultSet (collection type) class on Model

[](#define-resultset-collection-type-class-on-model)

Now is possible to define the resultSet class returned for a model instances result. (if `return_result_sets` config variable is set to true) Notice that the resultSet class defined must `extends Granada\ResultSet` and must be loaded

```
    // In the Model
    public static $resultSetClass = 'TreeResultSet';
```

```
    // outside of the model
    var_dump(Content::find_many());

    // echoes
    object(TreeResultSet)[10]
        protected '_results' => array(...)
    ....
```

ResultSets are defined by the model in the result, as you can see above. On eager load, the results are consistent. For example, if we have a `Content` model, with `$resultSetClass = 'TreeResultSet'` and a `has_many` relationship defined as `media`:

```
  Content::with('media')->find_many();
```

will return a `TreeResultSet` with instances of `Content` each with a `property $media` containing `Granada\ResultSet` (the default resultSet if none if defined on the Model)

---

Basic Documentation comes from Paris:
-------------------------------------

[](#basic-documentation-comes-from-paris)

Paris
=====

[](#paris)

### Feature complete

[](#feature-complete)

Paris is now considered to be feature complete as of version 1.4.0. Whilst it will continue to be maintained with bug fixes there will be no further new features added.

A lightweight Active Record implementation for PHP5.

Built on top of [Idiorm](http://github.com/j4mie/idiorm/).

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

Released under a [BSD license](http://en.wikipedia.org/wiki/BSD_licenses).

Features
--------

[](#features)

- Extremely simple configuration.
- Exposes the full power of [Idiorm](http://github.com/j4mie/idiorm/)'s fluent query API.
- Supports associations.
- Simple mechanism to encapsulate common queries in filter methods.
- Built on top of [PDO](http://php.net/pdo).
- Uses [prepared statements](http://uk.php.net/manual/en/pdo.prepared-statements.php) throughout to protect against [SQL injection](http://en.wikipedia.org/wiki/SQL_injection) attacks.
- 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 are supported

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity29

Limited adoption so far

Community23

Small or concentrated contributor base

Maturity63

Established project with proven stability

 Bus Factor1

Top contributor holds 56.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~46 days

Total

4

Last Release

4571d ago

PHP version history (2 changes)v1.0PHP &gt;=5.2.0

v1.5PHP &gt;=5.3.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/3fe0063e782fd7efb933619df4ac774d2eb447ae240464dc50893100efbdc417?d=identicon)[Surt](/maintainers/Surt)

---

Top Contributors

[![Surt](https://avatars.githubusercontent.com/u/48085?v=4)](https://github.com/Surt "Surt (170 commits)")[![j4mie](https://avatars.githubusercontent.com/u/6988?v=4)](https://github.com/j4mie "j4mie (56 commits)")[![treffynnon](https://avatars.githubusercontent.com/u/65215?v=4)](https://github.com/treffynnon "treffynnon (44 commits)")[![tomvo](https://avatars.githubusercontent.com/u/1503385?v=4)](https://github.com/tomvo "tomvo (11 commits)")[![joshbmarshall](https://avatars.githubusercontent.com/u/4043827?v=4)](https://github.com/joshbmarshall "joshbmarshall (8 commits)")[![PeterSchumacher](https://avatars.githubusercontent.com/u/200637?v=4)](https://github.com/PeterSchumacher "PeterSchumacher (4 commits)")[![Wuffz](https://avatars.githubusercontent.com/u/996222?v=4)](https://github.com/Wuffz "Wuffz (3 commits)")[![pine3ree](https://avatars.githubusercontent.com/u/3229979?v=4)](https://github.com/pine3ree "pine3ree (1 commits)")[![jahvi](https://avatars.githubusercontent.com/u/661330?v=4)](https://github.com/jahvi "jahvi (1 commits)")[![bitdeli-chef](https://avatars.githubusercontent.com/u/3092978?v=4)](https://github.com/bitdeli-chef "bitdeli-chef (1 commits)")[![scrutinizer-auto-fixer](https://avatars.githubusercontent.com/u/6253494?v=4)](https://github.com/scrutinizer-auto-fixer "scrutinizer-auto-fixer (1 commits)")

---

Tags

databaseormactive-recordeager-loadingidiormparis

### Embed Badge

![Health badge](/badges/surt-granada/health.svg)

```
[![Health](https://phpackages.com/badges/surt-granada/health.svg)](https://phpackages.com/packages/surt-granada)
```

###  Alternatives

[propel/propel1

Propel is an open-source Object-Relational Mapping (ORM) for PHP5.

8481.6M87](/packages/propel-propel1)[granadaorm/granada

Active Record / ORM with eager loading, lazy loading and more

178.9k1](/packages/granadaorm-granada)[perplorm/perpl

Perpl is an improved and still maintained fork of Propel2, an open-source Object-Relational Mapping (ORM) for PHP.

203.7k](/packages/perplorm-perpl)[flightphp/active-record

Micro Active Record library in PHP, support chain calls, events, and relations.

163.0k](/packages/flightphp-active-record)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
