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

Что я сделал

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

Чтобы лучше объяснить себя на примере, у меня была страница CRUD «Заметка», в которой обрабатывались заметки внутри «Билета». Билет и Примечание являются двумя отдельными объектами 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

То, что я ожидал, произойдет

Я ожидал увидеть часть «Показать» одного конкретного тикета на странице «Создание» NoteCrud.

Что произошло

Данные тикета перезаписывают данные Note на странице CRUD(потому что объект CrudPanel теперь обрабатывается как одноэлементный?) и страница создания возвращает ошибку, поскольку она пытается получить доступ к полям и методам Note через Ticket.

То, что я уже пытался исправить,

Я поместил новые команды, расположенные внутри __construct () CrudController, в метод SetupRelated, который находится внутри моей пользовательской особенности RelatedCrud.

Рюкзак, Laravel, PHP, версия БД

КогдаЯ бегу php artisan backpack:version вывод:

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.
...