-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
166 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Boosting CSV Export | ||
|
||
The module tries to detect the fact that you are doing the CSV Export and scans the `private static $export_fields` for suitable relations and loads them in advance in attempt to speed up the export. | ||
|
||
In the following example relations `Subscribers` and `Address` would be loaded as a whole for every exported rows and instead of being fetched one-by-one. | ||
|
||
```php | ||
class YourClass extends DataObject | ||
{ | ||
private static $has_one = [ | ||
'Subscriber' => Subscriber::class, | ||
]; | ||
|
||
private static $has_many = [ | ||
'Address' => Address::class, | ||
]; | ||
|
||
private static $export_fields = [ | ||
'Created' => 'Date', | ||
'ID' => 'Order ID', | ||
'Subscriber.FirstName' => 'Recipient first name', | ||
'Subscriber.LastName' => 'Recipient last name', | ||
'Address.Address' => 'Recipient street address', | ||
'Address.Region' => 'Recipient state', | ||
'Address.Country' => 'Recipient country', | ||
'Address.PostalCode' => 'Recipient postcode', | ||
]; | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Boosting GridField Output | ||
|
||
You can add a property to your DataObject class with a list of relations to eagerly load when browsing this class entities with a GridGield (in CMS area). | ||
|
||
```php | ||
|
||
class YourClass extends DataObject | ||
{ | ||
private static $eager_loading = [ | ||
'Relation1', | ||
'Relation1.Relation4', | ||
'Relation2', | ||
'Relation3', | ||
]; | ||
|
||
private static $has_one = [ | ||
'Relation1' => SomeClassOne::class, | ||
]; | ||
private static $has_many = [ | ||
'Relation2' => SomeClassTwo::class, | ||
]; | ||
private static $many_many = [ | ||
'Relation3' => SomeClassThree::class, | ||
]; | ||
} | ||
|
||
class SomeClassOne extends DataObject | ||
{ | ||
private static $has_one = [ | ||
'Relation4' => SomeClassFour::class, | ||
]; | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Using with `$has_many`, `$many_many` and `$belongs_many_many` | ||
|
||
Module is able to load such relations out of the bot, but accessing it is a problem because it has to be done through functions. | ||
|
||
To enable access to `$has_many`, `$many_many`, `$belongs_many_many` **add the following trait to all your models**: | ||
```php | ||
class MyClass extends DataObject { | ||
use Gurucomkz\EagerLoading\EagerLoaderMultiAccessor; | ||
|
||
// ... | ||
} | ||
``` | ||
|
||
This trait declares `__call()` method necessary for accessing the eager-loaded data. | ||
|
||
## When you have your own `__call()` method | ||
|
||
If you have your own `__call()`, please put the contents of `EagerLoaderMultiAccessor::__call()` into it: | ||
|
||
```php | ||
class MyClass extends DataObject { | ||
|
||
public function __call($fn, $params) | ||
{ | ||
// Copy contents of EagerLoaderMultiAccessor::__call() here | ||
|
||
// your code goes here | ||
} | ||
} | ||
``` | ||
|
||
If the trait is not included, an exception will be thrown on attempt to use `$has_many`, `$many_many` or `$belongs_meny_many`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Using With `$has_one` | ||
|
||
This type of relations is supported out of the box without any structural modifications. | ||
|
||
Simply add `->with([...relations...])` to the ORM invocation chain when needed. | ||
|
||
```php | ||
MyModelClass::get()->with(['Relation1','Relation2'])->filter(...); | ||
``` | ||
|
||
Once your code starts accessing data from the query, module will load related entries from `Relation1` and `Relation2` with much less queries, than doing that one-by-one as SilverStripe usually does. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Silverstripe EagerLoading | ||
|
||
Module solves the [N+1 problem](https://stackoverflow.com/questions/97197/what-is-the-n1-selects-problem-in-orm-object-relational-mapping) in SilverStripe 4. | ||
|
||
Normally SilverStripe uses Lazy Loading and fetches the required information only when it is actually accessed. | ||
|
||
I.e. | ||
```php | ||
$items = MyModelClass::get(); # no query yet | ||
|
||
foreach ($items as $item) { # makes a DB query for all $items | ||
echo $item->Feature1->Title; # makes DB query for ONE Feature1 | ||
echo $item->Feature2->Title; # makes DB query for ONE Feature2 | ||
foreach ($items->Feature3() as $subitem) { # makes a DB query for ALL Feature3 | ||
echo $subitem->Title; # makes DB query for ONE Feature2 | ||
} | ||
} | ||
``` | ||
With `K` rows in `MyModelClass`, `N` number of relations that are directly accessed every `for` iterations: | ||
`K * (1 + N)` DB queries. | ||
|
||
Using this module the code above can be reduced to `K + N * 3`. | ||
|
||
## Solution | ||
|
||
```php | ||
MyModelClass::get()->with(['Relation1','Relation2'])->filter(...); | ||
``` | ||
|
||
It does not require huge configuration - only one function to be added to the query builder chain : `->with([..relations...])`. | ||
|
||
This will result in the final DataList to be presented by the `EagerLoadedDataList` class that handles the eager loading. | ||
|
||
The module takes advantage of `DataList::getGenerator()` to query for and attach the related records only when needed. | ||
|
||
## Examples | ||
|
||
* [Using with $has_one / $belongs_to](Using_With_HasOne.md) | ||
* [Using with $has_many / $many_many / $belongs_many_many](Using_With_HasMany.md) | ||
* [Boosting GridField output](Boosting_GridField.md) | ||
* [Boosting CSV export](Boosting_CSV_Export.md) |