Is there any way to access session variable from ClassGeneratorConfiguration in symfony1.4?
I need it because i want to set default filter field values according to session variable.
You can get it from the context (I think there is no other way) and than you can use the getFilterDefaults method to set a default value for a field or use the getFilterFormOptions to pass the user into the form as an option and implement the logic there. This is how I usally do it:
class productGeneratorConfiguration extends BaseProductGeneratorConfiguration
{
/**
* #return sfBasicSecurityUser
*/
public function getUser()
{
return sfContext::getInstance()->getUser();
}
public function getFilterFormOptions()
{
return array('user' => $this->getUser());
}
public function getFilterDefaults()
{
return array(
'some_field' => $this->getUser()->getSomething() ? 'a' : 'b';
);
}
}
You can access session variable like follows:
$varname = sfContext::getInstance->getUser()->getAttribute('your_field');
Related
I would like to know if you can validate a field depending on its value from a form in Symfony?
For example, I have an url and a name within a form associated to it. If the value of the name is 'instagram' let's say, I want that the url to be validated by the class Instagram Validator and so on. I wrote a switch but I get the error:
Call to a member function buildViolation() on null
What I've tried:
public function validateURL($url, $name)
{
$message = '';
switch ($name) {
case "Instagram":
$instagramValidator = new InstagramValidator();
$instagramValidator->validate($url, new Url());
break;
default:
return;
}
return $message;
}
InstagramValidator:
class InstagramValidator extends ConstraintValidator
{
/**
* {#inheritdoc}
*/
public function validate($url, Constraint $constraint)
{
if (!preg_match('/(?:http:\/\/)?(?:www\.)?instagram\.com\/(?:(?:\w)*#!\/)?(?:pages\/)?(?:[\w\-]*\/)*([\w\-]*)/', $url)) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($url))
->addViolation();
}
}
}
So there is a way to handle this?
You've got this error because you didn't pass $context to validator's constructor.
Create your own constraint and use it via Validation::createValidator()->validate():
use Symfony\Component\Validator\Constraints\Regex;
class Instagram extends Regex
{
public function __construct()
{
parent::__construct(['pattern' => '/your regex/']);
}
public function validatedBy(): string
{
return Regex::class . 'Validator';
}
}
Now you can use it:
$violations = Validation::createValidator()->validate($url, new Instagram());
Also, you can use your own validator, you just have to set it in validatedBy function of your constraint.
I would like to visit recursively each property of the serializing Entity, check if a string is set and verify that the metadata property is properly set to string, otherwise change it in order to allow the serialization.
Imagine a users property which is an ArrayCollection, but I force the value to be a string in corner cases.
I set a SerializationSubscriber to catch the serializer.pre_serialize event, but I'm not finding any doc for take advantage of the Visitor and surroundings.
Any hint?
class MyEventSubscriber implements JMS\Serializer\EventDispatcher\EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
array('event' => 'serializer.pre_serialize', 'method' => 'onPreSerialize'),
);
}
public function onPreSerialize(JMS\Serializer\EventDispatcher\PreSerializeEvent $event)
{
/*
* #var YourEntity $object
*/
$object = $event->getObject();
$reflect = new \ReflectionClass($foo);
$props = $reflect->getProperties(\ReflectionProperty::IS_PRIVATE);
foreach ($props as $prop) {
$method = 'get'.ucfirst($prop->getName());
// here is call of methods like getId(), getName() etc,
// depending on name of entity properties
$object->$method();
}
}
}
I've got this strange problem, here is example usage of my custom ThingType class.
->add('photos', 'namespace\Form\Type\ThingType', [
'required' => false,
])
if the field name is photos everything works as expected, but if I change my entity field to let's say photosi, run generate entities, and change the form field name, this error is thrown:
Neither the property "photosi" nor one of the methods
"addPhotosus()"/"removePhotosus()", "setPhotosi()", "photosi()",
"__set()" or "__call()" exist and have public access in class
"AppBundle\Entity\Product".
I guess the problem comes from Symfony trying to generate getter method name for my entity. Why is this addPhotosus method name generated? How can I solve this?
EDIT:
I'm using model transformer when showing the data to the user.
$builder->addModelTransformer(new CallbackTransformer(
function ($imagesAsText) {
if (!$imagesAsText) {
return null;
}
$newImages = [];
foreach($imagesAsText as $img) {
$newImages[] = $img->getID();
}
return implode(',', $newImages);
},
function ($textAsImages) use ($repo) {
$images = [];
foreach(explode(',', $textAsImages) as $imgID) {
$img = $repo->findOneById($imgID);
if ($img) {
$images[] = $img;
}
}
return $images;
}
));
The actual field is TextType::class with entity ids in it for example 1,10,32,51. The model transformer transforms this data to entities. Setting 'data_class' to my form type seems irrelevant, because the actual form type is a part of entity. I mean I have Product entity and Photo entity, photos is array of photo entity. So in my ThingType, what data_class should I use, photo or product?
Thanks
The fist parameter of the add method for a form, should be one of the mapped attributes of the data_class of the form, usually selected inside the form as
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Product'
));
}
That isn't related to the form name. So , you are trying to access to a "photosi" attribute inside your Product class.
Hope this help you.
Ok so for the first point you need to remember that Symfony is looking for setXX() and getXX()method in your entity for each entry of your form.
If you change your variable name you need to update the form :
->add('newName', XXType::class, [
'required' => false,
])
and you're entity by changing the variable
class Entity
{
/**
* #ORM\Column(type="string", length=255)
*/
private $newName;
public function getOldName(){
return $this->$oldName;
}
public function setOldName(oldName){
$this->oldName = $oldName;
return $this
}
}
then run the command
php bin/console make:entity --regenerate
and symfony will upload your entity by itself
class Entity
{
/**
* #ORM\Column(type="string", length=255)
* #SerializedName("title")
* #Groups({"calendar"})
*/
private $newName;
public function getOldName(){
return $this->$oldName;
}
public function setOldName($oldName){
$this->oldName = $oldName;
return $this
}
public function getNewName(){
return $this->newName;
}
public function setNewName($newName){
$this->newName = $newName;
return $this
}
note that the old get and set method are not deleted by the script
note as well that in your specific case of photosi, symfonyguess that the "i" is a plural mark and look for addPhotosus() methods
For the edit it looks very unclear and has nothing to do with the first question. Consider reading : doc on collectionType
Just getting started with Symfony, so please bear with me here.
I have an Entity with a field "myField" that is stored in the database as an ENUM with values 'Y' or 'N'. (This is an old DB schema that I'm working with and trying to use symfony as an app to manipulate the data).
I want to represent "myField" with a checkbox for on or off (0 or 1). When the form is saved, how would I transform the value to the appropriate 'Y' or 'N' value before persisting it to the database?
I looked at Data Transformers, and that may be where I need to go, but it seems so silly to create a new class and file just to convert that data. This is a very simple transformation.
Maybe instead I would just change the setMyField($myField) () {} setter method on the Entity to convert the data there? And likewise, convert it back in getMyField() {}? But doesn't Doctrine also use the setter methods? If so, then when Doctrine set a value, it would be the proper value (0 or 1) from the database and wouldn't need transforming. But if the form set the value, it would need transforming.
Here's the action code:
public function newAction(Request $request)
{
$course = new Course();
$form = $this->createForm(new CourseForm(), $course);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($course);
$em->flush();
return $this->redirect($this->generateUrl('courses'));
}
return $this->render('PucsTestBundle:Course:new.html.twig', array(
'form' => $form->createView(),
));
}
I think I could convert the data myself in the controller just before I call handleRequest, but that is probably not good practice.
Additionally, I have a field in the database "days" that is just a VARCHAR that would be something like MTW for Monday, Tuesday Wednesday. I want to present a checkbox for all these values, and then post-process the form submission to convert the data to the appropriate single value.
You should use a custom Doctrine Type as defined here in the documentation
<?php
namespace My\Project\Types;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* My custom datatype.
*/
class OldBooleanType extends Type
{
const NAME = 'OldBoolean'; // modify to match your type name
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return 'OldBoolean';
}
public function convertToPHPValue($value, AbstractPlatform $platform)
{
if ($value === 'Y'){
return true;
}
if ($value === 'N'){
return false;
}
return null;
}
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
if ($value === true){
return 'Y';
}
if ($value === false){
return 'N';
}
return null;
}
public function getName()
{
return self::NAME;
}
}
From Symfony documentation: http://symfony.com/doc/current/cookbook/form/data_transformers.html
Data transformers are used to translate the data for a field into a format that can be displayed in a form (and back on submit).
I try to pass my variable to constraint in form validator, but can't.
i'm doing that:
$payForm = $this->createForm(new CableTVPayType(), null, array('balance' => $balance));
And in CableTVPayType:
public function getDefaultOptions(array $options)
{
$maxSumm = $options['balance'] - 100;
[...]
It works fine, my maxSumm is what i want, but Symfiony checks $options array. 'balance' isn't a default option, and complain about this:
The option "balance" does not exist
Is there another, more right way to pass custom variable to validation?
Use the constructor for stuff to be used by all instances of a type. For example, your type might need an entity manager for it to work. It will be reused across all the form instances.
For instance specific stuff use options. If you use the constructor for instance specific stuff, all the instances will get the value you pass to the constructor of the first instance.
/**
* #FormType
*/
class PayType extends AbstractType {
private $someService;
/**
* #InjectParams
*/
public function __construct(SomeService $someService)
{
$this->someService = $someService;
}
public function getDefaultOptions(array $options)
{
return array(
'balance' => 0
);
}
public function getName()
{
return 'pay';
}
}
$form = $this->createForm('pay', null, array('balance' => $balance));
Note that the #FormType annotation registers the type as a service. It allows you to use the type's name instead of creating an instance manually. It gets even more convenient when a type needs a service to be injected into it. You use just the name — pay in this case — instead of something like this:
$form = $this->createForm(new PayType($this->get('some_service')), null, array(
'balance' => $balance
));
Done with this!
Crate variable for a class, and passing value to it through construct method
class CableTVPayType extends AbstractType {
private $maxSumm;
public function __construct($maxSumm) {
$this->maxSumm = $maxSumm;
}
Create form with argument
$payForm = $this->createForm(new CableTVPayType($someValue));
Now i can use this variable as i want in my form.