diff --git a/README.md b/README.md
index 01da0b8..bdd5419 100644
--- a/README.md
+++ b/README.md
@@ -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)
-[Documentation](http://spiral-framework.com/guide) | [CHANGELOG](/CHANGELOG.md)
\ No newline at end of file
+ORM engine with automatic database scaffolding, strict schemas, code discovery, modular database partitions and various relation loaders. Hackable!
+
+[Full Documentation](http://spiral-framework.com/guide) | [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);
+```
diff --git a/source/Spiral/ORM/Entities/Loaders/AbstractLoader.php b/source/Spiral/ORM/Entities/Loaders/AbstractLoader.php
index 50631ab..c99507f 100644
--- a/source/Spiral/ORM/Entities/Loaders/AbstractLoader.php
+++ b/source/Spiral/ORM/Entities/Loaders/AbstractLoader.php
@@ -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])) {
@@ -364,4 +366,4 @@ private function loadChain(string $chain, array $options, bool $join): LoaderInt
$join
);
}
-}
\ No newline at end of file
+}
diff --git a/source/Spiral/ORM/Entities/Relations/Traits/SyncedTrait.php b/source/Spiral/ORM/Entities/Relations/Traits/SyncedTrait.php
index 87b2ef1..5f8b492 100644
--- a/source/Spiral/ORM/Entities/Relations/Traits/SyncedTrait.php
+++ b/source/Spiral/ORM/Entities/Relations/Traits/SyncedTrait.php
@@ -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;
}
@@ -46,4 +46,4 @@ protected function isSynced(RecordInterface $inner, RecordInterface $outer): boo
* @return string|null
*/
abstract protected function key(int $key);
-}
\ No newline at end of file
+}
diff --git a/source/Spiral/ORM/Schemas/Relations/BelongsToMorphedSchema.php b/source/Spiral/ORM/Schemas/Relations/BelongsToMorphedSchema.php
index 7df410e..a4f2f80 100644
--- a/source/Spiral/ORM/Schemas/Relations/BelongsToMorphedSchema.php
+++ b/source/Spiral/ORM/Schemas/Relations/BelongsToMorphedSchema.php
@@ -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
@@ -198,4 +202,4 @@ public function packRelation(SchemaBuilder $builder): array
return $packed;
}
-}
\ No newline at end of file
+}