This Symfony bundle features a newsletter registration template with attention to data avoidance for privacy protection:
To reduce the amount of unwanted emails, the following ideas are implemented:
Finally, the bundle tries to be developer friendly:
composer req webfactory/newsletter-registration-bundle
activate in src/bundles.php
:
<?php
return [
// ...
Webfactory\NewsletterRegistrationBundle\WebfactoryNewsletterRegistrationBundle::class => ['all' => true],
];
Implement all src/Entity/*Interface.php
in your project. The easiest way, if you don't mind the biased namespaces, is
to copy the templates:
mkdir src/AppBundle/Newsletter
cp vendor/webfactory/newsletter-registration-bundle/app-class-templates/* src/AppBundle/Newsletter/*
If you want to implement the interfaces by yourself, you could extend the corresponding abstract classes like in the templates above and add class level Doctrine ORM annotations (find template for them in the abstract classes). For customizing, see the "Customizing" section below.
In either case, configure Doctrine's interface mapping to deal with your custom entity class:
// config.yml
doctrine:
orm:
resolve_target_entities:
\Webfactory\NewsletterRegistrationBundle\Entity\NewsletterInterface: '\AppBundle\Entity\Newsletter'
Side node: The templates and example above assume that you want to keep your Newsletter classes inside a Newsletter directory in your AppBundle. If you choose to do so, you might need to configure Doctrine to load the entities:
// config.yml
doctrine:
orm:
entity_managers:
default:
mappings:
NewsletterRegistrationBundle:
type: annotation
prefix: AppBundle\Newsletter\Entity\
dir: "%kernel.root_dir%/AppBundle/Newsletter/Entity/"
is_bundle: false
Update your database schema, e.g. with a migration.
Configure the bundle:
// config.yml
parameters:
webfactory.newsletter_registration.email_sender_address: 'newsletter@example.com'
webfactory.newsletter_registration.secret: 'your-secret' # do not use Symfony's %secret%!
webfactory.newsletter_registration.time_limit_for_opt_in_in_hours: 72 # default value
webfactory.newsletter_registration.minimal_interval_between_op_in_emails_in_hours: 1 # default value
webfactory.newsletter_registration.block_email_address_duration_in_days: 30 # default value
Include the RegistrationController in your routing:
// routing.yml
newsletter:
prefix: /newsletter
type: annotation
resource: '@WebfactoryNewsletterRegistrationBundle/Controller/RegistrationController.php'
The RegistrationController gets some Interfaces injected in its constructor. Alias these interfaces with your own implementations:
// src/services.yml
services:
AppBundle\Newsletter\Entity\NewsletterRepository:
factory:
- '@doctrine.orm.entity_manager'
- 'getRepository'
arguments:
- 'AppBundle\Entity\Newsletter'
Webfactory\NewsletterRegistrationBundle\Entity\NewsletterRepositoryInterface:
alias: 'AppBundle\Newsletter\Entity\NewsletterRepository'
AppBundle\Newsletter\Entity\PendingOptInRepository:
factory:
- '@doctrine.orm.entity_manager'
- 'getRepository'
arguments:
- 'AppBundle\Entity\PendingOptIn'
Webfactory\NewsletterRegistrationBundle\Entity\PendingOptInRepositoryInterface:
alias: 'AppBundle\Newsletter\Entity\PendingOptInRepository'
AppBundle\Newsletter\Entity\RecipientRepository:
factory:
- '@doctrine.orm.entity_manager'
- 'getRepository'
arguments:
- 'AppBundle\Entity\Recipient'
Webfactory\NewsletterRegistrationBundle\Entity\RecipientRepositoryInterface:
alias: 'AppBundle\Newsletter\Entity\RecipientRepository'
bin/console newsletter-registration:delete-outdated-pending-opt-ins
bin/console newsletter-registration:delete-outdated-blocked-email-addresses
Use the regular symfony mechanism for overriding templates.
Start with:
mkdir src/Resources/WebfactoryNewsletterRegistrationBundle -p
cp -r vendor/webfactory/newsletter-registration-bundle/src/Resources/views src/Resources/WebfactoryNewsletterRegistrationBundle
Use the translation component's overwrite mechanism.
If you add new languages or fix mistakes, please consider contributing via pull request.
AppBundle\Entity\PendingOptIn
and AppBundle\Entity\Recipient
in the example
above). Maybe you want to extends their respective Repositories, too.Webfactory\NewsletterRegistrationBundle\Entity\PendingOptInFactoryInterface
and Webfactory\NewsletterRegistrationBundle\Entity\RecpientFactoryInterface
,
as they are responsible for creating your entities from the corresponding form data. Alias the interfaces to your
implementations, e.g.
// services.yml
services:
Webfactory\NewsletterRegistrationBundle\Entity\PendingOptInFactoryInterface:
alias: 'App\Newsletter\Entity\PendingOptInFactory'
If you can pin down your modifications to the StartRegistration
, ConfirmRegistration
, EditRegistration
or
DeleteRegistration
tasks, you are probably better off implementing your own versions of the respective interface
(maybe extending the task class) and aliasing the interface service to them.
For greater flexibility, you can replace the RegistrationController with your own, e.g.:
<?php
namespace AppBundle\Newsletter;
class Controller extends \Webfactory\NewsletterRegistrationBundle\Controller\Controller
{
// ...
}
Don't forget to configure your routing and services accordingly.