Specifying custom data in Symfony Routing Annotation - php

I am using symfony 5, and specifying the routings as annotation. So now I have a requirement to pass some extra data along with the routes. It is not part of routing, but I need to have a value for each routing. So I am specifying the route as below, using the options object options={"label"="COMMMON_CLIENTMANAGEMENT"}.
It is not producing an error. So I am not sure if it is working or not. Also I have not been able to retrieve the data from any routing services.
*
* #Route("/client/list", name="client_list", options={"label"="COMMMON_CLIENTMANAGEMENT"})
* #return \Symfony\Component\HttpFoundation\Response
*/
And I want to create an html based on this data, whick will be like <li href="{{path(route)}}">{{ label }}</li>

Update:
So I did a bit more experimenting since I gather the intent is to use the 'label' data when listing routes. I think it is still easier to use the defaults section but you can access the options information using the route collection:
class PlayCommand extends Command
{
protected static $defaultName = 'app:play';
private RouterInterface $router;
public function __construct(RouterInterface $router)
{
parent::__construct();
$this->router = $router;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$routes = $this->router->getRouteCollection();
$route = $routes->get('index');
$label = $route->getOption('label');
Not sure if there is a way to directly get the route by from inside of twig but it would be easy enough to write a twig extension for this.
Original Answer:
The defaults section is used to provide additional information.
I had a hard time finding the docs on the options section. This blog article talks about some new options such as utf-8 support. I think the options section is used by the router. Not positive.
/**
* #Route("/", name="index", options={"label"="COMMMON_CLIENTMANAGEMENT"})
*/

Related

Call to protected method Symfony\Bundle\FrameworkBundle\Controller\Controller::generateUrl()

Recently I am upgrading the system to Symfony 4.2, in one of my page, I encountered the error saying
Call to protected method Symfony\Bundle\FrameworkBundle\Controller\Controller::generateUrl() from context 'Acme\Bundle\Security\Listener\SecurityListener'
The line at which the error is showing:
$this_url = $controller[0]->generateUrl($event->getRequest()->get('_route'), $event->getRequest()->get('_route_params'));
Please let me know, is there anything that I have left.
You are trying to call the controller helper method from a listener. As #ArtisticPhoenix has said in the comments, this is not allowed. What you could do here is instead rewrite your listener to use not the controller's method (which is just intended to be a helper for your actions), but the actual router method that generates the URL. Take a look at the Controller (or ControllerTrait depending on your Symfony version). The generateUrl() method makes a call on the #router service:
/**
* Generates a URL from the given parameters.
*
* #see UrlGeneratorInterface
*
* #final
*/
protected function generateUrl(string $route, array $parameters = [], int $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): string
{
return $this->container->get('router')->generate($route, $parameters, $referenceType);
}
That's what you actually have to use instead of calling the controller's method. You could try something like this:
$this_url = $this->container->get('router')->generate($event->getRequest()->get('_route'), $event->getRequest()->get('_route_params'));
Although, you'd have to make sure you either have the container available (which in general is not a good pattern), or you pass the Router into your service as a dependency. This way, you'd change $this->container->get('router') to the prop you're injecting the router into.
If you just want to generate an url in your Listener, you can simply inject the router component to you class :
private $router;
public function __construct(UrlGeneratorInterface $router)
{
$this->router = $router;
}
...
// Use it like this
$url = $this->router->generate(
$event->getRequest()->get('_route'),
$event->getRequest()->get('_route_params')
);

Laravel 5.5 : How to define global variable that can be used in all controllers ?

Hello Developers & Coders ,
My question is How to define a global variable , that can be used in
all controllers in Laravel ?
I have defined one variable $company in AppServiceProviders's boot method - that im using in all blade views , but I can not use it in controllers file , it gives error , undefined variable $company
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
View::share('key', 'value');
Schema::defaultStringLength(191);
$company=DB::table('company')->where('id',1)->first();
View::share('company',$company);
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
}
please guide me , thanks for your efforts & time :)
set configuration variables at runtime
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
View::share('key', 'value');
Schema::defaultStringLength(191);
$company=DB::table('company')->where('id',1)->first();
// View::share('company',$company);
config(['yourconfig.company' => $company]);
}
}
usage:
config('yourconfig.company');
Okay, so unless you want to keep it in your Session, which I absolutely do not recommend, Cache which does not seem to be a best idea either or set it through the Config system inside of a Framework (which already are 3 different solutions suited for different matters) I would start from thinking what that variable will contain, if that's something that's just a Collection of Company model then you can basically use it in any controller by just using Laravel Eloquent methods.
What I recommend is either $company = Company::where('foo', 'bar')->first();, or just some data provider that would return all the information that you need in the form of Laravel Collection.
tl;dr
#recommended way that's reusable throughout whole app
Company::find(1); // instead of DB::table('company')->where('id', 1)->get();
Hope that helps.

