Как я могу иметь несколько объектов CRUD на одной странице? [Рюкзак 4.0]

Что я сделал

Когда я использовал Backpack 3.6, я создал трейт под названием RelatedCrud и настроил все так, чтобы на одной странице было несколько CRUD.

Чтобы лучше объяснить себя на примере, у меня была страница CRUD "Заметка", которая обрабатывала заметки внутри "Заявки". Ticket и Note - две отдельные сущности CRUD. Путем изменения представлений и создания черты мне удалось поместить часть "Показать" одного конкретного тикета на страницу "Создать" заметки. Страница создания заметки в основном содержала как отображение конкретного тикета, так и форму, которую я мог использовать для создания новой заметки.

Раньше он работал в версии 3.6, но теперь, когда я перешел на версию 4.0, этого не произошло. Это потому, что CrudPanel теперь синглтон? Что я мог сделать, чтобы это заработало?

Вот что я сделал:

NoteTicketCrudController:

<?php

namespace App\Http\Controllers\Admin;

use Route;

class NoteTicketCrudController extends TicketCrudController
{
    public function setup()
    {
        parent::setup();
        $this->crud->removeButton('reply_button');
        $this->crud->removeButton('note_button');
        $this->crud->denyAccess('delete');
        $this->crud->denyAccess('create');
        $this->crud->denyAccess('update');
        // get the user_id parameter
        $noteId = Route::current()->parameter('note') ?: Route::current()->parameter('note_id');
        // set a different route for the admin panel buttons
        $this->crud->setRoute("admin/notes/".$noteId."/tickets");
        // show only that user's posts
        $this->crud->addClause('whereHas', 'notes', function ($query) use($noteId) {
            $query->where('id', $noteId);
        });

        $this->crud->setColumnDetails('subject', ['limit' => '1000']);

        $this->crud->addColumn([
                'name'  => 'description',
                'label' => 'Messaggio',
                'type'  => 'text',
                'limit' => 1000
        ])->afterColumn('subject');

        $this->crud->addColumn([
                // run a function on the CRUD model and show its return value
                'name' => "history_info",
                'label' => "",
                'type' => 'closure',
                'function' => function ($entry) {
                    return $entry->getHistoryView();
                }
        ]);
    }
}

RelatedCrud:

<?php

namespace App\Traits;

use Backpack\CRUD\app\Http\Controllers\CrudController;

trait RelatedCrud
{
    public $relatedCrud;

    public function setupRelated(CrudController $relatedController)
    { 

        $relatedController->crud = app()->make('crud'); // 4.0
        $relatedController->request = request();
        $relatedController->setupDefaults(); // 4.0
        $relatedController->setup(); 
        $relatedController->setupConfigurationForCurrentOperation(); // 4.0
        $this->relatedCrud = $relatedController->crud;
    }
}

NoteCrudController:

class NoteCrudController extends CrudController
{
    use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
    use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation   { show as traitShow; }
    use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation { store as traitStore; create as traitCreate; }
    use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation { edit as traitEdit; update as traitUpdate; }
    use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation { destroy as traitDestroy; }
    use AccessManager;
    use RelatedCrud;

    public $ticket;

