Skip to content
This repository has been archived by the owner on Jan 24, 2024. It is now read-only.

Commit

Permalink
Merge pull request #11 from spiral/develop
Browse files Browse the repository at this point in the history
Update readme, exception message, orm bugfix
  • Loading branch information
wolfy-j authored Sep 20, 2017
2 parents e6b7125 + f18755a commit 8327b2d
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 8 deletions.
97 changes: 96 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,99 @@ Spiral ORM
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/spiral/orm/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/spiral/orm/?branch=master)
[![Coverage Status](https://coveralls.io/repos/github/spiral/orm/badge.svg?branch=master)](https://coveralls.io/github/spiral/orm?branch=master)

<b>[Documentation](http://spiral-framework.com/guide)</b> | [CHANGELOG](/CHANGELOG.md)
ORM engine with automatic database scaffolding, strict schemas, code discovery, modular database partitions and various relation loaders. Hackable!

<b>[Full Documentation](http://spiral-framework.com/guide)</b> | [CHANGELOG](/CHANGELOG.md)

# Documentation
* [Overview](https://spiral-framework.com/guide/orm/overview.md)
* [Record and RecordEntity](https://spiral-framework.com/guide/orm/entities.md)
* [Repositories and Selectors](https://spiral-framework.com/guide/orm/repositories.md)
* [Accessors and Filters](https://spiral-framework.com/guide/orm/accessors.md)
* [Column Objects](https://spiral-framework.com/guide/orm/columns.md)
* [Scaffolding and Migrations](https://spiral-framework.com/guide/orm/scaffolding.md)
* [Transactions](https://spiral-framework.com/guide/orm/transactions.md)
* [Relations](https://spiral-framework.com/guide/orm/relations.md)
* [Morphed Relations](https://spiral-framework.com/guide/orm/morphed-relations.md)
* [Pre-compiled Relations](https://spiral-framework.com/guide/orm/late-binding.md)
* [Query Models](https://spiral-framework.com/guide/orm/query.md)
* [Eager loading](https://spiral-framework.com/guide/orm/loading.md)
* [Recursive Relations](https://spiral-framework.com/guide/orm/recursive-relations.md)
* [Hybrid Databases](https://spiral-framework.com/guide/orm/odm-bridge.md)
* [Custom Relations](https://spiral-framework.com/guide/orm/custom-relations.md)

# Examples

```php
class Post extends RecordEntity
{
use TimestampsTrait;

//Database partitions, isolation and aliasing
const DATABASE = 'blog';

const SCHEMA = [
'id' => 'bigPrimary',
'title' => 'string(64)',
'status' => 'enum(published,draft)',
'body' => 'text',

//Simple relation definitions
'comments' => [self::HAS_MANY => Comment::class],

//Not very simple relation definitions
'collaborators' => [
self::MANY_TO_MANY => User::class,
self::PIVOT_TABLE => 'post_collaborators_map',
self::PIVOT_COLUMNS => [
'time_assigned' => 'datetime',
'type' => 'string, nullable',
],
User::INVERSE => 'collaborated_posts'
],

//Pre-compiled relations
'author' => [
self::BELONGS_TO => AuthorInterface::class,
self::LATE_BINDING => true
],

//Hybrid databases
'metadata' => [
Document::ONE => Mongo\Metadata::class
]
];
}
```

```php
$posts = $postSource->find()->distinct()
->with('comments', ['where' => ['{@}.approved' => true]]) //Automatic joins
->with('author')->where('author_name', 'LIKE', $authorName) //Fluent
->load('comments.author') //Cascade eager-loading (joins or external query)
->paginate(10) //Quick pagination using active request
->getIterator();

foreach ($posts as $post) {
echo $post->author->getName();
}
```

```php
$post = new Post();
$post->publish_at = 'tomorrow 8am';
$post->author = new User(['name' => 'Antony']);

$post->tags->link(new Tag(['name' => 'tag A']));
$post->tags->link($tags->findOne(['name' => 'tag B']));

$transaction = new Transaction();
$transaction->store($post);
$transaction->run();

//--or--: Active record (optional)
$post->save();

//--or--: request specific transaction
$this->transaction->store($post);
```
8 changes: 5 additions & 3 deletions source/Spiral/ORM/Entities/Loaders/AbstractLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,10 @@ final public function loadRelation(
}

if ($join) {
//Let's tell our loaded that it's method is JOIN (forced)
$options['method'] = self::JOIN;
if (empty($options['method']) || !in_array($options['method'], [self::JOIN, self::LEFT_JOIN])) {
//Let's tell our loaded that it's method is JOIN (forced)
$options['method'] = self::JOIN;
}
}

if (isset($loaders[$relation])) {
Expand Down Expand Up @@ -364,4 +366,4 @@ private function loadChain(string $chain, array $options, bool $join): LoaderInt
$join
);
}
}
}
4 changes: 2 additions & 2 deletions source/Spiral/ORM/Entities/Relations/Traits/SyncedTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ trait SyncedTrait
*/
protected function isSynced(RecordInterface $inner, RecordInterface $outer): bool
{
if (empty($outer->primaryKey())) {
if (empty($inner->primaryKey()) || empty($outer->primaryKey())) {
//Parent not saved
return false;
}
Expand All @@ -46,4 +46,4 @@ protected function isSynced(RecordInterface $inner, RecordInterface $outer): boo
* @return string|null
*/
abstract protected function key(int $key);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,11 @@ public function declareTables(SchemaBuilder $builder): array

$outerKey = $this->findOuter($builder);
if (empty($outerKey)) {
throw new RelationSchemaException("Unable to build morphed relation, no outer record found");
throw new RelationSchemaException(sprintf(
"Unable to build morphed relation, no outer record(s) found for '%s' from '%s'",
$this->getDefinition()->getTarget(),
$this->getDefinition()->sourceContext()->getClass()
));
}

//Make sure all tables has same outer
Expand Down Expand Up @@ -198,4 +202,4 @@ public function packRelation(SchemaBuilder $builder): array

return $packed;
}
}
}

0 comments on commit 8327b2d

Please sign in to comment.