Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Версия 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>
Не в сети
Ошибку 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">
Не в сети
На сколько я понимая(очень плохо пока в этом всём разбираюсь), js через post должен сам получать разрешение (csrf-token) на переправку данных, а не из формы их брать, как в твоём случае прописанный ключик в ajaxSetup
Не в сети