Каков наилучший способ использовать несколько контроллеров и моделей в Laravel

#laravel #controller #request

#laravel #контроллер #запрос

Вопрос:

У меня есть проект с несколькими контроллерами и моделями. Например, в таблице products есть «дочерняя» таблица (подробная информация о продукте) с именем «producto_material».

Во внешнем интерфейсе пользователь создает новый продукт, но у этого продукта должна быть хотя бы одна деталь. Когда пользователь нажимает «Создать продукт», запрос отправляется с информацией о продукте (products) и подробной информацией о продукте (producto_material).

На данный момент у меня есть следующая структура:

  • Контроллеры (ProductoController, ProductoMaterialController)
  • Модели (ProductoModel, ProductoMaterialModel)

Мне нравится, чтобы каждый контроллер выполнял вашу собственную проверку, но запрос отправляется на ProductController.

Веб-маршруты:

 Route::resource('products', 'ProductoController');
Route::get('duplicar/{param?}', 'ProductoExtController@duplicar');
Route::post('mostrarProductos', 'ProductoExtController@mostrarProductos');
Route::post('guardarValoresEditados', 'ProductoExtController@guardarValoresEditados');
Route::get('imprimirListadoPrecios', 'ProductoExtController@imprimirListadoPrecios');
Route::post('mostrarProductosStickers', 'ProductoExtController@mostrarProductosStickers');
Route::post('imprimirStickers','ProductoExtController@imprimirStickers');
  

Контроллер продукта:

 <?php

namespace AppHttpControllers;

use IlluminateHttpRequest;
use AppModelosProductsModel;
use AppModelosProductoMaterialModel;
use IlluminateSupportFacadesValidator;
use IlluminateSupportArr;
use AppHttpRequestsProductoValidationRules;
use CarbonCarbon;
use IlluminateSupportFacadesDB;
use IlluminateSupportFacadesAuth;


class ProductoController extends Controller
{

    protected $proMaterialesProducto;

    public function __construct(ProductoMaterialController $pMaterialesProducto)
    {
        $this->proMaterialesProducto = $pMaterialesProducto;
    }

