#php #laravel #laravel-8
Вопрос:
Я хочу, чтобы у пользователя было много продуктов. есть какой-то продукт, который принадлежит одному пользователю. но он показывает array_map(): Аргумент #2 ($array) должен иметь тип array, int с учетом ошибки. я думаю, что в контроллере есть какая-то проблема, но я не могу ее исправить. кто-нибудь, помогите мне. Спасибо, это адвенс, вот мой ProductController.php
<?php
namespace AppHttpControllers;
use AppModelsProduct;
use IlluminateHttpRequest;
use IlluminateSupportFacadesDB;
use AppHttpRequestsAdminStoreTagsRequest;
use AppModelsUser;
use IlluminateSupportFacadesHash;
class ProductController extends Controller
{
/**
* Display a listing of the resource.
*
* @return IlluminateHttpResponse
*/
public function index()
{
$products = Product::latest()->paginate(20);
return view('products.index',compact('products'))
->with('i', (request()->input('page', 5) - 1) * 5);
}
function authapi(Request $request)
{
$user = User:: where('email', $request->email)->first();
if(!$user || !Hash::check($request->password, $user->password)){
return response([
'message' => ['These credentials do not match our records.']
],404);
}
$token = $user -> createToken('my-app-token')->plainTextToken;
$response = [
'user' => $user,
'token' => $token
];
return response($response,201);
}
function all_app_jsons(){
return Product::all();
}
function search_by_name($name){
return Product::where('name','like','%'.$name.'%')->get();
}
function search_by_id($id){
return Product::where('id',$id)->get();
}
/**
* Show the form for creating a new resource.
*
* @return IlluminateHttpResponse
*/
public function create()
{
return view('products.create');
}
/**
* Store a newly created resource in storage.
*
* @param IlluminateHttpRequest $request
* @return IlluminateHttpResponse
*/
public function store(Request $request)
{
//$tag = Product::create($request->all());
//return redirect()->route('admin.tags.index');
$request->validate([
'name' => 'required',
'detail' => 'required',
'color' => 'required',
'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
'logo' => 'required|mimes:jpeg,png,jpg,gif,svg|max:1024',
]);
// $input = $request->all();
$request->validated();
$input['user_id'] = auth()->user()->id;
if ($image = $request->file('image')) {
$destinationPath = 'image/';
$profileImage = date('YmdHis') . "." . $image->getClientOriginalExtension();
$image->move($destinationPath, $profileImage);
$input['image'] = "$profileImage";
}
if ($logo = $request->file('logo')) {
$destinationPath = 'logo/';
$profileLogo = date('YmdHis') . "." . $logo->getClientOriginalExtension();
$logo->move($destinationPath, $profileLogo);
$input['logo'] = "$profileLogo";
}
Product::create($input);
return redirect()->route('products.index')
->with('success','Product created successfully.');
}
/**
* Display the specified resource.
*
* @param AppProduct $product
* @return IlluminateHttpResponse
*/
public function show(Product $product)
{
return view('products.show',compact('product'));
}
/**
* Show the form for editing the specified resource.
*
* @param AppProduct $product
* @return IlluminateHttpResponse
*/
public function edit(Product $product)
{
return view('products.edit',compact('product'));
}
/**
* Update the specified resource in storage.
*
* @param IlluminateHttpRequest $request
* @param AppProduct $product
* @return IlluminateHttpResponse
*/
public function update(Request $request, Product $product)
{
$request->validate([
'name' => 'required',
'detail' => 'required',
'color' => 'required'
]);
$input = $request->all();
if ($image = $request->file('image')) {
$destinationPath = 'image/';
$profileImage = date('YmdHis') . "." . $image->getClientOriginalExtension();
$image->move($destinationPath, $profileImage);
$input['image'] = "$profileImage";
}else{
unset($input['image']);
}
if ($logo = $request->file('logo')) {
$destinationPath = 'logo/';
$profileLogo = date('YmdHis') . "." . $logo->getClientOriginalExtension();
$logo->move($destinationPath, $profileLogo);
$input['logo'] = "$profileLogo";
}else{
unset($input['logo']);
}
$product->update($input);
return redirect()->route('products.index')
->with('success','Product updated successfully');
}
/**
* Remove the specified resource from storage.
*
* @param AppProduct $product
* @return IlluminateHttpResponse
*/
public function destroy(Product $product)
{
$product->delete();
return redirect()->route('products.index')
->with('success','Product deleted successfully');
}
// function indextwo(){
// //return DB::select("select * from products");
// //DB::table('products')->orderBy('id','desc')->first();
// return Product::orderBy('id', 'DESC')->first();
// }
}
вот мой Product.php в качестве модели
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class Product extends Model
{
use HasFactory;
protected $fillable = [
'name', 'detail', 'image','color','logo','user_id'
];
public function user(){
return $this->belongsTo(User::class);
}
}
вот мой user.php в качестве модели
<?php
namespace AppModels;
use IlluminateContractsAuthMustVerifyEmail;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateFoundationAuthUser as Authenticatable;
use IlluminateNotificationsNotifiable;
use LaravelFortifyTwoFactorAuthenticatable;
use LaravelJetstreamHasProfilePhoto;
use LaravelSanctumHasApiTokens;
class User extends Authenticatable
{
use HasApiTokens;
use HasFactory;
use HasProfilePhoto;
use Notifiable;
use TwoFactorAuthenticatable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
'two_factor_recovery_codes',
'two_factor_secret',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* The accessors to append to the model's array form.
*
* @var array
*/
protected $appends = [
'profile_photo_url',
];
public function products(){
return $this->hasMany(Product::class);
}
}
вот моя таблица продуктов
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('detail');
$table->string('color');
$table->string('image');
$table->string('logo');
$table->unsignedBigInteger('user_id');
$table->timestamps();
});
Schema::table('products', function (Blueprint $table){
$table->foreign('user_id')->references('id')->on('users');
});
}
Комментарии:
1. где в вашем коде находится array_map ()?
2. я не знаю. где это должно быть, не могли бы вы мне помочь? я борюсь с ним последние 4 часа
3. Что такое трассировка стека ошибок? Ошибка заключается в том, что вы передаете не массив, когда он ожидает массив. В отчете об ошибках должно быть указано, какая строка из ProductController делает это. Какая линия?
4. он не показывает никакой ошибки в моем ProductController, но он показывает ошибку в ValidationRuleParser.php строка 92
Ответ №1:
Проблема в том, что этот фрагмент кода из вашего ProductController
:
'user_ID' => auth()->user()->id,
Это ошибка, потому что вместо правила проверки у вас есть фактический идентификатор пользователя.
Я предполагаю, что вы хотели, чтобы идентификатор пользователя был текущим идентификатором пользователя, и хотели проверить это, вы можете, но не так.
Если вы хотите быть уверены user_id
, что ваш ввод всегда является аутентифицированным идентификатором пользователя, используйте это:
$input = $request->all();
$input['user_id'] = auth()->user()->id;
Ошибка заключается в том, что идентификатор пользователя , вероятно, является целочисленным значением, если мы посмотрим на код, в котором произошла ошибка ValidationRuleParser:92
, вы увидите, что он проверяет строку и объект и в противном случае передает неизмененное значение array_map
, поскольку вы передаете целое число, оно выдает ошибку, которую вы видите. Немного сложно разобраться, но трассировка стека должна была включать кадр, исходящий от вашего контроллера, в частности $request->validate
вызов.
Хотя технически это не входит в ваш вопрос, я хочу предупредить об использовании $request->all()
, поскольку это потенциально может привести к появлению дополнительных данных, которые передаются в вашу модель без ее проверки или предназначения. Вместо этого используйте $request->validated()
для получения только проверенных значений. Вы также $fillable
установили свои модели, так что это не является непосредственной проблемой, но я бы все равно рекомендовал вводить только проверенные поля на всякий случай $fillable
, если они расширены, но правила проверки не являются таковыми.
Комментарии:
1. спасибо вам большое, это сработало. но я могу оценить один и тот же продукт с разными идентификаторами. Но я хочу, чтобы у идентификатора пользователя были разные продукты, которые нельзя оценить с помощью другого идентификатора. вы можете видеть, что у меня есть код обновления с таблицей продуктов
2. вы можете мне в этом помочь?
3. Это совершенно другой вопрос, верно? Проблема заключалась в методе магазина, который создает продукты и не должен иметь ничего общего с доступом к ним?
4. да, спасибо вам большое, я мучился с этим последние 6 часов, вы помогли мне 🙂 . Но если вы не можете помочь мне с другими, это нормально, спасибо 🙂
5. Я могу, но технически это не по теме для этого вопроса… поэтому я быстро расскажу об этом здесь, но если это не поможет создать новый вопрос. В вашем
update
методе контроллера замените, Product $product
на, $productId
и добавьте в качестве первой строки метода:$product = auth()->user()->products()->findOrFail($productId);
. Это должно гарантировать, что можно редактировать только продукты, принадлежащие аутентифицированному пользователю, в качестве альтернативы проверьте: laravel.com/docs/8.x/routing#implicit-model-binding-scoping (но в зависимости от настройки вашего маршрута это может не сработать для вас).