Laravel BAP, MulitCRM — Creating Relations — Part 2— OneToMany

Laravel BAP is a Modular Backend Application Platform build on top of Laravel 5.6, Twitter Bootstrap and SCSS. The software contains over 20 core features, module generator, relations in tabs. BAP is Easy to extend, customize, developer, can build any back-office application with short time.

You can read more about platforms here:

Tutorial

In previous tutorial we created “ManyToOne” relation that was a Picker in form. Now we are going to create “OneToMany”.

We are going to create List of Tickets in Account module.

List of Tickets in Account — Example of One To Many Relation

im going to use relation created in previous tutorial (if you are creating new relation just go back to this tutorial and follow tutorial). If fact many to one relation is required to create oneToMany.

Creating OneToMany Relation

In this example we need to add list of tickets in account module. for that we need.

  1. Edit Account.php entity and add tickets relation
  2. Add new routes that will bind tickets with account
  3. Create AccountTicketsDatatable.php
  4. Add AccountsTicketsController that will show Datatable in account module.
  5. Modify AccountController and add new created controller.

Looks like lot of work? Nope, in fact, most of this is copy, paste and replace.

  1. Edit Account.php entity and add tickets relation
/**
*
@return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function tickets()
{
return $this->hasMany(Ticket::class);
}

Remember that we already added account() relation in Ticket.php

2. Edit routes.php and add tickets section

Route::get('accounts/tickets-selection/{entityId}', ['as'=>'tickets.selection','uses'=> 'Tabs\AccountsTicketsController@selection']);
Route::get('accounts/tickets-linked/{entityId}', ['as'=>'tickets.linked','uses'=> 'Tabs\AccountsTicketsController@linked']);
Route::post('accounts/tickets-unlink', ['as'=>'tickets.unlink','uses'=> 'Tabs\AccountsTicketsController@unlink']);
Route::post('accounts/tickets-link', ['as'=>'tickets.link','uses'=> 'Tabs\AccountsTicketsController@link']);

explanation

tickets-selection —this link is list of tickets that can be accessible by current logged user.

tickets-linked — this link shows currently linked tickets to account.

tickets-unlink — this link is invoked when user removes ticket from account.

tickets-link — this link will bind ticket with account.

3. Create Datatable

create file Modules\Accounts\Datatables\Tabs\AccountTicketsDatatable.php

<?php

namespace
Modules\Accounts\Datatables\Tabs;

use Modules\Deals\Entities\Deal;
use Modules\Platform\Core\Datatable\RelationDataTable;
use Modules\Platform\Core\Helper\DataTableHelper;
use Modules\Tickets\Entities\Ticket;
use Yajra\DataTables\EloquentDataTable;

/**
* Class AccountTicketsDatatable
*
@package Modules\Accounts\Datatables\Tabs
*/
class AccountTicketsDatatable extends RelationDataTable
{
const SHOW_URL_ROUTE = 'tickets.tickets.show';

protected $unlinkRoute = 'accounts.tickets.unlink';

/**
* Build DataTable class.
*
*
@param mixed $query Results from query() method.
*
@return \Yajra\DataTables\DataTableAbstract
*/
public function dataTable($query)
{
$dataTable = new EloquentDataTable($query);

$this->applyLinks($dataTable, self::SHOW_URL_ROUTE, 'tickets_');

$dataTable->filterColumn('owner', function ($query, $keyword) {
DataTableHelper::queryOwner($query, $keyword);
});

$dataTable->filterColumn('created_at', function ($query, $keyword) {
$dates = DataTableHelper::getDatesForFilter($keyword);

if ($dates != null) {
$query->whereBetween('created_at', array($dates[0], $dates[1]));
}
});
$dataTable->filterColumn('updated_at', function ($query, $keyword) {
$dates = DataTableHelper::getDatesForFilter($keyword);

if ($dates != null) {
$query->whereBetween('updated_at', array($dates[0], $dates[1]));
}
});

return $dataTable;
}

/**
* Get query source of dataTable.
*
*
*
@return \Illuminate\Database\Eloquent\Builder
*/
public function query(Ticket $model)
{
return $model->with('owner')->newQuery()->select();
}

/**
* Optional method if you want to use html builder.
*
*
@return \Yajra\DataTables\Html\Builder
*/
public function html()
{
return $this->builder()
->setTableId('AccountTicketsDatatable' . $this->tableSuffix)
->columns($this->getColumns())
->minifiedAjax(route($this->route, ['entityId' => $this->entityId]))
->setTableAttribute('class', 'table table-hover')
->parameters([
'dom' => 'lBfrtip',
'responsive' => false,
'stateSave' => true,
'columnFilters' => [
[
'column_number' => $this->countFilterColumn(0),
'filter_type' => 'text'
],
[
'column_number' => $this->countFilterColumn(1),
'filter_type' => 'bap_date_range_picker',

],
[
'column_number' => $this->countFilterColumn(2),
'filter_type' => 'bap_date_range_picker',
],
[
'column_number' => $this->countFilterColumn(3),
'filter_type' => 'select',
'select_type' => 'select2',
'select_type_options' => [
'theme' => "bootstrap",
'width' => '100%'
],
'data' => DataTableHelper::filterOwnerDropdown()
]
],
'buttons' => DataTableHelper::buttons(),
'regexp' => true

]);
}

/**
*
@return array
*/
protected function getColumns()
{
$unlink = [
'unlink' => [
'data' => 'unlink',
'title' => '',
'data_type' => 'unlink',
'orderable' => false,
'searchable' => false,

]
];

$check_selection = [
'check_select' => [
'data' => 'check_select',
'title' => '',
'data_type' => 'check_select',
'orderable' => false,
'searchable' => false,
]
];

$columns =
[
'name' => [
'data' => 'name',
'title' => trans('core::core.table.name'),
'data_type' => 'text'
],
'created_at' => [
'data' => 'created_at',
'title' => trans('core::core.table.created_at'),
'data_type' => 'datetime'
],
'updated_at' => [
'data' => 'updated_at',
'title' => trans('core::core.table.updated_at'),
'data_type' => 'datetime'
],
'owner' => [
'data' => 'owner',
'title' => trans('core::core.table.assigned_to'),
'data_type' => 'assigned_to',
'orderable' => false
]
];

if ($this->allowSelect) {
return $check_selection + $columns;
}
if ($this->allowUnlink) {
return $unlink + $columns;
}

return $columns;
}
}

