i’m trying to build a shop management system but i’m stuck with this issue. I know this post will be a bit long, but it’s the only one solution i have to let you understand.
So i have a db structure as following :
One user hasMany shops
One shop hasMany employee
The ideal workflow for me would be:
- A user register (This user will have admin role);
- After registration, he’s redirected to a new page where he will create the new shop;
- Once the new shop is created, he will be redirected to the shop dashboard.
- On the sidebar of the dashboard there will be some link calling the different routes.
- He can click on the ‘Employee’ route and will be prompted to a new view, where there
will be a list of all the employees(if existing) and a button which will open a modal
with a form to create a new employee.
Now, what i have done until this point is the following :
- I have created a new user in the RegisterController
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Auth\Events\Registered;
use App\Providers\RouteServiceProvider;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
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 = '/shop';
/**
* 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
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'surname'=>['required', 'string', 'max:255'],
'phone'=>['required', 'string', 'max:25'],
'isAdmin'=>['string', 'required'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return \App\Models\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'surname'=>$data['surname'],
'phone'=>$data['phone'],
'isAdmin'=>$data['isAdmin'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
- I have created the route who redirect the user after registration to a
newshopview :
Route::get('/shop', [ShopController::class, 'shop'])->name('shop')
- I have created the ShopController to create the new shop istance :
<?php
namespace App\Http\Controllers;
use App\Models\Shop;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
class ShopController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function shop(){
return view('newshop');
}
public function newShop(Request $req){
$shop = Shop::create([
'name' => $req->input('name'),
'address'=> $req->input('address'),
'vat_number' => $req->input('vatnumber'),
'legal_name' => $req->input('legalname'),
'legal_address' => $req->input('legaladdress'),
'fiscal_code' => $req->input('fiscalcode'),
'user_id' => Auth::user()->id
]);
return Redirect::route('home');
}
}
- Then i created the route to the employee view :
Route::get('/employees', [employeesController::class, 'employees'])->name('employees');
- and then the EmployeeController :
<?php
namespace App\Http\Controllers;
use App\Models\Shop;
use App\Models\User;
use App\Models\Employee;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Contracts\Encryption\DecryptException;
class employeesController extends Controller
{
public function __construct(){
$this->middleware('auth');
}
public function employees(){
$employees = Employee::all();
return view('employees', compact('employees') );
}
//create a new employee instance and a new user for the employee to login
public function newEmployee(Request $request , Shop $shop){
dd($this->shop);
//Create a new password 18 Char
$psw = User::random_psw();
//create a new user instance for the employee to login
$user = User::create([
'name' => $request->input('name'),
'surname' => $request->input('surname'),
'phone' => $request->input('phone'),
'isAdmin'=> 0,
'email'=> $request->input('email'),
'password' => Crypt::encryptString($psw),
]);
// Create a new Employee instance
Employee::create ([
'name' => $request->input('name'),
'surname' => $request->input('surname'),
'phone' => $request->input('phone'),
'email'=> $request->input('email'),
'role'=> $request->input('role'),
'user_id'=>$user->id,
'shop_id'=>//HERE I NEED TO INSERT THE CURRENT SHOP ID WHERE THE EMPLOYEE IS BEING CREATED,
])->save();
$a = $user->password;
try{
$decrypt = Crypt::decryptString($a);
}catch(DecryptException $e){
echo 'Decryption error';
}
return Redirect::back();
}
//update employee data from DB
public function employeeUpdate(Request $request){
$employee = Employee::find($request->id);
$employee->name = $request->input('name');
$employee->surname = $request->input('surname');
$employee->email = $request->input('email');
$employee->phone = $request->input('phone');
$employee->role = $request->input('role');
$employee->save();
return Redirect::back();
}
public function employeeDelete(Request $request){
$employee = Employee::find($request->id);
$employee->delete();
return Redirect::back();
}
}
The issue i’m facing is, how do i get the current shop id in the employee controller??
Hope somebody can help me with this matter as i’m getting crazy with it.
Thank you so much.
>Solution :
If I understand correctly, you would like to create a Shop in ShopController, and later access its id in employeesController.
The easiest way to do this with Laravel is to make use of sessions. Modify the newShop method in ShopController:
public function newShop(Request $req){
$shop = Shop::create([
'name' => $req->input('name'),
'address'=> $req->input('address'),
'vat_number' => $req->input('vatnumber'),
'legal_name' => $req->input('legalname'),
'legal_address' => $req->input('legaladdress'),
'fiscal_code' => $req->input('fiscalcode'),
'user_id' => Auth::user()->id
]);
$req->session()->put('current_shop_id', $shop->id);
return Redirect::route('home');
}
And you can then get the current shop id in another controller by retrieving it from the session:
$shop = Shop::find($request->session()->get('current_shop_id'));
You can also add a default if not set in the session:
$shop = Shop::find($request->session()->get('current_shop_id')) ?? $request->user()->shops()->first();
Shop Selector
This will get the user’s first shop if one is not set in the session. If possible, I recommend adding a dropdown in your navbar to allow users to select a shop:
@foreach (Auth::user()->shops as $shop)
<a href="{{ route('shops.set', $shop) }}">{{ $shop->name }}</a>
@endforeach
And then a simple controller method:
public function set(Request $request, Shop $shop)
{
$request->session()->put('current_shop_id', $shop->id);
}
And lastly a route:
Route::get('/shops/set/{shop}', [ShopController::class, 'set'])->name('shops.set');
A few other notes
- The
employeesControllerclass should be namedEmployeeController(from PSR-12) - I recommend following the resource controller method names, even when not using resource controllers.
- The method for creating a new model should be called
store - The method for showing the page to create a new model should be called
create - The method for listing available models should be
index
- The method for creating a new model should be called
- I also strongly recommend using pagination instead of
::all():- Use
Employee::paginate()instead ofEmployee::all() - In the view, then add
{{ $employees->links() }}at the end to show the previous/next page links - Pagination only loads 15 models per page by default, instead of loading everything into memory
- Use