ImportController
<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Talent\ImportData\Requests\ImportDataRequest;
use Illuminate\Support\Facades\Hash;
use Rap2hpoutre\FastExcel\FastExcel;
class ImportController extends Controller
{
public function __construct(private User $user)
{
}
public function import(ImportDataRequest $request)
{
$validated = $request->validated();
$collection = (new FastExcel)->import($validated['file'], function ($rows) {
$user = $this->user->create([
'name' => $rows['First Name'] . " " . $rows['Last Name'],
'email' => $rows['Email'],
'password' => Hash::make('Introcept#123'),
'role' => $rows['Role']
]);
$employee = $user->employees()->create([
'status' => $rows['Status'],
'first_name' => $rows['First Name'],
'last_name' => $rows['Last Name'],
'email' => $rows['Email'],
'contact_number' => $rows['Contact Number'],
'date_of_birth' => $rows['Date of Birth'],
'current_address' => $rows['Current Address'],
'pan_number' => $rows['Pan Number'],
'bank_account_number' => $rows['Bank Account Number'],
]);
$education = $employee->education()->create([
'education_level' => $rows['Education Level'],
'passed_year' => $rows['Passed Year'],
'institution' => $rows['Institution'],
]);
$employment = $employee->employment()->create([
'organization' => $rows['Organization'],
'join_date' => $rows['Join Date'],
'current_position' => $rows['Current Position'],
'work_schedule' => $rows['Work Schedule'],
'team' => $rows['Team'],
'manager' => $rows['Manager'],
'superpowers' => $rows['Superpower'],
]);
$employment->manages()->create([
'employee_id' => $rows['Manages'],
]);
});
}
}
ImportData Request
<?php
namespace App\Talent\ImportData\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ImportDataRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array<string, mixed>
*/
public function rules()
{
return [
'file'=>'required|mimes:csv,xlsx'
];
}
}
I am creating an API where the admin can import data from an excel file. Here, I am using the Fast Excel package in order to import data. Everything is working fine, but I have no idea how I can validate excel data before saving it into the database. I am pretty new to Laravel and any help will be really appreciated. Thank you
Related
i need to get error from form request in controller and pass to JSON and front-end
in past i solve this problem in controller i mean my validation was in controller but now i don`t know how to handle this problem
in my form request i have rules and custom Persian message :
<?php
namespace App\Http\Requests\Admin;
use Illuminate\Foundation\Http\FormRequest;
class CreateAdminRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'first_name' => 'required|min:3|regex:/^[a-zA-ZÑñ\s]+$/',
'email' => 'required|email|unique:admins',
'password' => 'required|min:8',
];
}
public function messages()
{
return [
'first_name.required' => 'لطفا نام را وارد کنید',
'first_name.min' => 'نام حداقل باید ۳ کاراکتر باشد',
'first_name.regex' => 'لطفا حروف را به انگلیسی تایپ کنید',
'email.required' => 'لطفا ایمیل را وارد کنید',
'email.email' => 'فرمت ایمیل باید اینگونه باشد : example#gmail.com',
'email.unique' => 'ایمیل تکراری است',
'password.required' => 'فیلد رمز را وارد کنید',
'password.min' => 'رمز حداقل باید ۸ کاراکتر باشد',
];
}
}
in my controller i want a way to get something from form-request and say if this variable get error and fails get error and give it to front-end :
<?php
namespace App\Http\Controllers;
use App\Http\Requests\Admin\CreateAdminRequest;
use App\Services\AdminService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class AdminController extends Controller
{
public function create(CreateAdminRequest $req)
{
if ($->fails()) {
return response()->json([
"status" => false,
"errors" => $->errors()->all(),
]);
} else {
$create = AdminService::create($req->first_name, $req->email, $req->password);
return response()->json([
"status" => $create["status"],
"message" => $create["message"],
]);
}
}
}
I created a registration form with the use of laravel ui scaffolding.
What I did:
• Added some field besides the default ones
• Using the auth controller specifically RegisterController and change a part of the create function from this
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
Into this:
protected function create(array $data)
{
return User::create([
'user_email' => $data['email'],
'user_Type' => $data['user_Type'],
'username' => $data['username'],
'password' => Hash::make($data['password']),
'contact_number' => $data['contact_number'],
]);
}
But the result after submitting the form with a post method is this:
ArgumentCountError
Too few arguments to function App\Http\Controllers\Auth\RegisterController::create(), 0 passed in /Users/idan/Documents/SweetSurrender/vendor/laravel/framework/src/Illuminate/Routing/Controller.php on line 54 and exactly 1 expected
Web.php
Route::get('/register', function() {
return view('auth.register');
})->name('register');
Route::post('/register', [RegisterController::class, 'create']);
RegisterController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\Models\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
public function index() {
return view('auth.register');
}
protected function validator(array $data)
{
return Validator::make($data, [
'username' => ['required', 'string', 'max:16'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
'contact_number' => ['required', 'string', 'min:12', 'unique:users'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\Models\User
*/
protected function create(array $data)
{
return User::create([
'user_email' => $data['email'],
'user_Type' => $data['user_Type'],
'username' => $data['username'],
'password' => Hash::make($data['password']),
'contact_number' => $data['contact_number'],
]);
}
}
I also tried using this in RegisterController.php
protected function create(Request $data)
{
return User::create([
'user_email' => $data->input('email'),
'user_Type' => $data->input('user_Type'),
'username' => $data->input('username'),
'password' => Hash::make($data->input('password')),
'contact_number' => $data->input('contact_number'),
]);
}
but it results to an error:
Illuminate\Database\QueryException
SQLSTATE[HY000]: General error: 1364 Field 'user_email' doesn't have a default value (SQL: insert into users (password, updated_at, created_at) values ($2y$10$vr7UasRBCzx2URQxLSWneuvr4Hl1at.q7qDk8UK0Wc/INjeHeYH7y, 2020-12-22 07:15:41, 2020-12-22 07:15:41))
I solved this problem by using the same code:
protected function create(array $data)
{
return User::create([
'user_email' => $data['email'],
'user_Type' => $data['user_Type'],
'username' => $data['username'],
'password' => Hash::make($data['password']),
'contact_number' => $data['contact_number'],
]);
}
and In the User model I included this:
protected $fillable = [
'username',
'user_email',
'password',
'contact_number',
];
I am creating multi authentication system in laravel, I have created two sperate tables for each entity, everything works fine, but I am facing only one issue after register, users who are using web guard they can log in automatically and redirect to the user dashboard and it is perfect, but in case of other users who are using different guard, when they complete the registration process, they can not log in the system automatically.
so my question how can I enable the automatic login process for other user type once they complete the register step? below is the code that I am using in my project
Route File
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Auth::routes(['verify' => true]);
Route::get('/home', 'HomeController#index')->name('home')->middleware('verified');
Route::get('/seller/dashboard', 'SellerHomeController#index')->name('seller.dashboard');
Route::get('/seller/login','Auth\Seller\SellerLoginController#showLoginForm')->name('seller.login');
Route::post('/seller/login','Auth\Seller\SellerLoginController#login');
Route::post('/seller/logout','Auth\Seller\SellerLoginController#logout')->name('seller.logout');
Route::post('/seller/password/email','Auth\Seller\SellerForgotPasswordController#sendResetLinkEmail')->name('seller.password.email');
Route::get('/seller/password/reset', 'Auth\Seller\SellerForgotPasswordController#showLinkRequestForm')->name('seller.password.request');
Route::post('/seller/password/reset','Auth\Seller\SellerResetPasswordController#reset')->name('seller.password.update');
Route::get('/seller/password/reset/{token}', 'Auth\Seller\SellerResetPasswordController#showResetForm')->name('seller.password.reset');
Route::get('/seller/register','Auth\Seller\SellerRegisterController#showRegistrationForm')->name('seller.register');
Route::post('/seller/register','Auth\Seller\SellerRegisterController#register');
SellerLoginController
namespace App\Http\Controllers\Auth\Seller;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class SellerLoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/seller/dashboard';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest:seller')->except('logout');
}
public function showLoginForm()
{
return view('auth.seller.login');
}
protected function attemptLogin(Request $request)
{
return $this->guard('seller')->attempt(
$this->credentials($request), $request->filled('remember')
);
}
protected function guard()
{
return Auth::guard('seller');
}
}
SellerRegisterController
namespace App\Http\Controllers\Auth\Seller;
use App\Seller;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Auth\Events\Registered;
class SellerRegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = '/seller/dashboard';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest:seller');
}
public function showRegistrationForm()
{
return view('auth.seller.register');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'firstname' => ['required', 'string', 'max:255'],
'lastname' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:sellers'],
'business_name' => ['required', 'string', 'max:255'],
'business_description' => ['required', 'string', 'max:255'],
'business_location' => ['required', 'string', 'max:255'],
'business_website' => ['required', 'string', 'max:255'],
'password' => ['required', 'string', 'min:6', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
$seller = Seller::create([
'firstname' => $data['firstname'],
'lastname' => $data['lastname'],
'email' => $data['email'],
'business_name' => $data['business_name'],
'business_description' => $data['business_description'],
'business_location' => $data['business_location'],
'business_website' => $data['business_website'],
'business_logo' => 'test_logo.jpg',
'password' => Hash::make($data['password']),
'user_type' => $data['user_type'],
]);
return $seller;
}
}// code end here
This happens because you didn't defined the guard method on the SellerRegisterController and the default implementation retrieves the default driver (which is web).
That guard method provides the guard to the automatic login process in the register method of the RegistersUsers:
$this->guard()->login($user);
You have to override the guard method in your SellerRegisterController class to return the correct driver and allow the trait to perform the login process on the correct sellers driver:
/**
* Get the guard to be used during registration.
*
* #return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return Auth::guard('sellers');
}
Laravel Auth by default take User table as the main data. In case you want to do multiple auth, first thing you need to do is create a model with Notifiable trait
Model
class Admin extends Authenticatable
{
use Notifiable;
}
After that, you need to create the guard and provider in config/auth.php
The example like this
<?php
[...]
'guards' => [
[...]
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'writer' => [
'driver' => 'session',
'provider' => 'writers',
],
],
[...]
And
[...]
'providers' => [
[...]
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
'writers' => [
'driver' => 'eloquent',
'model' => App\Writer::class,
],
],
[...]
And in the login controller, you will need to check which guard is trying to login by doing this line
Auth::guard('admin')->attempt(['email' => $request->email, 'password' => $request->password], $request->get('remember'))
If you need more detail about it, try to read this https://pusher.com/tutorials/multiple-authentication-guards-laravel
// Adminmiddleware
if(Auth::check() && Auth::user()->role->id == 1)
{
return $next($request);
}else {
return redirect()->route('login');
}
// Authormiddleware
if(Auth::check() && Auth::user()->role->id == 2 )
{
return $next($request);
}else {
return redirect()->route('login');
}
// Admin Route
Route::group(['as'=>'admin.','prefix'=>'admin','namespace'=>'Admin','middleware'=>['auth','admin']], function (){
Route::get('dashboard','DashboardController#index')->name('dashboard');
});
// Auhtor Route
Route::group(['as'=>'user.','prefix'=>'user','namespace'=>'Author','middleware'=>['auth','user']], function (){
Route::get('dashboard','DashboardController#index')->name('dashboard');
});
// only auht route
Route::group(['middleware'=>['auth']], function(){
Route::post('favorite/{post}/add','FavoriteController#add')->name('post.favorite');
Route::post('review/{id}/add','ReviewController#review')->name('review');
Route::get('file-download/{id}', 'PostController#downloadproject')->name('project.download');
Route::post('file-download/{id}', 'PostController#downloadproject');
});
I'm trying to test if the current password is same as in DB.
my simplified controller:
class ChangePasswordController extends Controller
{
public function update(Request $request, User $user)
{
$this->validate($request, [
'current_password' => ['required', new CurrentPassword()],
'password' => 'required|string|min:6|confirmed'
]);
$user->update([
'password' => bcrypt($request->password)
]);
}
}
in my custom CurrentPassword rule i'm checking the hash like this:
class CurrentPassword implements Rule
{
public function passes($attribute, $value)
{
$check = Hash::check($value, auth()->user()->password);
dump($check);
return $check;
}
public function message()
{
return 'Current password is incorrect.';
}
}
and my test for the custom rule is:
/** #test */
public function an_authenticated_user_may_change_own_password()
{
$this->withoutExceptionHandling();
$user = factory(User::class)->create([
'password' => '1234'
]);
$this->actingAs($user)->patch("/profile/{$user->id}/password", [
'current_password' => '1234',
'password' => 'mynewpassword',
'password_confirmation' => 'mynewpassword'
]);
$this->assertTrue(Hash::check('mynewpassword', $user->fresh()->password));
}
unfortunately i'm getting an error:
1)
Tests\Feature\UpdatePasswordTest::an_authenticated_user_may_change_own_password
Illuminate\Validation\ValidationException: The given data was invalid.
i don't understand why this is happining. My dump($check); returns false when i run this test. My $value is '1234' and the auth()->user()->password returns also '1234'. Maybe somebody have an idee what I'm doing wrong.
this test is getting green:
/** #test */
public function current_password_must_be_valid()
{
$user = factory(User::class)->create([
'password' => '1234'
]);
$this->actingAs($user)->patch("/profile/{$user->id}/password", [
'current_password' => '12345',
'password' => 'mynewpassword',
'password_confirmation' => 'mynewpassword'
])->assertSessionHasErrors('current_password');
}
You should hash your password in your factory as well, otherwise Eloquent will store it in cleartext (that's why auth()->user()->password returns '1234')
public function current_password_must_be_valid()
{
$user = factory(User::class)->create([
'password' => Hash::make('1234'); // remember to import the Hash facade
]);
...
}
I am a week old into laravel and am working on my first api.
Everything worked well till I decided to introduce resources. When I call the UserResource method I get an error that I can't understand. I have googled but haven't found an answer yet.
This is the error I get when I run on postman
Symfony\Component\Debug\Exception\FatalThrowableError: Call to undefined function App\Http\Controllers\Api\UserResource()
The Resource file is in app/Http/Resources/
Checkout the path returned
App\Http\Controllers\Api\UserResource
yet the one I add is
App\Http\Resources\UserResource;
Laravel Code:
app/Http/Controllers/Api/usersController.php
use App\User;
use App\Http\Resources\UserResource;
class UsersController extends Controller
{
public function login(Request $request)
{
$this->validate($request, [
'email' => 'required',
'password' => 'required',
]);
$email = $request->email;
$password = $request->password;
$user = User::where('email', $email)->where('password', $password)->first();
if($user) {
$success['token'] = $user->createToken('myapp')-> accessToken;
$success['user'] = UserResource($user);
return response()->json(['success' => $success], 200);
}
return response()->json(['error' => 'UnAuthorised'], 401);
}
}
app/Http/Resources/UserResource.php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'first_name' => $this->first_name,
'other_names' => $this->other_names,
'email' => $this->email,
'phone_number' => $this->phone_number,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
You forgot the new operator trying to instantiate the UserResource class. Without the new operator, PHP will look for a function called UserResource in the current namespace, therefore you get that error.