Easyadmin is not recognizing boolean type - symfony

I am trying to implement a backend using easyadmin, I think its a great idea and I love the implementation... so far is going well, but I have a little problem, I want to show in the form a boolean field, for ex: 'published', my configuration looks like this:
Blog:
label: 'Posts list'
class: MyCompany\MyBundle\Entity\Post
list:
fields: ['title', 'published']
new:
fields:
- 'title'
- 'summary'
- 'body'
- { property: 'published', type: 'boolean' }
When I run this code, I get the error:
Could not load type "boolean"
This is how I define the field in the Entity:
/**
*
* #ORM\Column(name="published", type="boolean", length=1)
*/
protected $published = 1;

I know it's been a while since this question's posted, but for anyone still getting this error, in easyadmin documentation (https://github.com/javiereguiluz/EasyAdminBundle/blob/master/Resources/doc/book/4-edit-new-configuration.md) it is specified which types we need to use for each scenario (list, edit views).
In your question (edit scenario) so far the only workaround is to use "checkbox"as type in config.yml. Edit view only accepts Symfony Form Types (http://symfony.com/doc/current/reference/forms/types.html).

You don't have to specify type in configuration yml file. It will take automatically from entity.

Related

SonataAdmin create entity with boolean field

I have this entity, if I create a record like this.
$synopsis = new Synopsis();
$synopsis->setPartOne("a");
$synopsis->setPartTwo("b");
$synopsis->setTitle("A");
$synopsis->setSubtitle("B");
$synopsis->setEnabled(false);
$em->persist($synopsis);
$em->flush();
And then I go to my Admin, I see the enabled field to "no" which is expected.
But now, If I use the sonata admin new form field, even if I choose enabled "no", the record is created with enabled = true. And I don't really see why it would be like that.
Here is what I have in my SynopsisAdmin
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('title', TextType::class);
$formMapper->add('subtitle', TextType::class);
$formMapper->add('partOne', TextAreaType::class);
$formMapper->add('partTwo', TextAreaType::class);
$formMapper->add('enabled', BooleanType::class);
}
This is how the enabled field is defined in the entity
/**
* #ORM\Column(type="boolean")
*/
private $enabled;
Thanks for your help.
EDIT: Fun facts too, even if I see no in the sonata view list, when I go to the form view, I see yes instead.
I suspect an error within the sonata core functionnality.
I think you should use the CheckboxType instead of the BooleanType for your Form fields.
Looks like the BooleanType is ment for the list, show and grid actions.
https://symfony.com/doc/master/bundles/SonataAdminBundle/reference/field_types.html
Update
To use the BooleanType you have to set the 'transform' option to true.
This transforms your boolean value to the YES/NO options in the BooleanType:
$formMapper
->add('enabled', BooleanType::class, [
'transform' => true
])

Set up non-persistent relation in Doctrine 2

I have an object $user that has a one to many relation with $establishment. I can use:
$user->getEstablishments();
The user can select a stablishment to work on. I have this method that I call in the controller:
$user->setCurrentEstablishment($establishment);
And this one that I call in the view:
$establishment = $user->getCurrentEstablishment();
I want to be able to call:
$user->setCurrentEstablishmentBy Slug($establishment_slug);
where the slug is a string, and let the user object look for the establishment.
Doctrine discourages the practice of accessing the Entity Manager inside the Entity object, but I think that using it in the controller is even worse.
I suspect that some special Doctrine annotation exists that takes care of non persistent relations like this, or some method other than serving the Entity Manager through a service should be used here. Some easy way of referencing other entities from inside the model.
¿Is there any? ¿How could I do that?
There is no Annotation in Doctrine which could convert slug into object.
What can help You is ParamConverter, with it you can automatically convert slug from query into object. But it still must be used in Controller.
Example usage:
/**
* #Route("/some-route/{slug}")
* #ParamConverter("object", class="AppBundle:Establishment", options={"id" = "slug", "repository_method" = "findEstablishmentBySlug"})
*/
public function slugAction(Establishment $object)
{
...
Docs about param converter: http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html

Best practice symfony validation

I'm asking myself about the validation when an user sends a form... I saw the documentation and a tutorial. They explain 2 ways to valid datas:
Documentation:
You have to create the file:
/Resources/config/validation.yml
Then add something like that:
Acme\BlogBundle\Entity\Author:
properties:
name:
- NotBlank: ~
Tutorial I saw on Internet:
They add constraints directly in Entity like:
use Symfony\Component\Validator\Constraints as Assert;
/**
* #var string $title
*
* #ORM\Column(name="title", type="string", length=255)
* #Assert\MinLength(10)
*/
private $title;
There is a best pratice? Should I write all constraints in validation.yml or in my entities? Is it possible to face a form without entity behind?
Benefit from separate file:
You have all constraints in only one file
Benefit from entity file:
You have sql constaints with your form constaints and you have the field type.
So, what should I use? Or no one cares about that?
Edit: I don't find any information about how to add a variable in validation.yml like:
Acme\BlogBundle\Entity\Author:
constraints:
- Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity:
fields: [name]
message: {{ name }} isn't available
In Entity:
#Assert\UniqueEntity(message='{{ name }} isn't available'
Best regards,
Should I write all constraints in validation.yml or in my entities?
You can, but you don't have to, it is more about personal preference. Personally, I prefer to validate input in my forms, like this:
$builder->add('contactPerson', 'text', array(
'label' => 'Contact person',
'constraints' => array(
new NotBlank(array('message' => 'This field can not be empty.'))
),
'required' => true,
));
Is it possible to face a form without entity behind?
Yes it is, but usually it is better to use entity behind. If you want to leave out the entity behind form, you just remove this line from your form's setDefaultOptions method:
'data_class' => '...'
After submitting the form, you can access form data by using $form->getData().
Benefit from separate file: You have all constraints in only one file
Benefit from entity file: You have sql constaints with your form
constaints and you have the field type.
So, what should I use? Or no one cares about that?
This is more about personal preference. Personally, I prefer to have validation and form in the same time. Searching for the validation in some other file when I want to make a change to some of my fields in form would take me more time.

No entity manager defined for class DateTime

I have started using the Sonata Admin bundle and I was following the example on how to map an entity with the bundle to create an administrative interface.
I created an entity called Post and this is the configuration yml file:
Emiliano\PostsBundle\Entity\Post:
type: entity
table: null
repositoryClass: Emiliano\PostsBundle\Entity\PostRepository
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
title:
type: string
column: Title
lenght: 100
published:
type: boolean
column: Published
publishingDate:
type: datetime
column: Publishing_Date
nullable: TRUE
lifecycleCallbacks: { }
Then in my Admin class I have the configureFormFields method:
protected function configureFormFields(FormMapper $formMapper) {
$formMapper->add('title', 'text')
->add('published', 'checkbox', array('required' => false))
->add('publishingDate', 'sonata_type_model_hidden');
}
I found the sonata_type_model_hidden on the sonata admin documentation. What I would like to achieve is to programmatically handle the publishing date (e.g. set the date only if the checkbox published is checked) hiding the implementation to the user.
Everything works fine for create, delete and read, when it comes to modify an entity I get this message in the stacktrace:
No entity manager defined for class DateTime
In sonata-project/doctrine-orm-admin-bundle/Sonata/DoctrineORMAdminBundle/Model/ModelManager.php at line 214
If I show the field everything works fine, I tried also to use:
->add('publishingDate', 'hidden');
without success.
What is exactly the problem here? Is it because Sonata Admin tries to fill a form with the entity values and for publishingDate there's a DateTime while in the form specification I wrote a sonata_type_model_hidden? If so, how can I circumvent this?
sonata_type_model_hidden isn't just hidden field genereator, according to documentation:
sonata_type_model_hidden will use an instance of ModelHiddenType to render hidden field. The value of hidden field is identifier of related entity.
If I understand your problem, You want to set publishing date only when field published == true
You could use entity preSave/preUpdate lifecycle callback for eaxmple
public function preSave()
{
/**
* Check if item is published
*/
if($this->getPublished()) {
$this->setPublishingDate(new \DateTime());
} else {
$this->setPublishingDate(null);
}
}
and remove publishingDate field from SonataAdmin form.

How do you define the getter to use in a CRUD form besides defining __toString()?

If you've used Symfony2's generators to create CRUD forms from database entities, you may wind with an error like this on the "create new record" screen:
StringCastException: A "__toString()" method was not found on the objects of type
"ScrumBoard\ServiceBundle\Entity\Users" passed to the choice field. To read a
custom getter instead, set the option "property" to the desired property path.
If I'm reading this correctly, the problem is that it needs to display a dropdown list of users for the record I'm creating, but it doesn't know how to turn a "User" entity into a string.
Defining the __toString() method on my Users entity class fixes the problem. However, I can see right from the text of the error message that there is an alternative: read a customer getter instead, which is accomplished by "[setting] the option "property" to the desired property path."
This sounds like some kind of annotation. But in my searching, I can't figure out what that is. Because I want to have a thorough understanding of Symfony2--can someone help me out?
Thanks!
When creating an entity ( superclass of choice ) field type in a form. You need to specify which property shall be used for the labels/values otherwise the __toString() method of the underlying object will be used.
$builder->add('users', 'entity', array(
'class' => 'AcmeHelloBundle:User',
'property' => 'username',
));
Read more about it in the Form Type Reference for entity field Type.
Additional Info
A __toString() related error generally often comes from twig when generating a route in a template aswell.
if outputting an object an object in twig with {{ object }} ... twig will call the object'S __toString method.
This "trick" is used by the crud generated templates with SensioGeneratorBundle.
{{ path('article_show', {'id': article}) }}
with the route being something like this:
article_show:
pattern: /article/{id}
defaults: { _controller: AcmeArticleBundle:Article:show }
If you have the __toString method in your Article entity set to something like ...
public function __toString()
{
return $this->id;
}
... you dont't need to type
{{ path('article_show', {'id': article.id) }}
Generally Twig will automatically output Article::getId() if you use
{{ article.id }}
Hope this clarifies your findings.

Resources