I made a BaseController to share user information but that doesn't work. Auth::user()->id and Auth::user()->email are empty.
How can I archive this? Whats the best approach?
class BaseAdminController extends Controller{
public function __construct()
{
$this->initMenu();
}
private function initMenu()
{
View::share('userinfo', (object) ['id' => Auth::User()->id, 'email' => Auth::User()->email]);
}
}
You can do it via middleware because you can't access the session or authenticated user in the controller's constructor, since the middlware isn't runnig yet:
class BaseAdminController extends Controller{
public function __construct()
{
$this->middleware(function ($request, $next) {
$this->initMenu();
return $next($request);
});
}
private function initMenu()
{
View::share('userinfo', (object) ['id' => Auth::User()->id, 'email' => Auth::User()->email]);
}
}
You can use the view helper function to share stuff easily. Maybe this will help you:
view()->share('userinfo', [...data to pass in an array...]);
or
view()->share('user', Auth::user());
This is an example! Only pas the info you want to the view, like you did in your example. But just pass the array, not casting it to object, etc....
Related
I'm not familiar with Vue.js at all, so found a good replacement using Livewire.
The challenge that I've got to solve is to have a user friendly registration on my website using Fortify + Livewire. The registration process is a multistep one and depends on the choices that the user makes it will load the relative fields.
So far I set up the Fortify views by adding in the FortifyServiceProvider.php file the following code:
Fortify::loginView(function () {
return view('auth.login');
});
Fortify::registerView(function () {
return view('auth.register');
});
The auth/login.blade.php view loading the livewire component which is basically a form:
<form action="{{ route('register') }}" method="POST" wire:submit.prevent="submit">
/**
* Here would go the inputs that must be shown depends on what users choice
* (is it an ordinar user or a company)
*/
<button type="submit">Save<button/>
</form>
The multiform challenge would be resolved by adding $step property into the Register.php class:
class RegisterForm extends Component
{
public $step;
public function mount()
{
$this->step = 0;
}
public function submit()
{
if ($this->step < 3) {
$this->step++;
} else {
// pass all the data to the fortify register method
// <-- Here is my trouble!
}
}
}
which will be incremented by passing each of the registration steps ($this->step++).
The most important thing that is quite complicated for me is how to prevent form submission to have the validation + form changes and by the end all the set of the data to pass trough Fortify registration process?
Look at the fortify Controller for register
public function store(Request $request, CreatesNewUsers $creator): RegisterResponse
{
event(new Registered($user = $creator->create($request->all())));
$this->guard->login($user);
return app(RegisterResponse::class);
}
T
use Illuminate\Auth\Events\Registered;
use Illuminate\Support\Facades\Auth;
use Laravel\Fortify\Contracts\CreatesNewUsers;
use Livewire\Component;
class Register extends Component
{
public $name;
public $email;
public $password;
public $password_confirmation;
public function submit(CreatesNewUsers $creator)
{
event(new Registered($user = $creator->create([
'name' => $this->name,
'email' => $this->email,
'password' => $this->password,
'password_confirmation' => $this->password_confirmation,
])));
Auth::guard()->login($user);
$this->redirect('home');
}
public function render()
{
return view('livewire.register');
}
}
Something like this will work for your use case.
You are still using the fortify Action and Still Firing the Event
The response is to use app container
<?php
use Illuminate\Auth\Events\Registered;
use Illuminate\Support\Facades\Auth;
use App\Actions\Fortify\CreateNewUser;
use Livewire\Component;
class Register extends Component
{
public $name;
public $email;
public $password;
public $password_confirmation;
public function submit()
{
event(new Registered($user = app(CreateNewUser::class)->create([
'name' => $this->name,
'email' => $this->email,
'password' => $this->password,
'password_confirmation' => $this->password_confirmation,
])));
Auth::guard()->login($user);
$this->redirect('home');
}
public function render()
{
return view('livewire.register');
}
}
The response is to use dependency injection by injecting the Fortify CreateNewUser action in the mounting method of the Livewire component.
use Illuminate\Auth\Events\Registered;
use Illuminate\Support\Facades\Auth;
use App\Actions\Fortify\CreateNewUser;
use Livewire\Component;
class Register extends Component
{
public $name;
public $email;
public $password;
public $password_confirmation;
protected $creator;
public function mount(CreateNewUser $creator)
{
$this->creator = $creator;
}
public function submit()
{
event(new Registered($user = $this->creator->create([
'name' => $this->name,
'email' => $this->email,
'password' => $this->password,
'password_confirmation' => $this->password_confirmation,
])));
Auth::guard()->login($user);
$this->redirect('home');
}
public function render()
{
return view('livewire.register');
}
}
you can use blade example
#if($step > 3)
<input name="name" type="text">
#endif
I am currently trying to build a user registration system with edit fields. At the edit portion, I had to create separate views for editing/updating personal details, email, and passwords.
I started with an empty resource controller. it had only one edit method. Hence I added additional edit methods. Each method can have a separate route. However, I have a hard time having a separate route for each update method in each section as the resource has only one route like this in docs:
PUT/PATCH /photos/{photo} update photos.update
Is there any workaround for this?
Controller
class UserController extends Controller
{
public function __construct()
{
$this->middleware(['auth', 'verified']);
}
public function index()
{
return view('users.index');
}
public function edit_personal(User $user)
{
$user_profile = User::find($user->id);
return view('users.edit.personal', ['users' => $user_profile]);
}
public function update_personal(Request $request, User $user)
{
// How to write route for this method.
}
public function edit_email(User $user)
{
$user_profile = User::find($user->id);
return view('users.edit.email', ['users' => $user_profile]);
}
public function update_email(Request $request, User $user)
{
// How to write route for this method.
}
public function edit_password(User $user)
{
$user_profile = User::find($user->id);
return view('users.edit.password', ['users' => $user_profile]);
}
}
Routes
Auth::routes(['verify' => true]);
Route::get('/', function () {
return view('welcome');
});
Route::get('/users/{user}/personal', 'UserController#edit_personal')->name('users.personal');
Route::get('/users/{user}/email', 'UserController#edit_email')->name('users.email');
Route::get('/users/{user}/password', 'UserController#edit_password')->name('users.password');
Route::resource('users', 'UserController');
Basically I have separated edit portion of user controller into personal, email and password sections and they have separate forms. I want to write update functions for each section in UserController.
don't know why are you using separate forms for updating each fields while you can do it in a single form. however you can use either put/patch or post method for updates. here's i am using post for example.
routes:
Route::get('users/{user}/personal', 'UserController#edit_personal')->name('users.personal');
Route::post('users/{user}/personal', 'UserController#update_personal')->name('users.update-personal');
Route::get('users/{user}/email', 'UserController#edit_email')->name('users.email');
Route::post('users/{user}/email', 'UserController#update_email')->name('users.update-email');
Route::get('users/{user}/password', 'UserController#edit_password')->name('users.password');
Route::post('users/{user}/password', 'UserController#update_password')->name('users.update-password');
as you are using route model binding you can directly get the object.
public function edit_personal(User $user)
{
return view('users.edit.personal', ['users' => $user]);
}
public function update_personal(Request $request, User $user)
{
//validation goes here
$user->update([
'value' => $request->value,
...........
]);
}
I am finding it hard to understand the examples from the docs to the scenario I am having. In my project I have an application form which filled up by the user then admin will update that form once the application is approved, canceled etc.
Now I want to notify the user that her/his application has been approved, canceled etc.
in my controller:
public function update(Request $request, $id)
{
$this->validate($request, [
'status' => 'required'
]);
$requestData = $request->all();
$loanapplication = LoanApplication::findOrFail($id);
$loanapplication->update([
"status" => $request->status,
"admin_notes" => $request->admin_notes,
"date_approval" => $request->date_approved
]);
if($request->notifyBorrower = 'on') {
$user_id = $loanapplication->user_id;
$status = $request->status;
$this->notify(new AdminResponseToApplication($user_id));
}
return redirect()->back()->with('flash_message', 'LoanApplication updated!');
}
In my AdminResponseToApplication.php I like to achieve this
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class AdminResponseToApplication extends Notification implements ShouldQueue
{
use Queueable;
public function __construct()
{
//
}
public function via($notifiable)
{
return ['mail','database'];
}
public function toMail($notifiable)
{
return (new MailMessage)
->line(.$user->nameHere. 'your application has been '.$statusHere.'.')
->action('check it out', url('/'))
->subject('Regarding with your loan application')
->line('This is system generated. Do not reply here.');
}
public function toDatabase($notifiable)
{
return [
'user_id' => $user->nameHere,
'status' => $statusHere,
'title' => .$user->nameHere. 'your application has been '.$statusHere.'.',
'url' => '/'
];
}
}
How can I achieve that? Thank you in advance!
Get user object and call function notify() on it. $this->notify() will not work because $this is not an instance of User class.
$user = User::find($user_id);
$user in the $user->notify(new AdminResponseToApplication($data)) function is available in notification class as $notifiable.
You can get any value of that object using $notifiable->name etc.
Remember:
AdminResponseToApplication is a class and you can do anything with it that a php class can.
So you can pass as many variables as you want to AdminResponseToApplication class in constructor and do what you want.
$user->notify(new AdminResponseToApplication($data))
As shown above I am sending a $data object to the class which is available in the constructor.
In the class
class AdminResponseToApplication extends notification implements ShouldQueue{
use Queueable;
public $myData;
public function __construct($data)
{
$this->myData = $data; //now you have a $data copied to $this->myData which
// you can call it using $this->myData in any function of this class.
}
}
I'm calling cloud APIs using token authentication with php-openstack-sdk.
$openstack = new OpenStack\OpenStack([
'authUrl' => '{authUrl}',
'region' => '{region}',
'user' => [
'id' => '{userId}',
'password' => '{password}'
],
'scope' => ['project' => ['id' => '{projectId}']]
]);
However, every API call requires me to be authenticated (as shown in the code above). Instead of repeating the same auth code in every controller function, how do I do it once and be able to call $openstack in my controller's functions? i.e., in my controller, I can directly use $openstack.
public function listServers()
{
$openstack->computeV2()->listServers();
}
Write the logic in the __construct() of your Controller.php if you want that to be accessible for all the controllers. If not, write the __construct() within the controller you need.
Controller.php
class Controller extends BaseController
{
protected $openstack;
public function __construct()
{
$this->openstack = new OpenStack\OpenStack([
...
]);
}
}
NetworkController.php
class NetworkController extends Controller
{
public function getNetworkDetails() {
$network = $this->openstack->networking();
}
}
You can place the code shown in the __construct function of your controller and provide it as a protected variable to the class.
I think the best way is to use laravel middlewares
I want to allow users to CRUD only posts they own. I would like not to create a new middleware, but to leverage the existing ones instead. So, Can Entrust's default middlewares be extended to fit this purpose?
class PostsController extends Controller
{
public function __construct()
{
$this->middleware('auth');
$this->middleware('role:blogger|owner'); // <-- implement additional logic in here
}
...
}
#if (Auth::id() === $user->id){
Edit
}
If you have defined in your Kernel.php
protected $routeMiddleware = [
'auth' => '...'
]
In your construct:
public function __construct()
{
$this->middleware('auth', ['only' => ['create']]);
}
using eloquent along with Entrust:
$users = User::whereHas('roles' => function($q){
$q->where('name', 'my-user-role')
})->get();