Atlas

Simple. Sensible. SQL.

Atlas is a database framework for PHP to help you work with your persistence model, while providing a path to refactor towards a richer domain model as needed.

Object-Relational Manager

A data mapper ORM for your persistence layer, not your domain layer. The flagship package in the Atlas family. Supports MySQL, PostgreSQL, SQLite, and SQL Server.

Docs Code

Skeleton Generator

A command-line interface to generate all of the necessary Atlas classes to model your existing database tables in PHP. Supports MySQL, PostgreSQL, SQLite, and SQL Server.

Docs Code

Data Mapper

The core of the Atlas.Orm package, the data mapper helps you define relationships between table data gateways so you can retrieve Record objects with all their related rows. Supports MySQL, PostgreSQL, SQLite, and SQL Server.

Docs Code

Table Data Gateway

A table data gateway implementation, for when a full-fledged persistence ORM seems too much. Supports MySQL, PostgreSQL, SQLite, and SQL Server.

Docs Code

Query System

Build and perform SELECT, INSERT, UPDATE, and DELETE queries through a fluent interface using standard SQL vocabulary. Supports all database drivers for PDO.

Docs Code

PDO Wrapper

A straightforward PDO connection wrapper to provide convenience methods for fetching and yielding database results. Supports all database drivers for PDO.

Docs Code

Why Atlas?

Atlas helps developers to get started about as easily as they would with Active Record for their persistence model, and provides a path to refactor more easily towards a richer domain model as needed.

What Is A Persistence Model?

A persistence model is a model of your database, not your business domain. More specifically, it is an object-oriented representation of the tables and rows in the database.

Very often, a developer does not have a good, clean domain model to work with, especially early in the project. But there is almost always a database of some sort. Atlas models that database structure so you can use it more easily in PHP code.

Why Use A Persistence Model?

A persistence model alone should get your application a long way, especially at the beginning of a project. The Row, Record, and RecordSet objects in Atlas are disconnected from the database, which should make the refactoring and integration process a lot cleaner than with Active Record.

Because Atlas works with your database schema as-it-is, and not as-the-ORM-thinks it-should-be, Atlas is a very good fit for projects with pre-existing databases. (Indeed, Atlas supports both composite primary keys and composite foreign keys -- for some legacy systems, composite keys are absolutely necessary.)

How Does Atlas Work?

At a high level, Atlas is mini-framework built from a stack of packages, where any "lower" package can be used indepdendently of the the ones "above" it. This means you can pick the exact level of functionality you need right now, and expand to the next greater set of functionality only as is becomes necessary.

The package hierarchy, from bottom to top, looks like this:

  • Atlas.Pdo provides a database Connection object and a ConnectionLocator. If all you need is convenience wrapper around PDO with fetch and yield methods, this is the package for you.

  • Atlas.Query is a query builder that wraps an Atlas.Pdo Connection. If you just want to build and perform SQL queries using an object-oriented approach, the Atlas query objects can handle that.

  • Atlas.Table is a table data gateway implementation that uses Atlas.Query under the hood. If you don't need a full data mapper system and only want to interact with individual tables and their row objects, this will do the trick.

  • Atlas.Mapper is a data mapper implementation that models the relationships between tables. It allows you to build Record and RecordSet objects whose Row objects map naturally back to Table objects; you can write them back to the database one by one, or persist an entire Record graph back to the database in one go.

  • Atlas.Orm is the overarching ORM package; it provides a convenience wrapper around the Mapper system, as well as several strategies for transaction management.

Thus, Atlas uses a table data gateway for the underlying table Rows, then composes those Rows into Records and RecordSets via a data mapper; the PDO connection and query system move the data back and forth between PHP and the database.

From Persistence To Domain

At the beginning, your domain logic layer (e.g. service layer, application service, interactor, use case, etc.) can manipulate the Atlas persistence objects (Records and RecordSets) directly. You can add simple behavior methods to your Records and RecordSets as well.

Then, as a domain model grows within your application, Mehdi Khalili shows that the refactoring process can move along one of two paths:

  • "Domain Model composed of Persistence Model". That is, the domain objects can use Atlas persistence model Record objects internally, but do not expose them. The domain objects can manipulate the persistence model objects internally as much as they wish. For example, a domain object might have a getAddress() method that reads from the internal Record.
  • "DDD on top of ORM". Here, Repositories map the persistence model objects to and from domain objects. This provides a full decoupling of the domain model from the persistence model, but is more time-consuming to develop.

Other Considerations

Here some further considerations regarding Atlas:

  • PHPStorm IDE auto-completion. When you use the phpstorm.meta.php resource included in relevant packages, PHPStorm will autocomplete methods and properties from your Mapper, Record, RecordSet, et al. classes.
  • No annotations. Code should be in code, not in comments.
  • No lazy-loading. Lazy-loading is seductive, but eventually is more trouble than it's worth. Atlas doesn't make it available at all, so it cannot be invoked accidentally.
  • No data-type abstractions. Data-type abstraction seems great at first, but it too ends up not being worth the trouble. Therefore, the actual underlying database types are exposed and available as much as possible.

Contra-Indications

You may not find Atlas suitable for your needs because of the following:

  • Atlas uses code generation, though only in a very limited way. It turns out that code generation is useful for some boilerplate code. For example, each table is described as a PHP class, one that returns things like table name, column names, etc. Since the table class should change only when the database changes, code generation makes sense here; however, some developers may be against code generation just on principle alone.
  • Atlas uses base Row, Record, and RecordSet classes, instead of plain-old PHP objects. If this were a domain modeling system, a base class would be unacceptable. Because Atlas is a persistence modeling system, base classes are less objectionable, but for some this may be undesired.