I'm getting this errorarray_map(): Argument #2 should be an array when a user trying to create a product
I changed my code from this solutions How to make each authenticated user only see their own product, and now it gives me that error.
ProductController
class productController extends Controller
{
public function index(Request $request)
{
$userId = $request->user()->id;
$products = products_model::where('user_id', $userId)->get();
return view('seller.product.index',compact('products'));
}
public function create()
{
return view('seller.product.create');
}
public function seller()
{
$products=products_model::all();
return view('seller.product.index',compact('products'));
}
public function store(Request $request)
{
$formInput=$request->except('image');
$this->validate($request, [
'pro_name'=> 'required',
'pro_price'=> 'required',
'pro_info'=> 'required',
'user_id' => \Auth::id(),
'image'=>'image|mimes:png,jpg,jpeg|max:10000'
]);
$image=$request->image;
if($image){
$imageName=$image->getClientOriginalName();
$image->move('images', $imageName);
$formInput['image']=$imageName;
}
products_model::create($formInput);
return redirect()->back();
}
public function show($id)
{
//
}
public function edit($id)
{
//
}
public function update(Request $request, $id)
{
//
}
public function destroy($id)
{
$userId = $request->user()->id();
$deleteData=products_model::where('user_id', $userId)->findOrFail($id);
$deleteData->delete();
return redirect()->back();
}
}
Products_model
class products_model extends Model
{
protected $table='products';
protected $primaryKey='id';
protected $fillable= ['user_id','pro_name','pro_price','pro_info','image','stock','category_ id'];
}
Products table
class CreateProductsTable extends Migration
{
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('pro_name');
$table->integer('pro_price');
$table->text('pro_info');
$table->integer('stock');
$table->string('image')->nullable();
$table->timestamps();
$table->bigInteger('user_id')->unsigned()->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
public function down()
{
Schema::dropIfExists('products');
}
}
After updating my code now am getting this errorSQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a default value (SQL: insert intoproducts(pro_name,pro_price,stock,pro_info,i`
Change your validate function. Instead of use $this->validate(),
use $request->validate() method:
$request->validate([
'pro_name'=> 'required',
'pro_price'=> 'required',
'pro_info'=> 'required',
'user_id' => 'required|integer',
'image'=>'image|mimes:png,jpg,jpeg|max:10000'
]);
If the validation rules pass, your code will keep executing normally; however, if validation fails, an exception will be thrown and the proper error response will automatically be sent back to the user.
Another solution:
Add
use Validator;
to your class.
$validator = Validator::make($request->all(), [
'pro_name'=> 'required',
'pro_price'=> 'required',
'pro_info'=> 'required',
'user_id' => 'required|integer',
'image'=>'image|mimes:png,jpg,jpeg|max:10000'
]);
if($validator->fails()){
//Validation does not pass logic here
}else{
//
}
One more:
Create a form request, with
php artisan make:request RequestName
The file will be created in app\Http\Requests directory.
Within the file, add your rules to the rules method:
public function rules()
{
return [
'pro_name'=> 'required',
'pro_price'=> 'required',
'pro_info'=> 'required',
'user_id' => 'required|integer',
];
}
Change the authorize method, to return true:
public function authorize()
{
return true;
}
In your store method, swap the Request $request with RequestName $request.
Now you don't need to validate the $request inside store method. It will go to store only if the validation succeed;
Your store method now should looks like
public function store(RequestName $request)
{
$formInput=$request->except('image');
$image=$request->image;
if($image){
$imageName=$image->getClientOriginalName();
$image->move('images', $imageName);
$formInput['image']=$imageName;
}
products_model::create(array_merge(
$formInput, ['user_id' => Auth::user()->id]
));
return redirect()->back();
}
Dont forget to use App\Http\Requests\RequestName
If validation fails, a redirect response will be generated to send the user back to their previous location. The errors will also be flashed to the session so they are available for display. If the request was an AJAX request, a HTTP response with a 422 status code will be returned to the user including a JSON representation of the validation errors.
You can learn more about request validation here.
[EDIT]
I change the users_id rule to user_id, to match with your foreign key name.
I think you made a typo here when you asked the question.
Hope it helps.
Related
Below is some method in a trait AuthenticatesUsers where Illuminate\Foundation\Auth, Laravel.
...
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required|string',
'password' => 'required|string',
]);
}
...
public function username()
{
return 'email';
}
Originally, my goal is to make another login form with user_id and password in mobile device, so this will check Auth() and if success, it will work some method and automatically logout after then. could you tell me detailed advice?
Additional question.
as Jaskaran Singh's advice I added it also as below.
protected function authenticated(Request $request, $user)
{
if($request->Inn == 'Inn') {
return redirect()->route('mobiles_start', ['Inn' => 'Inn']);
}
elseif($request->Ut == 'Ut') {
return redirect()->route('mobiles_destroy', ['Ut' => 'Ut']);
}
return view('welcome');
}
but if login failed, then it is redirected back to the /login page instead of expected view page that pre defined in the route(mobiles_start and mobiles_destroy) above.
How could I do?
You can login with User ID like this:
if(Auth::loginUsingId($user->id)){
return response()->json(['success' => $user], $this->successStatus);
}
You don't have to extend the core trait or any core Laravel code.
in app/Http/Controllers/Auth/LoginController.php add the following functions, this will override the default functions in AuthenticatesUsers trait.
add username() function
public function username()
{
if(request('id')){
return 'id'; // if request contains id then return it
}
return 'email'; // else return email
}
add validateLogin() function
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required', //remove |string
'password' => 'required|string',
]);
}
that's it.
I have custom validation for validating data. The custom validation doesn't have unique rule as I need to ignore this on update, therefore I am using unique rule on store() method. But this is ignored, and it only works if I change the custom validation with default validation.
It works if I have the following:
public function store(Request $request)
{
if (!$this->user instanceof Employee) {
return response()->json(['error' => 'Unauthorized'], 401);
}
$request->validate([
'name' => 'required|max:50|unique:centers'
]);
$center = Center::create($request->all());
return response()->json($center, 201);
}
But this doesn't work if I change the method signature to the following:
public function store(CustomValidation $request)
How can I use both together? I do not want to move the custom validation code inside the method as I have to repeat msyelf for update method then.
I think it will help you
use Illuminate\Contracts\Validation\Rule;
class CowbellValidationRule implements Rule
{
public function passes($attribute, $value)
{
return $value > 10;
}
public function message()
{
return ':attribute needs more cowbell!';
}
}
and
public function store()
{
// Validation message would be "song needs more cowbell!"
$this->validate(request(), [
'song' => [new CowbellValidationRule]
]);
}
or
public function store()
{
$this->validate(request(), [
'song' => [function ($attribute, $value, $fail) {
if ($value <= 10) {
$fail(':attribute needs more cowbell!');
}
}]
]);
}
What I did:
I am trying to override backpack form validation roles (update request).
UserUpdateCrudRequest.php
use App\Http\Requests\Backpack\PermissionManager\UserUpdateCrudRequest as UpdateRequest;
class UserUpdateCrudRequest extends \Backpack\PermissionManager\app\Http\Requests\UserUpdateCrudRequest
{
function __construct()
{
parent::__construct();
}
public function authorize()
{
// only allow updates if the user is logged in
return \Auth::check();
}
public function rules()
{
$rules = [
'name' => 'required',
'password' => 'confirmed',
];
return $rules;
}
}
app/Http/Controllers/Admin/Backpack/PermissionManager/UserCrudController.php
public function update(UpdateRequest $request)
{
//code
}
What I expected to happen:
The email field is mandatory on create , and not mandatory on update.
What happened:
ErrorException in UserCrudController.php line 18:
Declaration of App\Http\Controllers\Admin\Backpack\PermissionManager\UserCrudController::update() should be compatible with Backpack\PermissionManager\app\Http\Controllers\UserCrudController::update(Backpack\PermissionManager\app\Http\Requests\UserUpdateCrudRequest $request)
If I'm right,
inside UserCrudController you have,
use Backpack\PermissionManager\app\Http\Requests\UserStoreCrudRequest as StoreRequest;
use Backpack\PermissionManager\app\Http\Requests\UserUpdateCrudRequest as UpdateRequest;
If you want to make the email field not mandatory on update you have to edit the UserUpdateCrudRequest.php inside your-project/vendor/backpack/permissionmanager/src/app/Http/Requests and remove the line
'email' => 'required',
I want to change the redirect path when the Registration fails in Laravel 5.3 right it redirects to the previous page but I want to change it and I can't find out where.
Here is the RegisterController
<?php
use RegistersUsers;
protected $redirectTo = '/';
public function __construct()
{
$this->middleware('guest');
}
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|max:255|min:6',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
]);
}
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
?>
And here is the RegistersUsers trait
<?php
use RedirectsUsers;
public function showRegistrationForm()
{
return view('auth.register');
}
public function register(Request $request)
{
$this->validator($request->all())->validate();
event(new Registered($user = $this->create($request->all())));
$this->guard()->login($user);
return $this->registered($request, $user)
?: redirect($this->redirectPath());
}
protected function guard()
{
return Auth::guard();
}
protected function registered(Request $request, $user)
{
}
?>
Is there any ideas on how to achieve that, because I want to make a register Modal on the home page, and since it's a modal the user can't see the errors until he opens the registration Modal again, I want to make the **Failed Registration attempts ** always redirects to /register.
Thank you for helping
Override the RedirectsUsers register function in RegisterController as following.
public function register(Request $request) {
$this->validator($request->all())->validate();
$user = $this->create($request->all());
if(empty($user)) { // Failed to register user
redirect('/register'); // Wherever you want to redirect
}
event(new Registered($user));
$this->guard()->login($user);
// Success redirection - which will be attribute `$redirectTo`
redirect($this->redirectPath());
}
I have 3 models: Priority, Task and User
Priority
can be assigned to many tasks
belongs to one user
Code ...
class Priority extends Model
{
protected $fillable = ['name', 'hexcolorcode'];
protected $casts = [
'user_id' => 'int',
];
public function task()
{
return $this->hasMany(Task::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
Task
has one priority assigned
belongs to one user
Code ...
class Task extends Model
{
protected $fillable = ['name'];
protected $casts = [
'user_id' => 'int',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function priority()
{
return $this->hasOne(Priority::class);
}
}
User
can have many tasks
can have many priorities
Code ...
class User extends Authenticatable
{
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
public function tasks()
{
return $this->hasMany(Task::class);
}
public function priorities()
{
return $this->hasMany(Priority::class);
}
}
TaskController
class TaskController extends Controller
{
protected $tasks;
private $priorities;
public function __construct(TaskRepository $tasks, PriorityRepository $priorities)
{
$this->middleware('auth');
$this->tasks = $tasks;
$this->priorities = $priorities;
}
public function index(Request $request)
{
return view('tasks.index', [
'tasks' => $this->tasks->forUser($request->user()),
'priorities' => $this->priorities->forUser($request->user())
]);
}
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255',
'description' => 'required',
'priority' => 'required'
]);
$request->user()->tasks()->create([
'name' => $request->name,
'description' => $request->description,
'priority_id' => $request->priority
]);
return redirect('/tasks');
}
public function edit(Task $task)
{
$this->authorize('edit', $task);
return view('tasks.edit', compact('task'));
}
public function update(Request $request, Task $task)
{
$this->validate($request, [
'name' => 'required|max:255',
]);
$task->update($request->all());
return redirect('/tasks');
}
public function destroy(Request $request, Task $task)
{
$this->authorize('destroy', $task);
$task->delete();
return redirect('/tasks');
}
}
Error
Now when I want to store a task it gives me following error:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or
update a child row: a foreign key constraint fails (tasks.tasks,
CONSTRAINT tasks_priority_id_foreign FOREIGN KEY (priority_id)
REFERENCES priorities (id)) (SQL: insert into tasks (name,
user_id, updated_at, created_at) values (test task, 1,
2016-05-01 14:11:21, 2016-05-01 14:11:21))
Is it possible with this construct or do I have to use Polymorphic Relations between priority table and tasks table?
My Tables
Database Model Picture: http://picpaste.de/mysql-kBH4tO5T.PNG
class CreatePrioritiesTable extends Migration
{
public function up()
{
Schema::create('priorities', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->char('name');
$table->char('hexcolorcode', 7);
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
});
}
}
class CreateTasksTable extends Migration
{
public function up()
{
Schema::create('tasks', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('name');
$table->text('description');
$table->integer('priority_id')->unsigned();
$table->timestamps();
$table->foreign('priority_id')->references('id')->on('priorities');
$table->foreign('user_id')->references('id')->on('users');
});
}
}
UPDATE
PriorityController
class PriorityController extends Controller
{
protected $priorities;
public function __construct(PriorityRepository $priorities)
{
$this->middleware('auth');
$this->priorities = $priorities;
}
public function index(Request $request)
{
return view('priority.index', [
'priorities' => $this->priorities->forUser($request->user()),
]);
}
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255',
'hexcolorcode' => 'required|max:7'
]);
$request->user()->priorities()->create($request->all());
return redirect('/priorities');
}
public function edit(Priority $priority)
{
$this->authorize('edit', $priority);
return view('priority.edit', compact('priority'));
}
public function update(Request $request, Priority $priority)
{
$this->validate($request, [
'name' => 'required|max:255',
'hexcolorcode' => 'required|max:7'
]);
$priority->update($request->all());
return redirect('/priorities');
}
public function destroy(Request $request, Priority $priority)
{
$this->authorize('destroy', $priority);
$priority->delete();
return redirect('/priorities');
}
}
In your store method. The create method it says :
user->tasks(). This bit will only inserting data in user and tasks table. Thats why you have foreign key error. As you are not updating one of your tables(priority) and also you have added foreign keys in tables as i csn see from migration.
What you are trying to achieve is right if you had a pivot table called task_user where you had userid, taskid and a priority_id. That would be perfect as you would simply update the priority column with userid and taskid. Thats one way but it will require few changes OR you can insert data into user and tasks table seperately for which you will need to just change the query. What do you prefer? I can show you an example for which you like.
//for Priority
// store
$priorities = new Priority;
$priorities->name = Input::get('priority_name');
$priorities->hexcolorcode = Input::get('hexcolorcode');
$priorities->save();
$priority = Priority::select('id')->orderBy('created_at', 'desc')->first();
//for Task
$tasks = new Task;
$tasks->name = Input::get('task_name');
$tasks->priority_id = Input::get('priority');
$priorities->save();
// redirect
return Redirect::to('some view please change this');
Please explain views or show screenshots, how are you handling it. For now, I have given you the solution with one controller handling priorities and tasks.
SOLUTION
I added the priority_id attribute to the fillable array inside the task model.
protected $fillable = ['name', 'description', 'priority_id'];
I had an understanding problem, because user_id is assigned automatically from the framework, but it isn't specified in fillable array. That's because I say $request->user->tasks->create(); it is assigned from the framework, but priority_id is assigned through the user, so it is mass assigned and need to be specified in the fillable array.
#Murlidhar Fichadia