Symfony: Load resources into the Translator from within a Service

I'm working on a Symfony (2.7.4) website where some users have their own language resources for their own locales. For example, a user might have two locales (for example fr and en) and another user could also have one or all of these locales.
Each user has the ability to edit its own translations in a third party app, so translations are not shared between users.
I would like to be able to load the appropriate (YML or XLIFF) resources file when accessing a user's page, based on the locale (which is defined in the URL) and the user (could be its ID or anything that identifies it).
For example, when visiting user99.my-domain.ext/fr/ I'd like to add [base_directory]/user99/messages.fr.yml to the resources loaded by the Translator so it overrides the keys in the base messages.fr.yml.
I've tried to inject the Translator in my service, but I can only use it for reading translations, not adding any. What would be the best way to do that? Or is doing it in a service is too late? Maybe the Kernel is a better place?
Any help is appreciated!
Note: I'm using the YAML format in my examples, but any of the Symfony-known formats is eligible.
In order to "override" translations you should decorate the translator service. That way your own translator logic will be executed when trans() is called somewhere.
http://symfony.com/doc/current/components/dependency_injection/advanced.html#decorating-services
By decorating the service other bundles will also start using the logic you did describe above. You can inject the active user (eg. token_storage service) and some caching services (eg. https://github.com/doctrine/DoctrineCacheBundle) to make sure your user gets the right translations.
This isn't related to the request or hostname, your translation logic for the user should happen after the firewall / authorization logic was executed.
See Symfony's LoggingTranslator PR to find out how the decorator pattern was used to let the translator log missing translations: https://github.com/symfony/symfony/pull/10887/files
I chose to use a custom Twig filter, so I can decide when I want user specific translations and when I want generic ones.
Here's my extension (my users are in fact Domain instances):
<?php
// src/AppBundle/Twig/DomainTranslationExtension
namespace AppBundle\Twig;
use AppBundle\Document\Domain;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Translation\Loader\YamlFileLoader;
use Symfony\Component\Translation\Translator;
class DomainTranslationExtension extends \Twig_Extension {
/**
* #var ContainerInterface
*/
protected $container;
/**
* #var Translator
*/
protected $translator;
/**
* #var string
*/
protected $locale;
/**
* #var Domain
*/
protected $domain;
public function setContainer(ContainerInterface $container) {
$this->container = $container;
$this->locale = $this->container->get('request_stack')->getMasterRequest()->getLocale();
$domainService = $this->container->get('app.domain_service');
$this->domain = $domainService->getDomain();
// TODO: File loading error check
$this->translator = new Translator($this->locale);
$this->translator->addLoader('yaml', new YamlFileLoader());
$this->translator->addResource('yaml', 'path/to/domain-translations/' . $this->domain->getSlug() . '/messages.' . $this->locale . '.yml', $this->locale);
}
public function getFilters() {
return array(
new \Twig_SimpleFilter('transDomain', array($this, 'transDomain')),
);
}
public function transDomain($s) {
$trans = $this->translator->trans($s);
// Falling back to default translation if custom isn't available
if ($trans == $s) {
$trans = $this->container->get('translator')->trans($s);
}
return $trans;
}
public function getName() {
return 'app_translation_extension';
}
}
Declared like that in app/config/services.yml:
app.domain_service:
class: AppBundle\Services\DomainService
arguments: [ #request_stack, #doctrine_mongodb, #translation.loader ]
And used like that in a Twig file:
{{ 'my.translation.key'|transDomain }}
I hope this helps, thanks!

Controller methods in Laravel

I was developing codeigniter app for last 2 years and since i started my mvc pattern styling from codeigniter itself, now i'm not a heavy command line user so at first i did had some learning curve with codeigniter but i crossed it and started developing apps with code igniter because we don't need to configure a lot and everything was inside one zip file but now as unfortunately codeigniter is dead and i'm just one person in my team i have to rely on other third party tools which are trusted by others so i decided to switch to laravel, now at starting it was way way tough to migrate from codeigniter because composer and every other stuff, but somehow i crossed that too, but i'm now confused with routing and other stuff and i've tried many tutorials but i'm still not able to see how can i migrate from application where i'm managing students, where they can change email, change phone number updated stuff, in codeigniter it was easy but i don't how to approach this stuff in routing of laravel, now this question sounds way to dumb for community who is already working on laravel but if you see from my point of view it is going to affect my bread and butter. This is how i use to approach in codeigniter
class Student extends CI_Controller{
// usual piece of code of constructor
function update_email()
{
// piece of code to update email
}
}
but now with laravel routing system and all i've no idea how to approach this a resource controller looks like this
<?php
class StudentController extends \BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param int $id
* #return Response
*/
public function update($id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id)
{
//
}
}
now every part is okay but how can i approach things where i've to update only email address or only phone number and stuff
Actually, in your question you have a RESTful controller which could be confusing for you at this time because you are new to Laravel and used CI, so probably you are very so much used with automating URL mapping without route. In this case, for ease, I suggest you to use a plain controller and that is almost same thing that you've did in CI but here in Laravel you have to declare route for every action. So, just create two routes like these:
Rouite::get('something/edit/{id}', array('uses' => 'StudentController#edit', 'as' => 'edit.record'));
Rouite::post('something/update/{id}', array('uses' => 'StudentController#update', 'as' => 'update.record'));
Then create a class/Controller and declare these methods:
class StudentController extends baseController {
// URL: http://example.com/something/edit/10 and it'll listen to GET request
public function edit($id) {
// $record = Load the record from database using the $id/10
// retuen View::make('editform')->with('record', $record);
}
// URL: http://example.com/something/update/10 and it'll listen to POST request
public function update($id) {
// Update the record using the $id/10
}
}
In your form, you need to use http://example.com/something/update/10 as action and you may use route('update.record') or url('something/update/10') to generate the action in the form. Read more on Laravel Documentation.
What you have created (or maybe rather generated) here is called Restful controller. It is some 'standard way' to manage CRUD actions (create/read/update/delete). However there is no need to do it this way. You can add in your controller whatever methods you want and not use Restful Controllers at all. That's your choice.
You can create in your function new method
function updateEmail()
{
// do here whatever you want
}
and in your routes.php file add new route:
Route::match(array('GET', 'POST'), '/changegemail', 'StudentController#updateEmail');
Now you can write your code for this method and it will work.

How to add custom debug data to ZendDebugToolbar

I am using the ZendDebugToolbar and it displays fine on the app, however, how do I send custom debug data to it? For example if I want to dump some key session information to it or a simple var_dump ?
I assume you are referring to the ZFDebug.
Since ZFDebug operates as a front-controller plugin that fires only on dispatchLoopShutdown(), it really only has access to variables that are available there, typically long-lived singleton instances from classes like Zend_Registry, Zend_Controller_Front (so you can get the request and response objects), etc. There is really no mechanism for direct communication between internal processes - like models and controllers - and the ZFDebug plugin.
So, for the kind of debugging about which you ask - var_dump() of your own custom variables and introspecting session data, presumably in other parts of system like services, controllers, models, etc - it might be easiest to simply add that data to Zend_Registry and then examine it later in ZFDebug under the Variables tab.
However, if you really want to add something new to the ZFDebug interface itself, then you can use its own internal plugin system to add tabs/panels to its interface.
It looks like you can simply create a class that implements the interface ZFDebug_Controller_Plugin_Debug_Plugin_Interface (link) and then register your custom plugin with the main $debug object during bootstrap.
Something like this:
/**
* See some of the other plugin implementations for examples of what could go into each of
* these methods.
*/
class My_ZFDebug_Controller_Plugin_SomePlugin implements ZFDebug_Controller_Plugin_Debug_Plugin_Interface
{
/**
* Has to return html code for the menu tab
*
* #return string
*/
public function getTab()
{
// #todo
}
/**
* Has to return html code for the content panel
*
* #return string
*/
public function getPanel()
{
// #todo
}
/**
* Has to return a unique identifier for the specific plugin
*
* #return string
*/
public function getIdentifier()
{
// #todo
}
/**
* Return the path to an icon
*
* #return string
*/
public function getIconData()
{
// #todo
}
}
Then in Bootstrap:
protected function _initZFDebug()
{
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('ZFDebug');
$options = array(
'plugins' => array('Variables',
'Database' => array('adapter' => $db),
'File' => array('basePath' => '/path/to/project'),
'Cache' => array('backend' => $cache->getBackend()),
'Exception')
);
$debug = new ZFDebug_Controller_Plugin_Debug($options);
// register your custom sub-plugin
$debug->registerPlugin(new My_ZFDebug_Controller_Plugin_SomePlugin());
$this->bootstrap('frontController');
$frontController = $this->getResource('frontController');
$frontController->registerPlugin($debug);
}
As usual, you will have to have autoloading in place for the namespace My_ or whatever you use for your custom class.
Remember, the same constraint as before applies: the only data available to your plugins are the long-lived instances that you can statically pull out of the ether; things like Zend_Registry, Zend_Controller_Front (hence request/response), etc.
#vinygarcia87 is the right answer.
Could not select it as the right answer because you typed it as a comment.

Categories