How to contextualize Symfony 2 routes without request parameters - symfony

I've been searching high and low for a solution here, but I'm not really finding what I need. It may just be that I'm not searching for the right thing.
For the admin backend of my app, I currently grab a user for a controller like this:
//routing.yml
view_user:
pattern: /user/{id}/
defaults: { _controller: AppBundle:User:view }
//UserController.php
use Sauce\AppBundle\Entity\User;
public function viewAction(User $user)
{
$user->getSauce();
}
For the frontend where a user doesn't fetch themselves at each URL using an id, this doesn't work. Is it possible to do this without having an id in the URL? My first thought of how to make a user easily available is something like:
/**
* A fast way to grab the user throughout this class.
*/
public function getUser() {
return $this->get('security.context')->getToken()->getUser();
}
public function viewAction()
{
$user = $this->getUser();
...
}
But this, to me, seems way below Symfony 2 standards. I must be overlooking something more elegant. Any insights out there?

Yea, creating a helper method is the way to go. You could move it to a base controller to stay DRY. My abstract base controller provides such a method.
There is no “magic” way of doing this I'm aware of.

Related

Symfony 4 Event Subscriber User

I created a middleware/event subscriber to generalise a few security checks I need to perform on routes with a specific request attribute.
But in order to perform the required database query I need to get access to the authenticated user.
When I call $event->getRequest()->getUser() it always returns null even when the user is authenticated.
Where can I find more information about this?
And one more question: is using EventSubscribers a good practice for my needs?
Thanks in advance.
In https://stackoverflow.com/a/55417508/4707978 is the answer.
use Symfony\Component\Security\Core\Security;
class ExampleService
{
private $security;
public function __construct(Security $security)
{
$this->security = $security;
}
public function someMethod()
{
$user = $this->security->getUser();
}
}
And one more question: is using EventSubscribers a good practice for my needs?
Probably not, you should check out security voters. With them you could implement your own custom security logic and enforce it with the given symfony tools like #IsGranted etc..
https://symfony.com/doc/current/security/voters.html

Where should I place my users method in Symfony 4?

I followed the symfony 4 documentation to make a login form (https://symfony.com/doc/current/security/form_login_setup.html) and I added a registration form in the same controller.
I'm a beginner, and I would like to make an account page where the user will be able to change his informations, but I would like to know if I should create a new Controller who work with the user entity, on just work onthe same controller than the login and registration ?
Or maybe my user controller have to inherit the securityController?
I'm a noob, sorry ^^'
Thank you
You can give a look at https://symfony.com/doc/current/service_container.html#creating-configuring-services-in-the-container
The path is creating your own service(s), for example App\Servie\UserManager that performs every task on a User object
For example, you could have:
App\Service\UserManager
class UserManager
{
// ...
public function handleUpdatePasswordRequest(Request $request) {...}
// or
public function handleUpdatePasswordForm(Form $form) {...}
// or:
public function handleUpdatePassword(User $user, $newPlainPassword) {...}
...
}
as to say, whatever you want to implement, keeping in mind that the thinner the controllers are better it is, while services can grow (and be split) indefinitely

Laravel service provider for sharing a variable in all views

I want to share a variable in all views but i'm not sure if this is the right way to do it? I have made a service provider:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Worktype;
class ShareWorktypesInViewsProwider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
$worktypes = Worktype::all();
view()->share('worktypes', $worktypes);
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}
but i still get an error in my view. Do i need to register my service provider or it should work out of the box?
Firstly, for such a small piece of code I wouldn't worry about creating a brand new service provider. I would just add the above to your AppServiceProvider. Also, you code inline the above as well:
view()->share('worktypes', Worktype::all());
As for registering a provider. Literally all you have to do is go to config/app.php, find the providers array and add your provider to it.
In your can you would add:
App\Providers\ShareWorktypesInViewsProwider::class,
The documentation for it:
https://laravel.com/docs/5.3/providers#registering-providers
Hope this helps!
A more recent update on this. While #Rwd solution works great, you may run into difficulties as the service provider is run every single request.
As a result, you'll end up requesting Worktype from the database regardless of whether you're on a view, etc.
The best way to achieve this now is by using Laravel View composers.
By adding the below into your service provider, you'll only call the Worktype::all() when needed within a view.
view()->composer('*', function($view) {
$view->with(['worktypes' => Worktype::all()]);
});
Although make sure to use some caching otherwise it'll get called for every view!

Symfony/DRY - check if user is granted in every action

I'm using this code to check if a user is granted in my Symfony application :
$securityContext = $this->container->get('security.context');
if($securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED') ){
$user = $this->get('security.context')->getToken()->getUser()->getId();
} else {
return $this->render('IelCategoryBundle:Category:home.html.twig');
}
I have to ckeck this in almost every CRUD action that I'm writing (edit, delete, ...).
I feel not DRY at all (no play on words ;-)). Is there a better way to check this in many actions ?
JMSSecurityExtraBundle provides the #Secure annotation which eases checking for a certain user-role before invoking a controller/service method.
use JMS\SecurityExtraBundle\Annotation as SecurityExtra;
/** #SecurityExtra\Secure(roles="IS_AUTHENTICATED_REMEMBERED") */
public function yourAction()
{
// ...
}
Your best bet would be to rely on Kernel event listeners: http://symfony.com/doc/current/cookbook/service_container/event_listener.html.
Implement your listener as a service and then you could set $this->user to desired value if isGranted results TRUE. Later on, you could easily retrieve the value within the controller using:
$myServiceListener->getUser();
On the other hand, if check fails you could easily redirect user to your home.html.twig.

Variable bound to whole application through requests

I want a variable bound to the application scope, (in java that would be application scope).
I thought service should be the thing to use in order to reach my goal.
I created a service test
<?php
namespace Acme\MyBundle\Service;
class test {
public $count;
public function __construct() {
$this->count = 0;
}
public function addCount() {
$this->count++;
}
}
which I declared in services.yml
acme.my.service.test:
class: Acme\MyBundle\Service\test
I call it in my controller
public function testAction() {
$this->get('acme.my.service.test')->addCount();
return $this->render('AcmeMyBundle:Test:test.html.twig');
}
But when I retrieve it in my twig, the value is 1, no matter how much I refresh or go with multiple session on the url bound to my testAction.
=> It means that constructor is called each time.
So is that the right way to do? I thought services were created once and reused then, but I may be mistaken.
Could you please enlighten me?
Thank you,
copndz
I found what I was looking for, APC caching system.
Easy to use and integrated to doctrine common.
How to cache in Symfony 2?
http://docs.doctrine-project.org/en/latest/reference/caching.html

Resources