I'm using symfony 2.3 version and I want to configure two different from_email in fos_user configuration how is it possible and where to set my configuration.
I want to send welcome email after registration normal user using normaluser#gmail.com and send addition user welcome email using additionaluser#gmail.com
Plz suggest any solution.
You can do it by Using A Custom Mailer.
Create a custom service
Example:
<?php
namespace AppBundle\Mailer;
// implement all the needed methods
class CustomMailer implements MailerInterface
{
public function sendConfirmationEmailMessage(UserInterface $user)
{
$template = $this->parameters['confirmation.template'];
$url = $this->router->generate('fos_user_registration_confirm', array('token' => $user->getConfirmationToken()), UrlGeneratorInterface::ABSOLUTE_URL);
$rendered = $this->templating->render($template, array(
'user' => $user,
'confirmationUrl' => $url,
));
// implement the logic that decides which from_email to use
// change the from_email accordingly
$this->sendEmailMessage($rendered, $this->parameters['from_email']['confirmation'], (string) $user->getEmail());
}
}
and update the fos_user configuration to use your custom mailer
fos_user:
# ...
service:
mailer: app.custom_fos_user_mailer
Reference links:
http://symfony.com/doc/current/bundles/FOSUserBundle/emails.html#using-a-custom-mailer
https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Mailer/Mailer.php
Related
I use EasyadminBundle for the Backend of a Symfony application.
Two type of users have access to the back-end and I'd like to keep the right to delete to a small number of persons granted with ROLE_ADMIN.
I'd like to use item_permission parameter as for the other actions (such as show or list) :
Lieu:
class: App\Entity\Lieu
list:
item_permission: ROLE_ENCADRANT
delete:
item_permission: ROLE_ADMIN
But it's not working and I can still delete user when I'm logged with ROLE_ENCADRANT. Is there another solution ?
I currently accomplish it with:
Lieu:
class: App\Entity\Lieu
list:
item_permission: ROLE_ENCADRANT
action: ['-delete']
help: "the delete button is accessible in <b>Edit</b> view"
form:
item_permission: ROLE_ADMIN
I'm just looking for a 100% configuration solution, more elegant than mine.
Take a look at adding an action in the docs. The action can be tied to a route, which allows specifying what role may perform the action. The downside is that the list view button is present regardless of role. You can add a flash message to advise the user whether they have permission.
Here's an example from a project. Not quite what you're looking for but may get you started:
easyadmin.yaml:
Admin:
class: App\Entity\Admin
disabled_actions: ['new', 'edit']
list:
actions:
-
name: 'admin_enabler'
type: 'route'
label: 'Enable/Disable'
controller:
/**
* #Route("/enabler", name = "admin_enabler")
*/
public function enabler(Request $request)
{
$em = $this->getDoctrine()->getManager();
$id = $request->query->get('id');
$admin = $em->getRepository(Admin::class)->find($id);
$enabled = $admin->isEnabled();
if (!$admin->isActivator() && !$admin->hasRole('ROLE_SUPER_ADMIN')) {
$admin->setEnabled(!$enabled);
$em->persist($admin);
$em->flush();
} else {
$this->addFlash('danger', $admin->getFullName() . ' cannot be disabled');
}
return $this->redirectToRoute('easyadmin', array(
'action' => 'list',
'entity' => $request->query->get('entity'),
));
}
am creating own framework based on Sf2 commponents and i try to create router service.
I i need that service for generateUrl() method
protected function generateUrl($route, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
{
return $this->get('router')->generate($route, $parameters, $referenceType);
}
I try this
$container = new ContainerBuilder();
$container->setDefinition('router_loader', new Definition('Symfony\Component\Config\Loader\LoaderInterface'));
$container->setDefinition('router', new Definition('Symfony\Component\Routing\Router', array()));
And when i execute in my methodAction
$this->generateUrl('home');
he return me:
Catchable fatal error: Argument 1 passed to
Symfony\Component\Routing\Router::__construct() must be an instance of
Symfony\Component\Config\Loader\LoaderInterface, none given in
D:\xampp\htdocs\my_fw\vendor\symfony\routing\Router.php on line 95
looking on router constructor i see. I need that interface
public function __construct(LoaderInterface $loader, $resource, array $options = array(), RequestContext $context = null, LoggerInterface $logger = null)
how to avoid that implementation in service?
**New update:** routing.php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
// Routing
$routes = new RouteCollection();
// Home
$routes->add('home', new Route('/', array(
'_controller' => 'MyCompany\\Controller\\HomeController::indexAction',
)));
You are having this error because you are configuring the router service with no service definition the service definition should have your service arguments which is the source of your error because the container try to create the router with no arguments check this
For better use you can configure the router service in the service.yml/.xml file
Edit: The documentation page for the Routing component has detailed setup instructions
Try injecting the router_loader service as an argument into the router service. For this case you have to use the Symfony\Component\DependencyInjection\Reference class.
Routes have to be configured with a config file when using the all in one Router class. You have to use a FileLocator and a real Loader class, like the YamlFileLoader, you can't just use the interface (services generally can't be interfaces in Symfony).
The service container setup for the router service should look like this:
use Symfony\Component\DependencyInjection\Reference;
// Loads config files from the current directory, change this to
// your liking, or add more than one path
$container->setDefinition('router_config_locator', new Definition(
'Symfony\Component\Config\FileLocator', [[__DIR__]]
));
$container->setDefinition('router_loader', new Definition(
'Symfony\Component\DependencyInjection\Loader\YamlFileLoader', [
new Reference('router_config_locator'),
]
));
$container->setDefinition('router',
new Definition('Symfony\Component\Routing\Router', array(
'loader' => new Reference('router_loader'),
// Definition of routes in Yaml form
'resource' => 'routes.yml',
))
);
The routes.yml file contains your route definitions:
home:
path: /home
defaults: {_controller: "MyController:index"}
Also have a look at this documentation page about setting up the routing component, which also talks about setting up the routing without the all in one class and config file.
My symfony2 project is setup with normal YAML routes to any normal project.
Routes are setup with annotation and final URLs are
http://examplecom/artices/{id}
http://example.com/comments/{id}
I want to add prefix querystring to all the path, only if there is querystring called preview
So If I access http://example.com/?preview=something - I want this querystring to append to all the routes, so it continue to pass on every page and if this does not exist, then it will continue to be used as normally.
How can I accomplish this?
service.yml
parameters:
router.options.generator_base_class: "Acme\\DemoBundle\\Routing\\Generator\\UrlGenerator"
UrlGenerator.php
<?php
namespace Acme\DemoBundle\Routing\Generator;
use Symfony\Component\Routing\Generator\UrlGenerator as BaseUrlGenerator;
class UrlGenerator extends BaseUrlGenerator
{
protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens)
{
return parent::doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens).'?preview=something';
}
}
reference: http://h4cc.tumblr.com/post/56874277802/generate-external-urls-from-a-symfony2-route
Disclaimer: I'm slowly starting to get into Symfony and still have some problems understanding how the architecture works.
Currently I set up different Bundles (Services, right?) that should deliver different output for different routes. So far I got around adding a simple Twig template that loads stylesheets and scripts via Assetics and Twig-blocks. Now I added another Bundle that queries data via Buzz from a remote location, which worked fine as a standalone script, but I don't get around printing output in a Twig template.
The architecture of the original script is like the following (names made more generic):
Vendors - abstract class that serves as base for all remote request Bundles.
ServiceABC - abstract class that extends Vendors and defines Error handling and output preparation for the ABC service.
ClientXYZ - final class that extends Service_ABC, defines output parsing and normalization of the returned data.
This Bundle got a services.yml file:
# ~/MyApp/Bundle/ServiceABCBundle/Resources/config/services.yml
parameters:
service_abc_manager.class: MyApp\Bundle\ServiceABCBundle\Models\Service_ABC
location_manager.class: MyApp\Bundle\ServiceABCBundle\Models\Clients\ClientLocation
monitor_manager.class: MyApp\Bundle\ServiceABCBundle\Models\Clients\ClientMonitor
services:
service_abc_manager:
abstract: true
location_manager:
class: %location_manager.class%
parent: service_abc_manager
monitor_manager:
class: %monitor_manager.class%
parent: service_abc_manager
Names changed for easier reference - Typos by accident possible.
Now my problem/question is, that I don't really get behind the Symfony2 concept of how to get the output into the template.
namespace MyApp\Bundle\ServiceABCBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use MyApp\Bundle\ServiceABCBundle\Models\Clients\ClientLocation;
class DefaultController extends Controller
{
public function indexAction()
{
$services = array();
$services[] = $this->container->has('service_abc_manager');
$services[] = $this->container->has('location_manager');
$services[] = $this->container->has('client_location');
$services[] = $this->container->has('ClientLocation');
var_dump( $services );
$client = new ClientLocation();
var_dump( $client );
$response = $this->render(
'Service_ABC:Default:index.html.twig'
);
# $response->setCharset( 'utf-8' );
# $response->headers->set( 'Content-Type', 'text/html' );
return $response;
}
}
The output of the first array() named $services is always false and the $client = new ClientLocation(); throws an Exception that the class name wasn't found.
How can I access those Services/Bundle(parts)/Classes? And how would I render the output to a template?
Update
After I added the complete tree definition to Configuration()->getConfigTreeBuilder(), I'm able to see the definitions in the CLI:
class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root( 'myapp_service_abc' );
$rootNode
->children()
->scalarNode('service_abc_manager')->end()
->scalarNode('location_manager')->end()
->scalarNode('monitor_manager')->end()
->end()
;
return $treeBuilder;
}
}
The CLI command php app/console config:dump-reference myapp_service_abc now gives me the following output:
myapp_service_abc:
service_abc_manager: ~
location_manager: ~
monitor_manager: ~
I can as well see that the config data was loaded, when I var_dump( $loader ); inside MyAppServiceABCExtension right after $loader->load( 'services.yml' ); was called.
The output is the following:
object(Symfony\Component\DependencyInjection\Loader\YamlFileLoader)
protected 'container' =>
object(Symfony\Component\DependencyInjection\ContainerBuilder)
private 'definitions' =>
array
'service_abc_manager' =>
object(Symfony\Component\DependencyInjection\Definition)
'location_manager' =>
object(Symfony\Component\DependencyInjection\DefinitionDecorator)
private 'parent' => string 'service_abc_manager'
// etc.
The problem itself remains: There's still a FALSE return value inside DefaultController()->indexAction() when I var_dump( $this->container->has( 'service_abc_manager' );. I as well tried var_dump( $this->container->has( 'location_manager' ); and var_dump( $this->container->has( 'myapp.service_abc_manager' ); with the same result.
You should not call your services from the twig file, but from the controller.
The role of the controller is to :
validate your forms if there were a form posted
call your services to get some stuffs to display in a view
initialize forms if there is a form to display
return a Response that typically contains a rendered twig view
Do not call your services using something like $client = new ClientLocation();, but call it using the service container. This will allow you to take the whole power of the dependancy injection offered by Symfony2.
Your controller will look like :
<?php
namespace MyApp\Bundle\ServiceABCBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller
{
public function indexAction()
{
$locationService = $this->container->get('location_manager');
$someStuffs = $locationService->someMethod();
$response = $this->render(
'ServiceABCBundle:Default:index.html.twig', array('stuffs' => $someStuffs)
);
return $response;
}
}
From your twig file, you'll be able to use the stuffs variable :
{{ stuffs }} if your variable is a terminal ( a string, a number... )
{{ stuffs.attribute }} if your variable is an object or an array
About your services file, I am a bit confused, because your architecture does not look to be the standard Symfony2's one :
# ~/MyApp/Bundle/ServiceABCBundle/Resources/config/services.yml
Why your services.yml file isn't in the src/MyApp/SomethingBundle/Resources/config/ directory?
If you didn't already read it, I suggest you to have a look to the Symfony2 : The Big Picture documentation, which is the best way to start with Symfony2.
I'm currently implementing Doctrine filters in my Symfony2.1 project with the following setup:
<?php
namespace Acme\Bundle\Entity;
class Article {
/**
* #ORM\Column(type="string")
*/
private $status;
...
}
//app/config/config.yml
doctrine:
orm:
filters:
status:
class: Acme\Bundle\Filter\StatusFilter
enabled: false
....
//src/Acme/Bundle/Filter/StatusFilter.php
namespace Acme\Bundle\Filter;
use Acme\Bundle\Entity\Status;
class StatusFilter extends SQLFilter {
public function addFilterConstraint(ClassMetadata $target, $alias)
{
$filter =
$target->reflClass->implementsInterface('Acme\Bundle\Entity\Status')?
$alias . '.status = ' . Status::PUBLISHED : '';
return $filter;
}
}
Where Acme\Bundle\Entity\Status is just an interface.
The code is working as expected when the filter is enabled in config.yml.
The problem is that I cannot retrieve all articles for administration!
Is there a way to enable this filter for a certain bundle?
p.s. I know how to enable and disable the filter with the EntityManager,
I just cannot find the proper place to do it for the frontend Bundle.
my admin section is accessible by route prefix myadmin
www.example.com/myadmin/ -> admin section = disable filter (disabled by default in config)
www.example.com/... -> anything else = enable filter.
Looking at the Doctrine code, there are methods to enable and disable filters.
Once you have defined your filter in the config.yml file, you can enable/disable in a controller or service:
// 'status' is the unique name of the filter in the config file
$this->getDoctrine()->getManager()->getFilters()->enable('status');
$this->getDoctrine()->getManager()->getFilters()->disable('status');
Note: this was taken from Symfony 2.3. You would need to test this with previous versions of Symfony/Doctrine.
there is no notion of bundle at Doctrine level. The only way I see would be to detect which controller is used, by parsing its className (reflection, ...) during a kernel.request event, or a kernel.controller event.
Then, if you detect that your controller is in FrontendBundle, just disable/enable your doctrine filter.
If you prefer using routing to detect when to disable/enable, just use kernel.request event. You will have access to all request parameters, via $event->getRequest()->attributes->get('_controller') for example.