Repositories

Depending on the model feature, include one or multiple of these traits: HandleTranslations, HandleSlugs, HandleMedias, HandleFiles, HandleRevisions, HandleBlocks, HandleRepeaters, HandleTags.

Repositories allows you to modify the default behavior of your models by providing some entry points in the form of methods that you might implement:

Filtering

1<?php
2 
3// implement the filter method
4public function filter($query, array $scopes = []) {
5 
6 // and use the following helpers
7 
8 // add a where like clause
9 $this->addLikeFilterScope($query, $scopes, 'field_in_scope');
10 
11 // add orWhereHas clauses
12 $this->searchIn($query, $scopes, 'field_in_scope', ['field1', 'field2', 'field3']);
13 
14 // add a whereHas clause
15 $this->addRelationFilterScope($query, $scopes, 'field_in_scope', 'relationName');
16 
17 // or just go manually with the $query object
18 if (isset($scopes['field_in_scope'])) {
19 $query->orWhereHas('relationName', function ($query) use ($scopes) {
20 $query->where('field', getLikeOperator(), '%' . $scopes['field_in_scope'] . '%');
21 });
22 }
23 
24 // don't forget to call the parent filter function
25 return parent::filter($query, $scopes);
26}

Custom ordering

1<?php
2 
3// implement the order method
4public function order($query, array $orders = []) {
5 // don't forget to call the parent order function
6 return parent::order($query, $orders);
7}

Custom form fields

1<?php
2 
3// implement the getFormFields method
4public function getFormFields($object) {
5 // don't forget to call the parent getFormFields function
6 $fields = parent::getFormFields($object);
7 
8 // get fields for a browser
9 $fields['browsers']['relationName'] = $this->getFormFieldsForBrowser($object, 'relationName');
10 
11 // get fields for a repeater
12 $fields = $this->getFormFieldsForRepeater($object, $fields, 'relationName', 'ModelName', 'repeaterItemName');
13 
14 // return fields
15 return $fields
16}

Custom field preparation before create action

1<?php
2 
3// implement the prepareFieldsBeforeCreate method
4public function prepareFieldsBeforeCreate($fields) {
5 // don't forget to call the parent prepareFieldsBeforeCreate function
6 return parent::prepareFieldsBeforeCreate($fields);
7}

Custom field preparation before save action

1<?php
2 
3// implement the prepareFieldsBeforeSave method
4public function prepareFieldsBeforeSave($object, $fields) {
5 // don't forget to call the parent prepareFieldsBeforeSave function
6 return parent:: prepareFieldsBeforeSave($object, $fields);
7}

After save actions (like attaching a relationship)

1<?php
2 
3// implement the afterSave method
4public function afterSave($object, $fields) {
5 // for exemple, to sync a many to many relationship
6 $this->updateMultiSelect($object, $fields, 'relationName');
7 
8 // which will simply run the following for you
9 $object->relationName()->sync($fields['relationName'] ?? []);
10 
11 // or, to save a oneToMany relationship
12 $this->updateOneToMany($object, $fields, 'relationName', 'formFieldName', 'relationAttribute')
13 
14 // or, to save a belongToMany relationship used with the browser field
15 $this->updateBrowser($object, $fields, 'relationName');
16 
17 // or, to save a hasMany relationship used with the repeater field
18 $this->updateRepeater($object, $fields, 'relationName', 'ModelName', 'repeaterItemName');
19 
20 // or, to save a belongToMany relationship used with the repeater field
21 $this->updateRepeaterMany($object, $fields, 'relationName', false);
22 
23 parent::afterSave($object, $fields);
24}

Hydrating the model for preview of revisions

1<?php
2 
3// implement the hydrate method
4public function hydrate($object, $fields)
5{
6 // for exemple, to hydrate a belongToMany relationship used with the browser field
7 $this->hydrateBrowser($object, $fields, 'relationName');
8 
9 // or a multiselect
10 $this->hydrateMultiSelect($object, $fields, 'relationName');
11 
12 // or a repeater
13 $this->hydrateRepeater($object, $fields, 'relationName');
14 
15 return parent::hydrate($object, $fields);
16}

Duplicating content

When enabling the duplicate feature on your controller the ui will expose a button and row action to duplicate the entry.

By default, the duplicate function will take care of duplicating the following:

  • Base content and translations
  • Blocks and json repeaters
  • Related browsers
  • Media's
  • Files'

It does not duplicate related content such as regular browsers, repeaters and other relations.

This is because we cannot know how to handle these specifically for your project. But we do provide a method you can use to trigger these duplications, if required, after the initial duplications are complete.

To do this, you can override the afterDuplicate method, which receives 2 arguments. One for the old and one for the new model.

Do not forget to include a call to the parent if you want to have the default behaviour.

Example:

1use A17\Twill\Models\Contracts\TwillModelContract;
2 
3class BlogRepository extends ModuleRepository
4{
5 public function afterDuplicate(TwillModelContract $old, TwillModelContract $new): void
6 {
7 parent::afterDuplicate($old, $new);
8 
9 $new->publish_start_date = Carbon::tomorrow();
10 $new->save();
11 }
12}