    public function setup()
    {
        /*
        |--------------------------------------------------------------------------
        | CrudPanel Basic Information
        |--------------------------------------------------------------------------
        */
        $this->crud->setModel('App\Note');
        $this->crud->setRoute(config('backpack.base.route_prefix') . '/notes');
        $this->crud->setEntityNameStrings('note', 'note');

        //imposta il controller usato per mostrare la tabella dei ticket nel metodo show
        $this->setupRelated(new NoteTicketCrudController()); // LOADS SECOND CRUD

        /*
        |--------------------------------------------------------------------------
        | CrudPanel Configuration
        |--------------------------------------------------------------------------
        */

        $this->setPermissions();

        $this->ticket = $this->crud->request->ticket ? Ticket::find($this->crud->request->ticket) : null; // GETS TICKET ID BASED ON GET REQUEST

[...]

public function create()
    {
        if(!$this->ticket) {
            throw new AccessDeniedException(trans('backpack::crud.unauthorized_access', ['access' => 'create']));
        }
        $this->hasAccessToEntryOrFail('create', null);

        $this->crud->hasAccessOrFail('create');
        // $this->crud->setOperation('create');

        // prepare the fields you need to show
        $this->data['crud'] = $this->crud;
        if($this->ticket) {      // GETS TICKET AND SAVES ITS DATA IN RELATEDCRUD FIELD
            $this->data['relatedCrud'] = $this->relatedCrud;
            $this->data['entry'] = $this->data['relatedCrud']->getEntry($this->ticket->id);
        }
        $this->data['saveAction'] = $this->crud->getSaveAction();
         // $this->data['fields'] = $this->crud->getCreateFields();
        $this->data['title'] = $this->crud->getTitle() ?? trans('backpack::crud.add').' '.$this->crud->entity_name;

        // load the view from /resources/views/vendor/backpack/crud/ if it exists, otherwise load the one in the package
        return view($this->crud->getCreateView(), $this->data);
    }

Маршруты \ рюкзак \custom.php:

Route::group([
    'prefix'     => config('backpack.base.route_prefix', 'admin'),
    'middleware' =>  ['web', config('backpack.base.middleware_key', 'admin')],
    'namespace'  => 'App\Http\Controllers\Admin',
], function () { // custom admin routes
    Route::get('/dashboard', 'DashboardController@dashboard')->name('backpack.dashboard');
    Route::get('/', 'DashboardController@redirect')->name('backpack');
    Route::crud('tickets', 'TicketCrudController');
    Route::crud('notes', 'NoteCrudController');
    Route::group(['prefix' => 'notes/{note_id}'], function() {
        Route::crud('tickets', 'NoteTicketCrudController');
    });
});

Create.blade.php:

@extends(backpack_view('layouts.top_left'))

@php
  $defaultBreadcrumbs = [
    trans('backpack::crud.admin') => url(config('backpack.base.route_prefix'), 'dashboard'),
    $crud->entity_name_plural => url($crud->route),
    trans('backpack::crud.preview') => false,
  ];

  // if breadcrumbs aren't defined in the CrudController, use the default breadcrumbs
  $breadcrumbs = $breadcrumbs ?? $defaultBreadcrumbs;
@endphp

@section('header')
    <section class="container-fluid">
      <h2>
        <span class="text-capitalize">{!! $crud->getHeading() ?? $crud->entity_name_plural !!}</span>
        <small>{!! $crud->getSubheading() ?? trans('backpack::crud.add').' '.$crud->entity_name !!}.</small>

        @if ($crud->hasAccess('list'))
          <small><a href="{{ url($crud->route) }}" class="hidden-print font-sm"><i class="fa fa-angle-double-left"></i> {{ trans('backpack::crud.back_to_all') }} <span>{{ $crud->entity_name_plural }}</span></a></small>
        @endif
      </h2>
    </section>
@endsection

@section('content')
@if(!empty($relatedCrud))
<div class="row">
    <div class="{{ $relatedCrud->getShowContentClass() }}">
    <!-- Default box -->
        <div class="">
            @if ($relatedCrud->model->translationEnabled())
            <div class="row">
                <div class="col-md-12 mb-2">
                    <!-- Change translation button group -->
                    <div class="btn-group float-right">
                    <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        {{trans('backpack::crud.language')}}: {{ $relatedCrud->model->getAvailableLocales()[$relatedCrud->request->input('locale')?$relatedCrud->request->input('locale'):App::getLocale()] }} &nbsp; <span class="caret"></span>
                    </button>
                    <ul class="dropdown-menu">
                        @foreach ($relatedCrud->model->getAvailableLocales() as $key => $locale)
                            <a class="dropdown-item" href="{{ url($relatedCrud->route.'/'.$entry->getKey()) }}?locale={{ $key }}">{{ $locale }}</a>
                        @endforeach
                    </ul>
                    </div>
                </div>
            </div>
            @else
            @endif
            <div class="card no-padding no-border">
                <table class="table table-striped mb-0">
                    <tbody>
                    <?php $i = 0 ?>
                    @foreach ($relatedCrud->columns() as $column)
                    @if($column['name'] != 'history_info')
                    @if($column['name'] != 'priority' && $column['name'] != 'description')
                        @if($i % 2 == 0)
                        <tr>
                        @endif
                            <td style="width:15%;">
                                <strong>{!! $column['label'] !!}</strong>
                            </td>
                            <td style="width:35%;">
                                @if (!isset($column['type']))
                                    @include('crud::columns.text')
                                @else
                                    @if(view()->exists('vendor.backpack.crud.columns.'.$column['type']))
                                        @include('vendor.backpack.crud.columns.'.$column['type'])
                                    @else
                                        @if(view()->exists('crud::columns.'.$column['type']))
                                            @include('crud::columns.'.$column['type'])
                                        @else
                                            @include('crud::columns.text')
                                        @endif
                                    @endif
                                @endif
                            </td>
                        @if($i % 2 == 1)
                        </tr>
                        @endif
                        <?php $i++; ?>
                        @endif
                    @endif
                    @endforeach
                    @if (count($relatedCrud->columns()) % 2 == 1)
                    </tr>
                    @endif
                </tr>
                    </tbody>
                </table>
                <table class="table table-striped mb-0">
                        <tbody>
                @foreach($relatedCrud->columns() as $column)

            @if($column['name'] == 'history_info' || $column['name'] == 'description')

                    <tr>
                    <td style="width:100%;">
                            @if($column['name'] == 'description')

                                    <strong>{!! $column['label'] !!}</strong><br>

                            @endif
                        @if (!isset($column['type']))
                            @include('crud::columns.text')
                        @else
                            @if(view()->exists('vendor.backpack.crud.columns.'.$column['type']))
                                @include('vendor.backpack.crud.columns.'.$column['type'])
                            @else
                                @if(view()->exists('crud::columns.'.$column['type']))
                                    @include('crud::columns.'.$column['type'])
                                @else
                                    @include('crud::columns.text')
                                @endif
                            @endif
                        @endif
                    </td>
                    </tr>
                    @endif
                @endforeach
                        </tbody>
                </table>
            </div><!-- /.box-body -->
        </div><!-- /.box -->

    </div>
</div>
@endif

<div class="row m-t-20">
    <div class="{{ $crud->getCreateContentClass() }}">
        <!-- Default box -->

        @include('crud::inc.grouped_errors')

          <form method="post"
                action="{{ url($crud->route) }}"
                @if ($crud->hasUploadFields('create'))
                enctype="multipart/form-data"
                @endif
                >
          {!! csrf_field() !!}

            <div class="row display-flex-wrap">
              <!-- load the view from the application if it exists, otherwise load the one in the package -->
              @if(view()->exists('vendor.backpack.crud.form_content'))
                @include('vendor.backpack.crud.form_content', [ 'fields' => $crud->getFields('create'), 'action' => 'create' ])
              @else
                @include('crud::form_content', [ 'fields' => $crud->getFields('create'), 'action' => 'create' ])
              @endif
            </div><!-- /.box-body -->
                @include('crud::inc.form_save_buttons')
          </form>
    </div>
</div>

@endsection

Что я ожидал случиться

I expected to see the "Show" part of one particular ticket inside the NoteCrud's "Create" page.

What happened

The Ticket data overwrite the Note data inside the CRUD page (because the CrudPanel object is now treated as a singleton?) and the create page returns an error because it tries to access Note's fields and methods through Ticket.

What I've already tried to fix it

I've put the new commands located inside the CrudController's __construct() into the SetupRelated method which is inside my custom RelatedCrud trait.

Backpack, Laravel, PHP, DB version

When I run php artisan backpack:version the output is:

laravel/framework                     v5.8.35            The Laravel Framework.
backpack/crud                         4.0.5              Quickly build an admin interfaces using Laravel 6, CoreUI, Boostrap 4 and jQuery.
backpack/generators                   2.0.4              Generate files for laravel projects
backpack/permissionmanager            5.0.0              Users and permissions management interface for Laravel 5 using Backpack CRUD.

0 ответов

Другие вопросы по тегам