Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 12.10.2019 16:45:36

Помогите реализовать связанные списки с помощью функции jQuery ajax.

Версия  Laravel Framework 5.4.36
Версия PHP 7.1.22
Windows 7 x64
OpenServer

Техническое задание:

Реализовать связанные выпадающие списки с помощью функции jQuery ajax. Есть форма с двумя элементами выпадающих списков Категорий и Подкатегорий.  Список Подкатегории неактивный и пустой. При выборе категории  список Подкатегории должен стать активным и иметь список подкатегорий соответствующих родительской категории.

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

При выборе категории сразу же появляется ошибка (смотрю в консоле)

      POST http://redcat/product/create 404 (Not Found)

и в Network-> Preview

      NotFoundHttpException

Получается, не  найден роут для данного URI и на сервер не отправляется запрос.
Возможно, синтаксис роутов с ошибкой или в скрипте. Как ни проверял/пробовал разные варианты – все никак. Или не совсем понимаю маршрутизацию. Помогите разобраться.

Код:


Routes:

Route::post('admin/products/create', 'Admin\ProductsController@list')->name('products.list'); 

Route::group(['prefix'=>'admin', 'namespace' => 'Admin'], function(){
	Route::get('/', 'DashBoardController@index');
	Route::resource('/categories', 'CategoriesController');
	Route::resource('/subcategories', 'SubcategoriesController');
	//Route::resource('/tags', 'TagsController');
	//Route::resource('/users', 'UsersController');
	Route::resource('/products', 'ProductsController');
	Route::resource('/brands', 'BrandsController');
    Route::resource('/linemodels', 'LineModelsController');
});т

app\Http\Controllers\ProductsController.php

<?php

namespace App\Http\Controllers\Admin;

use App\Product;
use App\Tag;
use App\Category;
use App\Subcategory;
use App\Brand;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use App\Http\Controllers\Controller;

class ProductsController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $products = Product::all();
        return view('admin.products.index', compact(
            'products'
        ));
    }
    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function list(Request $request)
    {
       dd($request->all());
       
       return view('admin.products.create');
    }
    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $categories = Category::pluck('title', 'id')->all();
        $subcategories = Subcategory::pluck('title', 'id')->all();
        $brands = Brand::pluck('title', 'id')->all();

        return view('admin.products.create', compact(
            'categories',
            'subcategories',
            'brands'
        ));
    }
    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        
       // $selectcategory = (int)$_POST['category'];
      // dd($_POST);

        $this->validate($request, [
           'title' => 'required',
           //'price' => 'required|regex:/^\d{0,8}(\.\d{1,2})?$/',
            'category_id' => 'required',
            'subcategory_id' => 'required',
            'brand_id' => 'required',
        /*    'content' => 'required',
            'date' => 'required',
            'image' => 'nullable|image'*/
        ]);
       // $price = $request->price;
      //  $price = $price*2;
  
        $product = Product::add($request->all());
       /* $product->uploadImageProduct($request->file('image'));
        $product->setCategory($request->get('category_id'));
        $product->setTags($request->get('tags'));
        $product->statusToggle($request->get('status'));
        $product->availableToggle($request->get('available'));
        $product->toggleFeatured($request->get('is_featured'));
*/
       // dd($request->all());

        return redirect()->route('products.index');
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        $product = Product::find($id);
        return view('admin.products.edit', compact(
            'product'
        ));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        $this->validate($request, [
            'title' => 'required',
            'price' => 'required|regex:/^\d{0,8}(\.\d{1,2})?$/'
        ]);

        $product = Product::find($id);
        $product->edit($request->all());

        return redirect()->route('products.index');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        Product::find($id)->remove();
        return redirect()->route('products.index');
    }

app\Models\Product.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Cviebrock\EloquentSluggable\Sluggable;
use Illuminate\Support\Fasades\Storage;

class Product extends Model
{
    
	use Sluggable;

	protected $fillable = ['title','price','category_id','subcategory_id','brand_id'];

    public function category()
    {
    	return $this->belongsTo(Category::class);
    }

    public function subcategory()
    {
    	return $this->belongsTo(Subcategory::class);
    }
/*
    public function brand()
    {
    	return $this->hasOne(Brand::class);
    }

    public function linemodel()
    {
    	return $this->hasOne(Linemodel::class);
    }
*/
    public static function add($fields)
    {
    	$product = new static;
    	$product->fill($fields);
    	$product->save();

    	return $product;
    }

    public function edit($fields)
    {
    	$this->fill($fields);
    	$this->save();
    }

    public function remove()
    {
    	$this->delete();
    }

