Closed reypm closed 10 years ago
Hi, you can define your own form type with the semantic config:
# app/config/config.yml
mremi_contact:
form:
type: your_custom_type
Then you can extend the form type provided by this bundle and remove/add what you want.
Maybe you could create a pull request to add some documentation about this?
@mremi Yes, I can create a PR and add some docs but first needs to get this working. This is the steps I followed:
Copy the content of file https://github.com/mremi/ContactBundle/blob/master/Form/Type/ContactType.php to FrontendBundle/Form/TanContactType.php
and fix namespaces and names.
This is the content of TanContactType.php
:
namespace Tan\FrontendBundle\Form\Type;
class TanContactType extends AbstractType
{
// The rest of the file
/**
* {@inheritdoc}
*/
public function getName()
{
return 'tan_contact';
}
}
Then in config I tried with:
mremi_contact:
form:
type: Tan\FrontendBundle\Form\TanContactType
name: contact_form
validation_groups: [Default]
subject_provider: mremi_contact.subject_provider.noop
captcha_disabled: false
captcha_type: genemu_captcha
Error:
Could not load type "Tan\FrontendBundle\Form\TanContactType"
And:
mremi_contact:
form:
type: tan_contact
name: contact_form
validation_groups: [Default]
subject_provider: mremi_contact.subject_provider.noop
captcha_disabled: false
captcha_type: genemu_captcha
Error:
Could not load type "tan_contact"
What I miss?
The second solution is the good one, with type: tan_contact
.
But you need to define this new service, for example:
# app/config/config.yml
services:
tan_frontend.contact_form_type:
class: Tan\FrontendBundle\Form\Type\TanContactType
tags:
- { name: form.type, alias: tan_contact }
# inject your needs...
# arguments: []
You can also do it in the xml format, see http://symfony.com/doc/current/book/forms.html#defining-your-forms-as-services
Good, I fixed that part but know I'm getting this error:
Catchable Fatal Error: Argument 1 passed to Tan\FrontendBundle \Form\TanContactType::__construct() must be an instance of Mremi\ContactBundle\Provider \SubjectProviderInterface, none given, called in /var/www/html/tan/var/cache /dev/appDevDebugProjectContainer.php on line 7016 and defined in /var/www/html/tan/src/Tan /FrontendBundle/Form/TanContactType.php line 42
I think due to I didn't inject the Interface, I was looking in MremiContactExtension.php
but didn't found which one to pass as arguments, any advice?
This fatal means you extend the ContactType
, so you have to inject the dependencies.
You have to do it yourself (following are default values):
# app/config/config.yml
services:
tan_frontend.contact_form_type:
class: Tan\FrontendBundle\Form\Type\TanContactType
tags:
- { name: form.type, alias: tan_contact }
arguments: ["@mremi_contact.subject_provider.noop", "Mremi\ContactBundle\Model\Contact", false, "genemu_captcha"]
@mremi Excellent, apparently it works now, I'll do some more test and if all go fine then I'll made a PR for docs to include this part as a suggestion will be nice if we could use Google reCaptcha instead this one on the Bundle, think on it as a new feature and if you need any help from me let me know
GenemuFormBundle already provides it: https://github.com/genemu/GenemuFormBundle/blob/master/Resources/doc/recaptcha/index.md . To use it, you need to configure it and then:
# app/config/config.yml
mremi_contact:
form:
captcha_type: genemu_recaptcha
Well something isn't good here since I'm getting this message all the time:
Please select a title
This is the content of TanContactType.php
:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->remove('title')
->add('firstName', 'text', array('label' => 'mremi_contact.form.first_name'))
->add('lastName', 'text', array('label' => 'mremi_contact.form.last_name'))
->add('company', 'text', array('label' => 'Compañía', 'mapped' => false))
->add('phone', 'text', array('label' => 'Teléfono(s)', 'mapped' => false))
->add('email', 'email', array('label' => 'mremi_contact.form.email'));
if ($subjects = $this->subjectProvider->getSubjects()) {
$builder->add('subject', 'choice', array(
'choices' => $subjects,
'label' => 'mremi_contact.form.subject',
));
}
else {
$builder->add('subject', 'text', array('label' => 'mremi_contact.form.subject'));
}
$builder->add('message', 'textarea', array('label' => 'mremi_contact.form.message'));
if (!$this->captchaDisabled) {
$builder->add('captcha', $this->captchaType, array(
'label' => 'mremi_contact.form.captcha',
'mapped' => false,
));
}
$builder->add('save', 'submit', array('label' => 'mremi_contact.form_submit'));
}
Why, if I'm removing the title, validator continue asking for them?
Try this:
src/Tan/FrontendBundle/Resources/config/validation.xml
to add a custom validation group (except for the title
):<?xml version="1.0" ?>
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping
http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
<class name="Mremi\ContactBundle\Model\Contact">
<property name="firstName">
<constraint name="NotBlank">
<option name="message">mremi_contact.first_name.blank</option>
<option name="groups">
<value>TanValidation</value>
</option>
</constraint>
<constraint name="Length">
<option name="min">2</option>
<option name="minMessage">mremi_contact.first_name.short</option>
<option name="max">50</option>
<option name="maxMessage">mremi_contact.first_name.long</option>
<option name="groups">
<value>TanValidation</value>
</option>
</constraint>
</property>
<property name="lastName">
<constraint name="NotBlank">
<option name="message">mremi_contact.last_name.blank</option>
<option name="groups">
<value>TanValidation</value>
</option>
</constraint>
<constraint name="Length">
<option name="min">2</option>
<option name="minMessage">mremi_contact.last_name.short</option>
<option name="max">50</option>
<option name="maxMessage">mremi_contact.last_name.long</option>
<option name="groups">
<value>TanValidation</value>
</option>
</constraint>
</property>
<property name="email">
<constraint name="NotBlank">
<option name="message">mremi_contact.email.blank</option>
<option name="groups">
<value>TanValidation</value>
</option>
</constraint>
<constraint name="Length">
<option name="min">2</option>
<option name="minMessage">mremi_contact.email.short</option>
<option name="max">254</option>
<option name="maxMessage">mremi_contact.email.long</option>
<option name="groups">
<value>TanValidation</value>
</option>
</constraint>
<constraint name="Email">
<option name="message">mremi_contact.email.invalid</option>
<option name="groups">
<value>TanValidation</value>
</option>
</constraint>
</property>
<property name="subject">
<constraint name="NotBlank">
<option name="message">mremi_contact.subject.blank</option>
<option name="groups">
<value>TanValidation</value>
</option>
</constraint>
<constraint name="Length">
<option name="min">2</option>
<option name="minMessage">mremi_contact.subject.short</option>
<option name="max">50</option>
<option name="maxMessage">mremi_contact.subject.long</option>
<option name="groups">
<value>TanValidation</value>
</option>
</constraint>
</property>
<property name="message">
<constraint name="NotBlank">
<option name="message">mremi_contact.message.blank</option>
<option name="groups">
<value>TanValidation</value>
</option>
</constraint>
<constraint name="Length">
<option name="min">2</option>
<option name="minMessage">mremi_contact.message.short</option>
<option name="max">500</option>
<option name="maxMessage">mremi_contact.message.long</option>
<option name="groups">
<value>TanValidation</value>
</option>
</constraint>
</property>
<property name="createdAt">
<constraint name="DateTime">
<option name="message">mremi_contact.created_at.invalid</option>
<option name="groups">
<value>TanValidation</value>
</option>
</constraint>
</property>
</class>
</constraint-mapping>
# app/config/config.yml
mremi_contact:
form:
validation_groups: [TanValidation]
Note also that:
validation.xml
parent::buildForm
method to avoid duplicated code@mremi I did the validation as you suggest but in .yml
format since I have others validators in there and it works, after fix the email.txt.twig
template and add my own additions as type has I get this error:
Method "company" for object "Mremi\ContactBundle\Model\Contact" does not exist in MremiContactBundle:Contact:email.txt.twig at line 5
This is the content of email.txt.twig
:
{% trans_default_domain 'MremiContactBundle' %}
{% block body_text %}
{% autoescape false %}
{{ 'mremi_contact.email_message_txt'|trans({
'%firstName%': contact.firstName,
'%lastName%': contact.lastName,
'%company%': contact.company,
'%phone%': contact.phone,
'%email%': contact.email,
'%message%': contact.message
}) }}
{% endautoescape %}
{% endblock %}
{% block body_html %}
{% autoescape false %}
{{ 'mremi_contact.email_message_html'|trans({
'%firstName%': contact.firstName,
'%lastName%': contact.lastName,
'%company%': contact.company,
'%phone%': contact.phone,
'%email%': contact.email,
'%message%': contact.message|nl2br
}) }}
{% endautoescape %}
{% endblock %}
What's wrong?
I did this in my form:
public function buildForm(FormBuilderInterface $builder, array $options) { parent::buildForm($builder, $options); $builder ->remove('title') ->add('company', 'text', array('label' => 'Compañía', 'mapped' => false)) ->add('phone', 'text', array('label' => 'Teléfono(s)', 'mapped' => false)); }
But this only render those two fields the rest wasn't rendered, is the call wrong?
@mremi Trying to find a solution for this problem I'm having I create a model at Tan\FrontendBundle\Model\TanContact.php
and extends or at least try from Mremi\ContactBundle\Model\Contact
. See the code below:
namespace Tan\FrontendBundle\Model;
use Mremi\ContactBundle\Model\Contact;
class TanContact extends Contact
{
/**
* @var string
*/
protected $company;
/**
* @var string
*/
protected $phone;
public function __construct()
{
parent::__construct();
}
public function setCompany($company)
{
$this->company = $company;
}
/**
* {@inheritdoc}
*/
public function getCompany()
{
return $this->company;
}
/**
* {@inheritdoc}
*/
public function setPhone($phone)
{
$this->phone = $phone;
}
/**
* {@inheritdoc}
*/
public function getPhone()
{
return $this->phone;
}
/**
* {@inheritdoc}
*/
public function toArray()
{
return array(
'title' => $this->title,
'firstName' => $this->firstName,
'lastName' => $this->lastName,
'email' => $this->email,
'subject' => $this->subject,
'message' => $this->message,
'company' => $this->company,
'phone' => $this->phone,
'createdAt' => $this->createdAt->format('c'),
);
}
}
But I still having the issue, any advice?
About your first problem, is the TanContactType
extend the ContactType
?
About the 2nd, you forgot to inject your model class into your form service tan_frontend.contact_form_type
(replace mine by yours).
No at the moment I wrote the post but now it's extending from ContactType
and ContactType
overwrite TanType
. This is the code of TanType
at this moment:
class TanContactType extends ContactType
{
public function __construct()
{
parent::__construct();
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder
->remove('title')
->add('company', 'text', array('label' => 'Compañía', 'mapped' => false))
->add('phone', 'text', array('label' => 'Teléfono(s)', 'mapped' => false));
}
}
I don't know what is wrong there. And where should I replace tan_frontend.contact_form_type
? This is my services definition at config.yml
:
services:
tan_frontend.contact_form_type:
class: Tan\FrontendBundle\Form\TanContactType
tags:
- { name: form.type, alias: tan_contact }
arguments: ["@mremi_contact.subject_provider.noop", "Mremi\ContactBundle\Model\Contact", false, "genemu_captcha"]
Should I pass my own Tan\FrontendBundle\ModelTanContact
model which extends from Mremi\ContactBundle\Model\Contact
instead of yours on the arguments
or not?
So if your form type extends mine, you should see all fields, including those of this bundle.
For the model, yes you have to replace the second argument because you override both form and model.
@mremi I get this error:
The data class "Tan\FrontendBund\Model\TanContact" is not a valid class.
This is the content of that file:
namespace Tan\FrontendBundle\Model;
use Mremi\ContactBundle\Model\Contact;
class TanContact extends Contact
{
protected $company;
protected $phone;
public function __construct()
{
parent::__construct();
}
public function setCompany($company)
{
$this->company = $company;
}
public function getCompany()
{
return $this->company;
}
public function setPhone($phone)
{
$this->phone = $phone;
}
public function getPhone()
{
return $this->phone;
}
public function toArray()
{
return array(
'title' => $this->title,
'firstName' => $this->firstName,
'lastName' => $this->lastName,
'email' => $this->email,
'subject' => $this->subject,
'message' => $this->message,
'company' => $this->company,
'phone' => $this->phone,
'createdAt' => $this->createdAt->format('c'),
);
}
}
What's wrong in that class?
The error message shows the namespace is wrong: Tan\FrontendBund\Model\TanContact
instead of Tan\FrontendBundle\Model\TanContact
Still having issues now this is the error:
The form's view data is expected to be an instance of class Tan\FrontendBundle\Model \TanContact, but is an instance of class Mremi\ContactBundle\Model\Contact
I though this is due to this 'data_class' => $this->class
in my custom type, but if I set this to null
what will be the result? The data_class
is only for persistence or it's used for something else?
Can you show me both mremi_contact
config and service definition of tan_frontend.contact_form_type
?
Sure,
services:
tan_frontend.contact_form_type:
class: Tan\FrontendBundle\Form\TanContactType
tags:
- { name: form.type, alias: tan_contact }
arguments: ["@mremi_contact.subject_provider.noop", "Tan\FrontendBundle\Model\TanContact", false, "genemu_captcha"]
mremi_contact:
form:
type: tan_contact
name: contact_form
validation_groups: [TanValidation]
subject_provider: mremi_contact.subject_provider.noop
captcha_disabled: false
captcha_type: genemu_captcha
And if this help this is how my TanContactType.php
looks:
namespace Tanane\FrontendBundle\Form;
use Tanane\FrontendBundle\Model\TananeContact;
use Mremi\ContactBundle\Form\Type\ContactType;
class TananeContactType extends ContactType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder
->remove('title')
->add('company', 'text', array('label' => 'Company', 'mapped' => false))
->add('phone', 'text', array('label' => 'Phone', 'mapped' => false));
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'tanane_contact';
}
}
You have to add contact_class: Tan\FrontendBundle\Model\TanContact
in the mremi_contact
config.
It is used by the contact manager to create a new contact instance.
Grrrrr now it says that my TanContactType
isn't compatible with FormTypeInterface::buildForm()
:
Compile Error: Declaration of Tan\FrontendBundle\Form\TanContactType::buildForm() must be compatible with Symfony\Component\Form\FormTypeInterface::buildForm(Symfony\Component \Form\FormBuilderInterface $builder, array $options)
My form looks like the one I leave in the post above
I think you forgot a use statement, can you show me the header of this file?
Sure,
namespace Tan\FrontendBundle\Form;
use Tan\FrontendBundle\Model\TanContact;
use Mremi\ContactBundle\Form\Type\ContactType;
So a use is missing for FormBuilderInterface
Still not working :-(:
Invalid title , possible values are: mr, mrs
And also the email I'm getting miss values for: %subject%
and the fields I'm adding %company%
and %phone%
so apparently the bundle isn't getting the right form since in TanContactType
I'm removing title
and setting up company, phone
This exception is raised because you removed the title field, but the setter is still called. You can override this method like this for instance:
public function setTitle($title)
{
if ($title) {
parent::setTitle($title);
}
}
About the email, can you dump the contact
variable in the confirmAction
(after clearing your cookie to be sure your session is clean)?
@paquitodev Something new?
@mremi sorry I was out for a few days but I'm back now. The title issue is fixed with your suggestion. This is the result of var_dump($contact)
:
object(Tan\FrontendBundle\Model\TanContact)[503]
protected 'company' => null
protected 'phone' => null
protected 'title' => null
protected 'firstName' => string 'Reynier' (length=7)
protected 'lastName' => string 'Perez' (length=5)
protected 'email' => string 'reynierpm@gmail.com' (length=19)
protected 'subject' => string 'Test' (length=4)
protected 'message' => string 'Test' (length=4)
protected 'createdAt' => object(DateTime)[117]
public 'date' => string '2014-08-02 07:57:53.000000' (length=26)
public 'timezone_type' => int 1
public 'timezone' => string '-04:30' (length=6)
And this is the email I'm getting in my inbox:
Subject: %subject% Send by: Reynier Perez From company: Email: reynierpm@gmail.com Phone: Message: Test
Something is wrong and I can't find where
In a previous comment, you pasted email.txt.twig
, still the same content? If so, subject
variable is not passed to the trans
Twig function.
About company
and phone
, is your TanContact::toArray
method still contains these properties as you show me previously? If so, can you dump the $contact
and $_POST
variables in the indexAction
when form is valid?
I fixed the subject
issue by adding this line: '%subject%': contact.subject,
to the email.txt.twig
. Now as for the other issue I'm getting this error:
An exception has been thrown during the rendering of a template ("Notice: Undefined index: in /var/www/html/tan/vendor/mremi/contact-bundle/Mremi/ContactBundle/Model/Contact.php line 197") in MremiContactBundle:Contact:confirm.html.twig at line 6.
Where this is the line 197
This exception is raised because you removed the title
field, so you have to override the template Contact/confirm.html.twig
.
This should be the last "problem" :)
Not at all, you're right I have removed the %title%
from confirm.html.twig
but still not getting company and phone in the email I receive, any other advice?
What about the second part of my answer from yesterday?
Yes, the toArray()
function still the same at Tan\FrontendBundle\Model\TanContact.php
, see below:
public function toArray()
{
return array(
'title' => $this->title,
'firstName' => $this->firstName,
'lastName' => $this->lastName,
'email' => $this->email,
'subject' => $this->subject,
'message' => $this->message,
'company' => $this->company,
'phone' => $this->phone,
'createdAt' => $this->createdAt->format('c'),
);
}
This is the output of var_dump($contact)
:
object(Tanane\FrontendBundle\Model\TananeContact)[988]
protected 'company' => null
protected 'phone' => null
protected 'title' => null
protected 'firstName' => string 'Reynier' (length=7)
protected 'lastName' => string 'Perez Mira' (length=10)
protected 'email' => string 'reynierpm@gmail.com' (length=19)
protected 'subject' => string 'Test' (length=4)
protected 'message' => string 'Testing' (length=7)
protected 'createdAt' =>
object(DateTime)[989]
public 'date' => string '2014-08-03 02:05:15.000000' (length=26)
public 'timezone_type' => int 3
public 'timezone' => string 'America/Caracas' (length=15)
And this is the output of var_dump($_POST)
array (size=1)
'contact_form' =>
array (size=10)
'firstName' => string 'Reynier' (length=7)
'lastName' => string 'Perez Mira' (length=10)
'email' => string 'reynierpm@gmail.com' (length=19)
'subject' => string 'Test' (length=4)
'message' => string 'Testing' (length=7)
'captcha' => string '9987' (length=4)
'save' => string '' (length=0)
'company' => string 'Freelance' (length=9)
'phone' => string '04241805609' (length=11)
'_token' => string 'OzIaoNUMnvLUoS4UvKOkNCevB50RHVUeXwUHt3G7rzg' (length=43)
Just remove the option mapped
to the company
and phone
fields in your TanContactType
;-)
@mremi thanks it's done I'll write the doc about this and made a PR
:+1:
:+1: Any update on a docs section for this @paquitodev ?
Not at the moment I'll made a PR with this but at this moment I'm very busy so you'll need to wait
Sent from my MotoG On Nov 30, 2014 4:17 PM, "webDEVILopers" notifications@github.com wrote:
[image: :+1:] Any update on a docs section for this @paquitodev https://github.com/paquitodev ?
— Reply to this email directly or view it on GitHub https://github.com/mremi/ContactBundle/issues/6#issuecomment-64999626.
Hi @mremi ,
This issue is itself a great doc, but it miss a point : I'd like to remove the title field, but I have activated the database storage. Currently, and following this step-by-step tutorial, I finally have a doctrine error sayin that de title field can't be null ( Constraint violation..) In your xml, nothin is specified, so it's required by default. Do you have an idea about how to override the mapping ?
Thx !
Hi @numerogeek ,
The mapping file should be updated with nullable="true"
for all fields except createdAt
. Thus, all the use cases will be covered.
Do you want to do it?
It's possible to remove fields like for example title and add new ones like phone and company? How I do that and where? In
ContactType.php
?