I'm currently working on an OroPlatform project and I need to add a custom field on the BusinessUnit core entity.
I have read the Oro documentation section about the way to extend core entities : https://doc.oroinc.com/backend/entities/extend-entities/#id1
<?php
namespace MyBundle\Bundle\AppBundle\Migrations\Schema\v1_0;
use Doctrine\DBAL\Schema\Schema;
use Oro\Bundle\EntityExtendBundle\EntityConfig\ExtendScope;
use Oro\Bundle\MigrationBundle\Migration\Migration;
use Oro\Bundle\MigrationBundle\Migration\QueryBag;
class AddColumnsToBusinessUnit implements Migration
{
public function up(Schema $schema, QueryBag $queries)
{
$table = $schema->getTable('oro_business_unit');
$table->addColumn('siret', 'string', [
'oro_options' => [
'extend' => ['owner' => ExtendScope::OWNER_CUSTOM],
'entity' => ['label' => 'siret'],
],
]);
}
}
When I run the command symfony console oro:migration:load --force, it works and the migration is applied to my database.
Now, I want a required field. I have seen the instruction 'notnull' => true to setup a non nullable field on the database.
Everything works well, but my field hasn't any JavaScript validation on the organization/business_unit/create route. Any ideas ?
You can validate the new field by extending the validation metadata that is already defined for the core entity you are extending.
To do this, please follow the official Symfony documentation and use the YML format:
https://symfony.com/doc/4.4/validation.html#constraint-configuration
The constraint that you can use for the field is "not blank."
Here is an example:
# src/<YourBundlePath>/Resources/config/validation.yml
Oro\Bundle\OrganizationBundle\Entity\BusinessUnit:
properties:
siret:
- NotBlank: ~
Related
I just upgraded API platform to version 3.0.
After the few classical modifications linked to the version upgrade, and despite the use of: php bin/console api:upgrade-resource
I notice that my entities are not exposed anymore when I go to the API documentation and if I try to access an endpoint, I get a route error:
No route found for "GET https://127.0.0.1:9000/api/XXX
I replaced all the ApiResource uses in my entities and rewrote my annotations.
example of an entity:
<?php
namespace App\Entity\Test;
use ApiPlatform\Metadata\ApiResource;
#[ApiResource(
collectionOperations: [
'get',
'post' => [
'denormalization_context' => ['groups' => ['create:xxx']]
]
],
itemOperations: [
'get' => [
'normalization_context' => ['groups' => ['read:fully:xxx']]
],
'put' => [
'denormalization_context' => ['groups' => ['update:xxx']]
],
'delete'
],
normalizationContext: ['groups' => ['read:xxx']]
)]
class Departement
{
....
}
Thanks in advance!
ok so, i update a little entity manually and now she is exposed !
<?php
namespace App\Entity\Agorha;
//use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use App\Entity\ChoixEcole;
use App\Repository\Agorha\EcoleRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[ORM\Entity(repositoryClass: EcoleRepository::class)]
#[ORM\Table(name: "agorha_ecole")]
#[ORM\HasLifecycleCallbacks()]
#[ApiResource(operations: [
new Get(),
new GetCollection()
])]
#[
UniqueEntity('code')
]
class Ecole
{
#[ORM\Id()]
#[ORM\GeneratedValue()]
#[ORM\Column(type: "integer")]
private $id;
i didn't see the results of the upgrade command, which ended up being an error and therefore did nothing.
in fact, it does not seem to exist
Command "api:upgrade-resource" is not defined.
anyone would know why ?
It looks like your entities are still in the <= v2.6 format despite your call to the api:upgrade-resource command.
See the migration documentation: instead of
'get', 'post', etc. you should use new Metadata classes Get(), Post(), etc.
Are you sure that the migration command returned no error?
In my case (migration from 2.6 to 3.0) the migration command was not available for unknwon reason (not found from the console).
Try migrating manually one entity to the new format and watch your openApi documentation to see if your endpoints are back.
Edit: Why didn't api:upgrade-resource work ?
As far as I understand, the migration command is provided in v2.7 to prepare migration to 3.0 but has been dropped from v3.0. So the proper way to migrate according to the doc is:
migrate to 2.7
call api:upgrade-resource and check all is working
THEN migrate to 3.0
like #MendelYev says i should run the api upgrade command before upgrade.
now i ve to upgrade manually my entities using PHP attributes and new Metadata classes from Doctrine
I'm using Translatable and EasyAdmin in a Symfony 5 project and I have configured 2 languages.
The issue is I need to be able to edit the different languages of a record in EasyAdmin, I have checked the docs of Translatable, EasyAdmin and Symfony, There is very little information about how to integrate database translations into EasyAdmin.
Therefore, I'm a bit stuck in terms of code, I have tried configuring setTranslationParameters() inside the entity CRUD controller and changing some configuration in the DashboardController however, I don't think this is the right approach.
Any suggestions of how to solve this issue?
Thank you for your effort and time.
as of writing, this feature doesn't exist in EasyAdmin, please see the link to the answer to the issue on Github.
https://github.com/EasyCorp/EasyAdminBundle/issues/4982
However, a work around is possible with a different package:
remove doctrine-extensions/DoctrineExtensions and then install KnpLabs/DoctrineBehaviors
install a2lix/translation-form-bundle
Create a translation field:
<?php
declare(strict_types=1);
namespace App\Controller\Admin\Field;
use A2lix\TranslationFormBundle\Form\Type\TranslationsType;
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
use EasyCorp\Bundle\EasyAdminBundle\Field\FieldTrait;
final class TranslationField implements FieldInterface
{
use FieldTrait;
public static function new(string $propertyName, ?string $label = null, array $fieldsConfig = []): self
{
return (new self())
->setProperty($propertyName)
->setLabel($label)
->setFormType(TranslationsType::class)
->setFormTypeOptions([
'default_locale' => 'cz',
'fields' => $fieldsConfig,
]);
}
}
Use the TranslationField inside your admin CRUD controller:
public function configureFields(string $pageName): iterable
{
return [
TextField::new('title', 'title')->hideOnForm(),
TranslationField::new('translations', 'translations', [
'title' => [
'field_type' => TextType::class,
'required' => true,
]
// add more translatable properties into the array
])->setRequired(true)
->hideOnIndex()
];
}
I want to create a plugin to use zend-i18n/translate on controller. On zf2 I have a controller plugin that does this for me, but on zf3 I could not get this to work. How can I use zend-i18n inside a controller or via controller plugin with zf3?
==========
I just found what I need here on zf doc: https://docs.zendframework.com/zend-mvc-i18n/services/#mvctranslator-and-translatorfactory
if you already have config the translator as factory on your module.config.php, you can inject on your controller plugin.
You can virtually do the same as the answer that #hkulekci referred to in his comment.
'service_manager' => [
'factories' => [
\Zend\I18n\Translator\TranslatorInterface::class => \Zend\I18n\Translator\TranslatorServiceFactory::class,
]
]
and
'controller_plugins' => [
'invokables' => [
'translate' => \Zend\I18n\View\Helper\Translate::class
]
]
After that you can get the translate plugin like in your controller action methods like this:
public someAction(){
$translator = $this->translate;
}
Check the Zend Framework documentation or this Zend Framework blog for more details on the controller plugin manager.
For translate in model and controller, I did this in my module.config.php
'service_manager' => [
'factories' => [
\Zend\I18n\Translator\Translator::class => \Zend\I18n\Translator\TranslatorServiceFactory::class,
],
],
Then from my controller or model which has serviceContainer initialised I do:
$this->myVar = $serviceContainer->get(\Zend\I18n\Translator\Translator::class);
Then I can access it by doing
$this->myVar->translate('lorem ipsum');
I try to set up a symfony project with the microcontroller trait. But instead of use a config.yml I want to use a config.php file.
return [
'framework' => [
'secret' => 'secret_'
]
];
What is the best practice to achieve this?
when using microkernel trait, you can use the configureContainer method in your front controller (app.php) to load configuration directly from an array, like this:
protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
{
// PHP equivalent of config.yml
$c->loadFromExtension('framework', array(
'secret' => 'S0ME_SECRET'
));
}
docs here
You should use the container to set the parameters like
$container->setParameter('framework.secret', 'secret_');
as explained in the Symfony Docs
I'm trying to set up an Admin as a child of an other Admin in Sonata Admin Bundle.
I have 2 Admin classes:
CategoryAdmin
This class contains the following method
protected function configureSideMenu(MenuItemInterface $menu, $action, AdminInterface $childAdmin = null)
{
$id = $this->getRequest()->get('id');
$menu->addChild(
$this->trans('Projects'),
array('uri' => $this->getChild('sonata.admin.project')->generateUrl('list', array('id' => $id)))
);
}
ProjectAdmin
This class contains protected $parentAssociationMapping = 'category';
category is the property in the model class representing the ManyToOne association.
I added the following lines to my service configuration for CategoryAdmin
calls:
- [ addChild, ["#sonata.admin.project"]]
The routes for the child Admin are not being generated with this configuration. The link in the SideMenu (top menu) points to /admin/project/list?childId=1&id=1
Here is the output of the children of CategoryAdmin with dump()
array:1 [▼
"sonata.admin.project" => ProjectAdmin {#406 ▶}
]
This means that the configuration for my child admin seems to be correct. I have no idea, why the routes for the child admin are not being generated.
I hope somebody can give me a hint, what the problem could be.
Note for next gen sonata coders:
If your route is not being generated, first check you didn't do:
protected function configureRoutes(RouteCollection $collection)
{
//clear all routes except given !!!
$collection->clearExcept(array('list', 'show'));
}
It costs me two days...
Do you have the $baseRouteName and $baseRoutePattern overriden in your admin class ?
If you do, Sonata will generate both child and parent routes with the same name resulting in the parent routes overriding the child ones.
I bumped into this issue while solving the problem for myself and decided to share the solution, which costed me several debugging hours...
The only way to generate a proper uri in this case is to use low-level routeGenerator which doesn't make any sonata suggestions, made inside generateMenuUrl method.
First you have to debug the routes, you have in your app (including autogenerated by sonata).
php bin/console debug:router
For example I have 3 nesting levels
hall -> seats scheme -> sector
And my routes are following:
adminHall_list ANY ANY ANY /admin/hall/list
adminHall_create ANY ANY ANY /admin/hall/create
adminHall_edit ANY ANY ANY /admin/hall/{id}/edit
adminHall_delete ANY ANY ANY /admin/hall/{id}/delete
adminHall_adminScheme_list ANY ANY ANY /admin/hall/{id}/scheme/list
adminHall_adminScheme_create ANY ANY ANY /admin/hall/{id}/scheme/create
adminHall_adminScheme_edit ANY ANY ANY /admin/hall/{id}/scheme/{childId}/edit
adminHall_adminScheme_delete ANY ANY ANY /admin/hall/{id}/scheme/{childId}/delete
adminHall_adminScheme_adminSector_list ANY ANY ANY /admin/hall/{id}/scheme/{childId}/sector/list
adminHall_adminScheme_adminSector_create ANY ANY ANY /admin/hall/{id}/scheme/{childId}/sector/create
adminHall_adminScheme_adminSector_edit ANY ANY ANY /admin/hall/{id}/scheme/{childId}/sector/{childChildId}/edit
adminHall_adminScheme_adminSector_delete ANY ANY ANY /admin/hall/{id}/scheme/{childId}/sector/{childChildId}/delete
In admin classes baseRouteName and baseRoutePattern has been overridden.
// HallSchemeAdmin.php
$this->baseRouteName = 'adminScheme';
$this->baseRoutePattern = 'scheme';
To generate a most deep listing url:
$url = $admin->getRouteGenerator()->generate('adminHall_adminScheme_adminSector_list', [
'id' => $admin->getRequest()->get('id'),
'childId' => 555, // put required id
]);
It will produce the url like this:
/admin/hall/495/scheme/555/sector/list
If you need edit url, you have to provide childChildId param too:
$url = $admin->getRouteGenerator()->generate('adminHall_adminScheme_adminSector_edit', [
'id' => $admin->getRequest()->get('id'),
'childId' => 555,
'childChildId' => 12345
]);
The result is:
/admin/hall/495/scheme/555/sector/12345/edit