    /**
     * Display a listing of the resource.
     *
     * @return IlluminateHttpResponse
     */
    public function index()
    {
        if (Gate::allows('isAdmin') || Gate::allows('isUser')){
            return ProductsModel::latest()
                        ->orderBy('created_at','desc')
                        ->paginate(10);
        }
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return IlluminateHttpResponse
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  IlluminateHttpRequest  $request
     * @return IlluminateHttpResponse
     */
    public function store(ProductoValidationRules $request)
    {   
        $vIntIdProducto = 0;

        try {
            $validated = $request->validated();

            DB::beginTransaction();

            $vIntIdProducto = ProductsModel::insertGetId([
                'f014_nombre' => $request['nombre'],
                'f014_precio_basico'=> $request['vlrBasico'],
                'f014_precio_premium' => $request['vlrPelete'],
                'f014_categoria_id'  => $request['categoria'],            
                'f014_id_coleccion'=> $request['coleccion'],
                'created_at'=> Carbon::now()->toDateTimeString(),     
                'f014_creado_por'=> Auth::id(),
            ]);

            foreach (Arr::get($request,'colores') as $key => $color) {
                ProductoMaterialModel::insert([
                    'f019_producto_id' => $vIntIdProducto,
                    'f019_crosta_id'=> Arr::get($color,'crosta.valor'),
                    'f019_id_folia1' => Arr::get($color,'folia1.valor'),
                    'f019_id_folia2'  => Arr::get($color,'folia2.valor'),          
                    'f019_id_folia3'=> Arr::get($color,'folia3.valor'),
                    'f019_color'=> Arr::get($color,'color'),
                    'f019_creado_por'=> Auth::id(),
                ]);
            }

            DB::commit();

            return response()
            ->json(['status' => true]);

        } catch (Throwable $th) {
            DB::rollBack();
            return response()
            ->json([
                'status' => false,
                'message' => 'Fallo la creación del producto '.$th->getMessage()
            ]);
        }
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return IlluminateHttpResponse
     */
    public function show($id)
    {
        $vProductsModel = ProductsModel::with(
                            'MaterialesCombinaciones.Crostas',
                            'MaterialesCombinaciones.Folia1',
                            'MaterialesCombinaciones.Folia2',
                            'MaterialesCombinaciones.Folia3'
                        )
                        ->where('f014_id',$id)
                        ->get();

        return response()
                ->json($vProductsModel);
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return IlluminateHttpResponse
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  IlluminateHttpRequest  $request
     * @param  int  $id
     * @return IlluminateHttpResponse
     */
    public function update(Request $request, $id)
    {
        $vProductos = null;

        try {
            DB::beginTransaction();

            $vProductos = ProductsModel::find($id);
            $vProductos->f014_precio_basico = $request['vlrBasico'];
            $vProductos->f014_precio_premium = $request['vlrPelete'];
            $vProductos->f014_modificado_por = Auth::id();

            $vProductos->save();

            foreach (Arr::get($request,'colores') as $key => $color) {
                ProductoMaterialModel::updateOrCreate(
                    [
                        'f019_producto_id' => $id, 
                        'f019_crosta_id' => Arr::get($color,'crosta.valor'),
                        'f019_color'=>Arr::get($color,'color')
                    ],
                    [
                        'f019_id_folia1' => Arr::get($color,'folia1.valor'),
                        'f019_id_folia2' =>  Arr::get($color,'folia2.valor'),
                        'f019_modificado_por'=>Auth::id()
                    ]
                );
            }


            DB::commit();
            return response()
            ->json(['status' => true]);
        } catch (Throwable $th) {

            DB::rollBack();
            return response()
            ->json([
                'status' => false,
                'message' => 'Fallo la actualización del producto '.$th->getMessage()
            ]);
        }
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return IlluminateHttpResponse
     */
    public function destroy($id)
    {
        ProductsModel::destroy($id);
    }
}
  

Я думаю, что это неправильно:

  $vIntIdProducto = ProductsModel::insertGetId([
                'f014_nombre' => $request['nombre'],
                'f014_precio_basico'=> $request['vlrBasico'],
                'f014_precio_premium' => $request['vlrPelete'],
                'f014_categoria_id'  => $request['categoria'],            
                'f014_id_coleccion'=> $request['coleccion'],
                'created_at'=> Carbon::now()->toDateTimeString(),     
                'f014_creado_por'=> Auth::id(),
            ]);

            foreach (Arr::get($request,'colores') as $key => $color) {
                ProductoMaterialModel::insert([
                    'f019_producto_id' => $vIntIdProducto,
                    'f019_crosta_id'=> Arr::get($color,'crosta.valor'),
                    'f019_id_folia1' => Arr::get($color,'folia1.valor'),
                    'f019_id_folia2'  => Arr::get($color,'folia2.valor'),          
                    'f019_id_folia3'=> Arr::get($color,'folia3.valor'),
                    'f019_color'=> Arr::get($color,'color'),
                    'f019_creado_por'=> Auth::id(),
                ]);
            }
  

Комментарии:

1. Если пользователь НЕ МОЖЕТ создать ‘ProductoMaterial’ без ‘Producto’, то вам не нужен ProductoMaterialController… Вы просто устанавливаете связь Producto-> hasMany(ProductoMaterial::class), и когда вы сохраняете Producto, вы создаете с ним ProductoMaterial

2. Нет ничего плохого в создании записей Parent Children в одних и тех же контроллерах. Я бы сказал, что это должно быть правильным способом. Единственное, если вы используете движок InnoDB или базу данных, которые поддерживают транзакции, то вам следует использовать ваши вставки в транзакцию DB, чтобы гарантировать, что родительский элемент не сохранит дочерний элемент. Используйте DB::beginTransaction(); перед вставками, DB::commit(); после и DB::rollback(); при перехватывании исключения.