# Introduction

Create repositories using the repository factory:

```php
use Objectiphy\Objectiphy\Factory\RepositoryFactory;
use MyProject\Contact;

$pdo = new \PDO(
    'mysql:host=localhost;dbname=test', 
    getenv('DB_USER'), 
    getenv('DB_PASS')
);

$factory = new RepositoryFactory($pdo);
$repository = $factory->createRepository(Contact::class);
```

You can use simple criteria in an array to load entities:

```php
// Load all staff in Sales department:
$criteria = ['department.name' => 'Sales'];
$contacts = $repository->findBy($criteria);
```

Or use more complex criteria to limit which properties of which records are returned using the object-oriented query builder, which closely resembles standard SQL syntax (but using classes and properties instead of tables and columns):

```php
// Get just the name for permanent staff in Sales and 
// Finance who have a car (even if the Contact entity 
// does not have a vehicle property)
$criteria = ['departments' => ['Sales', 'Finance']];
$query = QB::create()
         ->select('firstName', 'lastName')
         ->from(Contact::class)
         ->innerJoin(Vehicle::class, 'v')
             ->on('id', '=', 'v.ownerContactId')
             ->and('v.type', '=', 'car')
         ->where('department.name', 'IN', ':departments')
         ->and('isPermanent', '=', true)
         ->buildSelectQuery($criteria);
 $contacts = $repository->findBy($query);
```

Inserting or updating entities is also very easy (Objectiphy keeps track of changes to entities that it loaded, so will only save the things that have changed):

```php
$repository->saveEntity($contact);
```

Mapping information is typically specified using [mapping definitions](https://docs.objectiphy.net/annotations). You can use entities with [Objectiphy](https://docs.objectiphy.net/annotations/objectiphy-annotations) or [Doctrine](https://docs.objectiphy.net/annotations/doctrine-annotations) attributes or annotations (some features of Objectiphy that are not present in Doctrine require Objectiphy attributes, but you can mix both types).

## Features

* [one-to-one](https://docs.objectiphy.net/defining-relationships/one-to-one), [many-to-one](https://docs.objectiphy.net/defining-relationships/many-to-one), [one-to-many](https://docs.objectiphy.net/defining-relationships/one-to-many), and [many-to-many](https://docs.objectiphy.net/defining-relationships/many-to-many) relationships
* [lazy or eager](https://docs.objectiphy.net/late-binding-and-lazy-loading#lazy-loading-vs-eager-loading) loading
* [filter based on properties](https://docs.objectiphy.net/basic-usage) of both parent and child objects (even one-to-many)
* filter using [complex criteria](https://docs.objectiphy.net/query-builder/criteria)
* easily write [custom queries](https://docs.objectiphy.net/query-builder)
* [pagination](https://docs.objectiphy.net/pagination-and-sorting#pagination)
* [iterable results](https://docs.objectiphy.net/streaming-results) for streaming
* option of fetching unbound (scalar) results
* [custom repositories](https://docs.objectiphy.net/custom-repositories)
* limit hydration using [serialization groups](https://docs.objectiphy.net/serialization-groups)
* automatic or manual control of [transactions](https://docs.objectiphy.net/basic-saving#transactions)
* [select](https://docs.objectiphy.net/query-builder/select-queries), [insert](https://docs.objectiphy.net/query-builder/insert-queries), [update](https://docs.objectiphy.net/query-builder/update-queries), and [delete](https://docs.objectiphy.net/query-builder/delete-queries) records
* [cascade deletes](https://docs.objectiphy.net/deleting#cascade-deletes) and [orphan removal](https://docs.objectiphy.net/deleting#orphan-removal)
* [embedded](https://docs.objectiphy.net/embedded-value-objects) value objects
* perform [scalar joins](https://docs.objectiphy.net/defining-relationships/scalar-joins) (retrieve a single value from a joined table without needing a new entity or custom query)
* use aggregate functions to populate [properties](https://docs.objectiphy.net/annotations/objectiphy-annotations#aggregate-function-column-annotations) or as [filter criteria](https://docs.objectiphy.net/query-builder/criteria/filtering-by-aggregates)
* use any MySQL function you like in custom queries
* mark properties as read only
* [manually override](https://docs.objectiphy.net/mapping-overrides) mapping definitions (useful for unit testing)
* custom collection classes (for collections of child objects)
* handles recursive object relationships

{% hint style="danger" %}
This library has the ability to insert, update, and delete records in your database. Use with care!
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.objectiphy.net/master.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
