Skeleton Generator

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.

PDO Wrapper

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.