# Related List

## Definition

A related list allow you to link some records to another one. For example, a customer can be linked to several invoices.

Uccello allows to displayed all related records using `Related Lists`.

You can use 2 types of related lists : **n-1** and **n-n**.

## Related List types

### n-1

A `Related List n-1` in a module, is linked to an `entity` field from another module. To be more explicit, let's take an example: we want to see all **invoices** related to a **customer**.

To be able to link an invoice to a customer you must create an `entity` field into the `customer` module.

```php
// database/migrations/xxxx_xx_xx_xxxxxx_create_invoice_module.php
​
<?php
​
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Uccello\Core\Database\Migrations\Migration;
use Uccello\Core\Models\Field;
...
  
class CreateInvoiceModule extends Migration
{
  public function up()
  {
    ...
    $this->createTable();
    $this->createTabsBlocksFields($module);
  }
  
  protected function createTable()
  {
    Schema::create('invoices', function (Blueprint $table) {
      ...
      $table->unsignedInteger('customer_id')->nullable();
      ...
    });
  }
  
  protected function createTabsBlocksFields($module)
  {
    ...
      
    // Field customer
    $field = Field::create([
        'module_id' => $module->id,
        'block_id' => $block->id,
        'name' => 'customer',
        'uitype_id' => uitype('entity')->id,
        'displaytype_id' => displaytype('everywhere')->id,
        'sequence' => $block->fields()->count(),
        'data' => [ "rules" => "required", "module" => "customer" ] // Linked to the customer module
    ]);
  }
  
  ...
}
```

We will create a `Related List n-1` and link it to the field freshly created.

```php
// database/migrations/xxxx_xx_xx_xxxxxx_create_customer_module.php
​
<?php
​
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Uccello\Core\Database\Migrations\Migration;
use Uccello\Core\Models\Module;
use Uccello\Core\Models\Field;
use Uccello\Core\Models\Relatedlist;
...
  
class CreateCustomerModule extends Migration
{
  public function up()
  {
    ...
    $this->createRelatedLists($module);
  }
  
  protected function createRelatedLists($module)
  {
        $relatedModule = Module::where('name', 'invoice')->first();
​
        Relatedlist::create([
            'module_id' => $module->id,
            'related_module_id' => $relatedModule->id,
            'related_field_id' => $relatedModule->fields->where('name', 'customer')->first()->id, // Retrieve the field created before
            'tab_id' => null,
            'label' => 'relatedlist.invoices', // Will be translated
            'type' => 'n-1',
            'method' => 'getDependentList',
            'sequence' => $module->relatedlists()->count(),
            'data' => [ 'actions' => [ 'add' ] ]
        ]);
  }
  
  ...
}
```

Don't forget to add the new translation:

```php
// resources/lang/en/customer.php
​
return [
  ...
  'relatedlist' => [
    'invoices' => 'Invoices',
  ],
];
```

Now, if you visit a customer record, a new tab will display all the invoices related to it. You can create new ones and they will be directly linked to the customer.

### n-n

A `Related List n-n` allows to link a same record to others records from different modules. To be more explicit, let's take an example: we want to link several **documents** to several **customers**.

To be able to do this we need to create an association table:

```php
// database/migrations/xxxx_xx_xx_xxxxxx_create_rl_customers_documents_table.php
​
<?php
​
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
​
class CreateRlCustomersDocumentsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('rl_customers_documents', function (Blueprint $table) {
            $table->increments('id');
            $table->unsignedInteger('customer_id');
            $table->unsignedInteger('document_id');
            $table->timestamps();
​
            // Foreign keys
            $table->foreign('customer_id')
                    ->references('id')->on('customers')
                    ->onDelete('cascade');
​
            $table->foreign('document_id')
                    ->references('id')->on('documents')
                    ->onDelete('cascade');
        });
    }
​
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('rl_customers_documents');
    }
}
​
```

We will create a `Related List n-n`:

```php
// database/migrations/xxxx_xx_xx_xxxxxx_create_customer_module.php
​
<?php
​
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Uccello\Core\Database\Migrations\Migration;
use Uccello\Core\Models\Module;
use Uccello\Core\Models\Field;
use Uccello\Core\Models\Relatedlist;
...
  
class CreateCustomerModule extends Migration
{
  public function up()
  {
    ...
    $this->createRelatedLists($module);
  }
  
  protected function createRelatedLists($module)
  {
    ...
      
    $documentModule = Module::where('name', 'document')->first();
    Relatedlist::create([
      'module_id' => $module->id,
      'related_module_id' => $documentModule->id,
      'tab_id' => null,
      'label' => 'relatedlist.documents', // Will be translated
      'type' => 'n-n',
      'method' => 'getRelatedList',
      'sequence' => $module->relatedlists()->count(),
      'data' => [ 'actions' => [ 'add', 'select' ] ]
    ]);
  }
  
  ...
}
```

Don't forget to add the new translation:

```php
// resources/lang/en/customer.php
​
return [
  ...
  'relatedlist' => [
    ...
    'documents' => 'Documents',
  ],
];
```

Now we'll configure the models:

```php
// app/Customer.php
​
<?php
​
namespace App;
​
use Uccello\Core\Database\Eloquent\Model;
...
​
class Customer extends Model
{
  public function documents()
    {
        return $this->belongsToMany(Document::class, 'rl_customers_documents')->withTimestamps();
    }
}
```

```php
// app/Document.php
​
<?php
​
namespace App;
​
use Uccello\Core\Database\Eloquent\Model;
...
​
class Document extends Model
{
  public function customers()
    {
        return $this->belongsToMany(Customer::class, 'rl_customers_documents')->withTimestamps();
    }
}
```

Now, if you visit a customer record, a new tab will display all the document related to it. You can select existant documents to link to the record or create new ones.

## Options

#### Display in a Tab or a Block?

By default, a Related List is displayed in a Tab. If you prefer, you can display it in an existant tab. The Related List will be displayed like a new block at the bottom of the page.

To do this, simply fill in `tab_id` with a valid tab's id from the current module.

```php
protected function createRelatedLists($module)
{
    $documentModule = Module::where('name', 'document')->first();
    Relatedlist::create([
      'module_id' => $module->id,
      'related_module_id' => $documentModule->id,
      'tab_id' => $module->tabs->first()->id, // The Related List will be displayed as a new block in the first tab
      'label' => 'relatedlist.documents', // Will be translated
      'type' => 'n-n',
      'method' => 'getRelatedList',
      'sequence' => $module->relatedlists()->count(),
      'data' => [ 'actions' => [ 'add', 'select' ] ]
    ]);
}
```

## Properties

| Attribute               |  Type  | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | Default |
| ----------------------- | :----: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-----: |
| **module\_id**          |   int  | Id of the source module in with display the related list.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |         |
| **related\_module\_id** |   int  | Id of the target module to which the related list points.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |         |
| **related\_field\_id**  |   int  | Only for a `n-1` related list. Id of the [entity](../../uitypes-displaytypes/default-uitypes#entity) field related to the source module.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |  `null` |
| **tab\_id**             |   int  | Id of the tab in which display the related list. If it is null, Uccello displays the related list in a new tab of the Detail View.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |  `null` |
| **label**               | string | Related list's name. It can be translated if you add the translation in the module localization file.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |         |
| **type**                | string | <p>Type of the related list.</p><p><code>n-1</code> or <code>n-n</code>.</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |         |
| **method**              | string | <p>Method to use for retrieving the related records.</p><p>By default, set <code>getDependentList</code> for a <code>n-1</code> related list and <code>getRelatedList</code> for a <code>n-n</code> one.</p><p>Theses methods are defined in the <a href="https://github.com/uccellolabs/uccello/blob/master/app/Support/Traits/RelatedlistTrait.php">RelatedlistTrait</a>.</p><p>To use your own method please refer to the example below.</p>                                                                                                                                                                                                                                                                                                                                                                        |         |
| **sequence**            |   int  | The display sequence for ordering related lists.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |         |
| **data**                |  array | <p>Useful to pass some settings params.</p><p></p><p>By default you can use the following structure:</p><p>[</p><p>  'actions' => [</p><p>    'add',</p><p>    'select'</p><p>  ]</p><p>]</p><p></p><p>This parameter allows to configure the buttons you want to display in the related list.</p><p></p><p><strong>select:</strong> The user can select a record if he has the <code>retrieve</code> capability on the related module.</p><p><strong>add:</strong> The user can create a new related record if he has the <code>create</code> capability on the related module.</p><p></p><p>You can adapt the contains of <code>actions</code> to use 0, 1 or 2 buttons (e.g. <code>[ 'actions' => [ 'add'] ]</code>).</p><p>If you don't want to display action buttons, simply let <code>actions</code> empty.</p> |  `null` |

{% hint style="info" %}
You can create your own method for retrieving the related records. To do this you have to create 2 functions in the model in which add the related list.

* `myOwnMethod`: You can use the name of you want
* `myOwnMethodCount`: The same name as the method above, suffixed by `Count`
{% endhint %}

#### Example

```php
<?php

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Uccello\Core\Models\Relatedlist;
use Uccello\Core\Support\Traits\UccelloModule;

class Person extends Model
{
    use UccelloModule;

    ...

    /**
     * Retrieves related records for n-n relations
     *
     * @param Relatedlist $relatedList
     * @param integer $recordId
     * @param Builder|null $query
     * @param int $start
     * @return Collection
     */
    public function myOwnMethod(Relatedlist $relatedList, int $recordId, ?Builder $query = null)
    {
        $modelClass = $relatedList->module->model_class;
        $relationName = $relatedList->relationName;
    
        $record = $modelClass::find($recordId);
        $filter = ['order' => request('order')];
    
        $query = $record->$relationName()
                        ->filterBy($filter);
    
        return $query;
    }
    
    /**
     * Counts related records for n-n relations
     *
     * @param Relatedlist $relatedList
     * @param integer $recordId
     * @return int
     */
    public function myOwnMethodCount(Relatedlist $relatedList, int $recordId) : int
    {
        return $this->myOwnMethod($relatedList, $recordId)->count();
    }
}
```