4. Create AccountsTicketsController.php

<?php

namespace
Modules\Accounts\Http\Controllers\Tabs;

use Modules\Accounts\Datatables\Tabs\AccountTicketsDatatable;
use Modules\Accounts\Entities\Account;
use Modules\Platform\Core\Datatable\Scope\BasicRelationScope;
use Modules\Platform\Core\Http\Controllers\ModuleCrudRelationController;
use Modules\Tickets\Entities\Ticket;

/**
* Class AccountsTicketsController
*
@package Modules\Contacts\Http\Controllers
*/
class AccountsTicketsController extends ModuleCrudRelationController
{
protected $datatable = AccountTicketsDatatable::class;

protected $ownerModel = Account::class;

protected $relationModel = Ticket::class;

protected $ownerModuleName = 'accounts';

protected $relatedModuleName = 'tickets';

protected $scopeLinked = BasicRelationScope::class;

protected $modelRelationName = 'tickets';

protected $relationType = self::RT_ONE_TO_MANY;

protected $belongsToName = 'account';
}

explanation

$datatable — linked datatable in our case it’s list of tickets.

$ownerModule — one account can have multiple tickets. So owner is account

$relationModel — other side of relation. In our case Ticket.

$ownerModuleName — name of owner module

$relatedModuleName — name of related module

$scopeLinked = how linked record should be scoped ( look into BasicRelationScope for details) this class scopes tickets to choose only assigned to current account.

$modelRelationName — relation name i owner module.

$relationType = RT_ONE_TO_MANY

$belongsToName — relation name on other side.

5. Final step — Update Account Controller

In AccountController update $relationTabs and add.

'tickets' => [
'icon' => 'report_problem',
'permissions' => [
'browse' => 'tickets.browse',
'update' => 'tickets.update',
'create' => 'tickets.create'
],
'datatable' => [
'datatable' => AccountTicketsDatatable::class
],
'route' => [
'linked' => 'accounts.tickets.linked',
'create' => 'tickets.tickets.create',
'select' => 'accounts.tickets.selection',
'bind_selected' => 'accounts.tickets.link'
],
'create' => [
'allow' => true,
'modal_title' => 'tickets::tickets.create_new',
'post_create_bind' => [
'relationType' => 'oneToMany',
'relatedField' => 'account_id',

]
],

'select' => [
'allow' => true,
'modal_title' => 'tickets::tickets.module'
],
],

explanation

icon — icon that represents relation/module

permissions — permissions required to browse tab

datatabe — datatable that will be displayed here

route — (we defined them before)

create — allow to create new records directly in tab

select — allow to select records and bind them here.

Thats is. We did a lot of work. Is this complicated? Yes and no. For a beginner that can be confusing but i think this aproach gives a lot of flexibility.

You can have whatever data you want in tab, you can bind your code into action. Create any datatable with any data and select and display them in tabs.

On next tutorial we are going to create ManyToMany relation.