    public function setCategory($id)
    {
    	if($id == null) {return;}

    	$category = Category::find($id);
    	$this->category()->save($category);
    	/*
    	$this->category_id = $id;
    	$this->save();
    	*/
    }

    public function setSubcategory($id)
    {
    	if($id == null) {return;}

    	$subcategory = Subcategory::find($id);
    	$this->subcategory()->save($subcategory);
    	/*
    	$this->category_id = $id;
    	$this->save();
    	*/
    }

    public function getListSubcategoryById()
    {
        $selectcategory = (int)$_POST['category'];

        return $selectcategory;
    }


    public function sluggable()
    {
        return [
            'slug'=> [
                'source'=>'title'
            ]
        ];
    }
}

app\Models\Category.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Cviebrock\EloquentSluggable\Sluggable;

class Category extends Model
{

    use Sluggable;

    protected $fillable = ['title'];

    public function products()
    {
        return $this->hasMany(Product::class);
    }

    public function subcategories()
    {
        return $this->hasMany(SubCategory::class);
    }

    public function brands()
    {
        return $this->hasMany(Brand::class);
    }

    public function linemodel()
    {
        return $this->hasMany(Linemodel::class);
    }

    public function sluggable()
    {
        return [
            'slug'=> [
                'source'=>'title'
            ]
        ];
    }
}

app\Models\Subcategory.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Cviebrock\EloquentSluggable\Sluggable;


class Subcategory extends Model
{
    
    use Sluggable;

    protected $fillable = ['title', 'category_id'];

    public function products()
    {
        return $this->hasMany(Product::class);
    }

    public function brands()
    {
        return $this->belongsToMany(
            Brand::class,
            'subcategory_brand',
            'subcategory_id',
            'brand_id'
        );
    }

    public function category()
    {
    	return $this->belongsTo(Category::class);
    }

    public function linemodel()
    {
        return $this->hasMany(Linemodel::class);
    }
    

    public function sluggable()
    {
        return [
            'slug'=> [
                'source'=>'title'
            ]
        ];
    }
}

script:

$(document).ready(function () {
	$('#category').change(function(){
		var category_id = parseInt($('#category').val());
		console.log(category_id);
		selectSubcategory(category_id);
	});
});

function selectSubcategory(id){
	var subcat = $('#category');
	console.log(id);
	if(id > 0){
		subcat.prop('disabled', false);

		$.ajax({
				url: '/products/create',
				type: 'POST',
				data: 'id',
				success: function(){
					alert('Данные ушли!');
				},
				/*error: function (xhr, ajaxOptions, thrownError) {
			           alert(xhr.status);
			           alert(xhr.responseText);
			           alert(thrownError);
			       }*/
		});

	}
}

resources/views/admin/products/create.blade.php :

    <div class="form-group">
          <label>Категория <span class="star">*</span></label>
            {{Form::select(
                  'category_id',               
                  $categories,
                  null,
                  [
                    'class' => 'form-control select2',
                    'placeholder'=>'Выбирете категорию',
                    'id'=>'category',
                  ])
            }}
        </div>
        <div class="form-group">
          <label>Подкатегория <span class="star">*</span></label>
            {{Form::select(
                  'subcategory_id',               
                  [],
                  null,
                  [
                    'class' => 'form-control select2 ',
                    'placeholder'=>'Выбирете подкатегорию', 
                    'id'=>'subcategory', 
                    'disabled'=> true,
                  ])
            }}
        </div>

Не в сети

#2 12.10.2019 19:44:58

Re: Помогите реализовать связанные списки с помощью функции jQuery ajax.

Ошибку 404 (Not Found) поборол, указав корректный URL в скрипте:
было

url: '/products/create'

стало

url: '/admin/products/create'

Но появилась ошибка 500 (Internal Server Error)  в Laravel  - TokenMismatchException. Добавил в html страницу

 <meta name="csrf-token" content="{{ csrf_token() }}"/>

а в скрипт

 $.ajaxSetup({
	 headers: {
	'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
	 }
	});

странно, ведь подключен Collective\Html\HtmlServiceProvider и он генерирует токен в форме в виде скрытого input

<input name="_token" type="hidden" value="IvypXaU0u4HmsvgLPsB5CfbzlICmAcltTTFvXFpE">

Не в сети

#3 14.10.2019 10:10:05

Re: Помогите реализовать связанные списки с помощью функции jQuery ajax.

На сколько я понимая(очень плохо пока в этом всём разбираюсь), js через post должен сам получать разрешение (csrf-token) на переправку данных, а не из формы их брать, как в твоём случае прописанный ключик в ajaxSetup

Не в сети

Подвал раздела