PHPackages                             perplorm/perpl - 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. perplorm/perpl

ActiveLibrary[Database &amp; ORM](/categories/database)

perplorm/perpl
==============

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

v2.7.0(2mo ago)203.7k↑11.5%4[5 PRs](https://github.com/perplorm/perpl/pulls)MITPHPPHP &gt;=8.1CI passing

Since Jun 5Pushed 1mo ago4 watchersCompare

[ Source](https://github.com/perplorm/perpl)[ Packagist](https://packagist.org/packages/perplorm/perpl)[ Docs](https://perplorm.github.io)[ RSS](/packages/perplorm-perpl/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (7)Dependencies (39)Versions (26)Used By (0)

Perpl ORM
=========

[](#perpl-orm)

Perpl is a fork of the unmaintained [Propel2](https://github.com/propelorm/Propel2), an open-source Object-Relational Mapping (ORM) for PHP. It adds several improvements and fixes, including proper versioning.

[![Github actions Status](https://github.com/mringler/perpl/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/propelorm/Propel2/actions/workflows/ci.yml?query=branch%3Amaster)[![codecov](https://camo.githubusercontent.com/3621f9971cf2f35ed2af28abca5ab0d9d4d0c4dfa24af1ac5ce79ee3fe5e69fa/68747470733a2f2f636f6465636f762e696f2f67682f70726f70656c6f726d2f50726f70656c322f6272616e63682f6d61737465722f67726170682f62616467652e7376673f746f6b656e3d4c3174684642396e4f47)](https://codecov.io/gh/propelorm/Propel2)[![PHPStan](https://camo.githubusercontent.com/ff9142aa79e58bd482fac3aff00d4bea75e9b4a0e2f4908bb26d1b7f5df3a5ab/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c253230372d627269676874677265656e2e7376673f7374796c653d666c6174)](https://phpstan.org/)[![Psalm](https://camo.githubusercontent.com/37a1f12841d3ec72c06420e9da09167d3cfb2c8f5a346d55ab842f62fc830896/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5073616c6d2d6c6576656c253230352d6461726b677265656e2e7376673f7374796c653d666c6174)](https://psalm.dev/docs/running_psalm/error_levels/)[![Minimum PHP Version](https://camo.githubusercontent.com/7ddd0b2455db79dcdef99447ace66fe96bef3e86f039ffeda44df726d814e700/687474703a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344253230382e312d3838393242462e737667)](https://php.net/)[![License](https://camo.githubusercontent.com/7be9068adde0caf9d852b484dc77ea48bfca916ecfb2353a9492f2e484c0b41c/68747470733a2f2f706f7365722e707567782e6f72672f70726f70656c2f70726f70656c2f6c6963656e73652e737667)](https://packagist.org/packages/perplorm/perpl)

Installation
============

[](#installation)

- Replace the `require` declaration for Propel with Perpl:

```
  "require": {
+    "perplorm/perpl": ">=2.0",
-    "propel/propel": "dev-main as 2.0.x-dev",
  },
```

- Remove the `vcs` entry for Propel2 dev in composer.json:

```
  "repositories": [
-    {
-      "type": "vcs",
-      "url": "git@github.com:propelorm/Propel2.git"
-    }
  ],
```

- Update libraries:

```
$ composer update
```

- Rebuild models:

```
$ vendor/bin/propel --config-dir  model:build
$ composer dump-autoload
```

- Open a file where you call `Query::find()` and replace it with `Query::findObjects()`. If everything worked, you get return type `ObjectCollection`. Yay!

⚡ Don't forget to analyze your project with [PHPStan](https://phpstan.org/) (or similar) to get notice where updates are necessary due to improved types in Perpl.Features
========

[](#features)

Motivation for Perpl was to make features available around code-style, typing, performance and usability.

Ready for PHP 8.5
-----------------

[](#ready-for-php-85)

Code is tested to run in PHP 8.5 without deprecation notices or warnings.

Type-preserving queries
-----------------------

[](#type-preserving-queries)

Improved types allow for code completion and statistic analysis.

- preserves types between calls to `useXXXQuery()`/`endUse()`
- adds methods `findObjects()`/`findTuples()`, which return typed Collection objects

```
// keep query class over calls to useQuery()
$q = BookQuery::create();                              // BookQuery
$q = $q->useAuthorQuery();                             // AuthorQuery
$q = $q->useEssayRelatedByFirstAuthorIdExistsQuery();  // EssayQuery
$q = $q->endUse();                                     // AuthorQuery
$q = $q->endUse();                                     // BookQuery

// keep query class over conditional chain
$q->_if($condition)
  ->filterBy...()
  ->_else()
  ->filterBy...()
  ->_endif();                                          // all BookQuery

// findObjects() returns object collection
$o = $q->findObjects();                                // BookCollection
$a = $o->populateAuthor()                              // AuthorCollection
$a = $a->getFirst();                                   // Author|null

// findTuples() returns arrays
$a = $q->findTuples();                                 // ArrayCollection
$r = $q->getFirst();                                   // array|null
```

Note that type propagation in `endUse()` requires child query classes to declare and pass on the generic parameter from their parent/base class:

```
/*
 * @template ParentQuery extends \Propel\Runtime\ActiveQuery\TypedModelCriteria|null = null
 * @extends BaseBookQuery
 */
class BookQuery extends BaseBookQuery
```

This cannot be added automatically for existing classes. While IDEs seem to figure it out without the declaration, phpstan or psalm will (correctly) see the return type as `null` and report errors. Add the declaration in the child class to fix it.

Generating collection classes for models can be configured in schema.xml, (see [\#47](https://github.com/mringler/perpl/pull/47) for details)

Code cleanup and improved performance
-------------------------------------

[](#code-cleanup-and-improved-performance)

These changes mostly improve internal readability/soundness of core Propel code. They mostly allow for easier and safe maintenance, but occasionally lead to performance improvements, for example when repetitive operations on strings are replaced by proper data structures.

Some notable changes:

- columns in queries are turned to objects, which leads to more readable code and makes tons of string operations obsolete (~30-50% faster query build time, see [\#24](https://github.com/mringler/perpl/pull/24))
- fixes some confusing names (Criteria vs Criterion)
- spreads out some "one size fits none" overloads, i.e. `Criteria::map` becomes `Criteria::columnFilters` and `Criteria::updateValues`

Nested filters through operators
--------------------------------

[](#nested-filters-through-operators)

Introduces `Criteria::combineFilters()`/`Criteria::endCombineFilters()` which build nested filter conditions:

```
// A=1 AND (B=2 OR C=3) AND (D=4 OR E=5)
(new Criteria())
  ->addFilter('A', 1)
  ->combineFilters()
    ->addFilter('B', 2)
    ->addOr('C', 3)
  ->endCombineFilters()
  ->combineFilters()
    ->addFilter('D', 4)
    ->addOr('E', 5)
  ->endCombineFilters()
```

Previously, this required to register the individual parts under an arbitrary name using `Criteria::addCond()` and then combining them with `Criteria::combine()`, possibly under another arbitrary name for further processing.

Read multiple behaviors from same repository
--------------------------------------------

[](#read-multiple-behaviors-from-same-repository)

Propel restricts reading behaviors from repositories to one per repo. This allows to read multiple behaviors (see [\#25](https://github.com/mringler/perpl/pull/25) for details).

Fixed cross-relations
---------------------

[](#fixed-cross-relations)

Creates methods for all elements of ternary relation (Propel only uses first foreign key). Fixes naming issues and detects duplicates in model method names.

Disclaimer
==========

[](#disclaimer)

Built with care, tested, provided as is. Test before deployment. Let me know how it goes!

Feedback and PRs are welcome.

Thanks to Propel2!

License
=======

[](#license)

MIT. See the `LICENSE` file for details.

###  Health Score

60

—

FairBetter than 99% of packages

Maintenance87

Actively maintained with recent releases

Popularity34

Limited adoption so far

Community24

Small or concentrated contributor base

Maturity82

Battle-tested with a long release history

 Bus Factor2

2 contributors hold 50%+ of commits

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 ~245 days

Recently: every ~79 days

Total

20

Last Release

69d ago

PHP version history (6 changes)2.0.0-alpha1PHP &gt;=5.4

2.0.0-alpha6PHP &gt;=5.5

2.0.0-alpha9PHP &gt;=7.1

2.0.0-alpha11PHP &gt;=7.2

v2.0.0PHP &gt;=7.4

v2.1.0PHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/db1142f853353d31999eb3c61487e7e245b07acb6cace1b568f8145cc21af9de?d=identicon)[mringler](/maintainers/mringler)

---

Top Contributors

[![fzaninotto](https://avatars.githubusercontent.com/u/99944?v=4)](https://github.com/fzaninotto "fzaninotto (1239 commits)")[![willdurand](https://avatars.githubusercontent.com/u/217628?v=4)](https://github.com/willdurand "willdurand (771 commits)")[![mringler](https://avatars.githubusercontent.com/u/9800945?v=4)](https://github.com/mringler "mringler (424 commits)")[![dereuromark](https://avatars.githubusercontent.com/u/39854?v=4)](https://github.com/dereuromark "dereuromark (336 commits)")[![marcj](https://avatars.githubusercontent.com/u/450980?v=4)](https://github.com/marcj "marcj (151 commits)")[![Incognito](https://avatars.githubusercontent.com/u/379322?v=4)](https://github.com/Incognito "Incognito (118 commits)")[![jaugustin](https://avatars.githubusercontent.com/u/564420?v=4)](https://github.com/jaugustin "jaugustin (94 commits)")[![cristianoc72](https://avatars.githubusercontent.com/u/865437?v=4)](https://github.com/cristianoc72 "cristianoc72 (70 commits)")[![ikeyan](https://avatars.githubusercontent.com/u/8082735?v=4)](https://github.com/ikeyan "ikeyan (66 commits)")[![oojacoboo](https://avatars.githubusercontent.com/u/764664?v=4)](https://github.com/oojacoboo "oojacoboo (49 commits)")[![robin850](https://avatars.githubusercontent.com/u/354185?v=4)](https://github.com/robin850 "robin850 (43 commits)")[![gharlan](https://avatars.githubusercontent.com/u/330436?v=4)](https://github.com/gharlan "gharlan (39 commits)")[![PhilinTv](https://avatars.githubusercontent.com/u/376033?v=4)](https://github.com/PhilinTv "PhilinTv (26 commits)")[![nederdirk](https://avatars.githubusercontent.com/u/778965?v=4)](https://github.com/nederdirk "nederdirk (25 commits)")[![Big-Shark](https://avatars.githubusercontent.com/u/646054?v=4)](https://github.com/Big-Shark "Big-Shark (25 commits)")[![bezpiatovs](https://avatars.githubusercontent.com/u/68903876?v=4)](https://github.com/bezpiatovs "bezpiatovs (22 commits)")[![smhg](https://avatars.githubusercontent.com/u/2411348?v=4)](https://github.com/smhg "smhg (21 commits)")[![themouette](https://avatars.githubusercontent.com/u/245501?v=4)](https://github.com/themouette "themouette (19 commits)")[![staabm](https://avatars.githubusercontent.com/u/120441?v=4)](https://github.com/staabm "staabm (18 commits)")[![K-Phoen](https://avatars.githubusercontent.com/u/66958?v=4)](https://github.com/K-Phoen "K-Phoen (17 commits)")

---

Tags

persistencedatabaseormactive-recordpropelpropel2Perpl

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/perplorm-perpl/health.svg)

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

###  Alternatives

[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

595.2M386](/packages/shopware-core)[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[propel/propel

Propel2 is an open-source Object-Relational Mapping (ORM) for PHP.

1.3k5.3M110](/packages/propel-propel)[drupal/core

Drupal is an open source content management platform powering millions of websites and applications.

19562.3M1.3k](/packages/drupal-core)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)

PHPackages © 2026

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