Doctrine Behaviours - Sortable on non relationship - symfony

I am trying to sort by a property which is not in relation but part of current entity.
For some reason sortable wont work for me if property with #Gedmo\SortableGroup is part of current entitty.
Here is my Entity:
https://gist.github.com/rat4m3n/91df50da8c653edfa3d0
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* #Gedmo\SortableGroup
* #ORM\Column(name="total_chips", type="integer")
*/
private $total_chips = 0;
/**
* #Gedmo\SortablePosition
* #ORM\Column(name="ranking", type="integer")
*/
private $ranking = 0;
Is this simply not possible / supported ?
Else... how could I accomplish such behaviour in any other way?

If you still have a problem with the SortablePosition and the SortableGroup feature of Gedmo, you can follow this :
Do not affect values to the property.
Activate the features in the config.yml
stof_doctrine_extensions:
default_locale: fr_FR
orm:
default:
sortable: true
tree: true
And add the listener to your entity :
namespace Acme\AcmeBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class AcmeAcmeBundle extends Bundle
{
public function boot()
{
$em = $this->container->get('doctrine.orm. default_entity_manager');
$evm = $em->getEventManager();
$evm->addEventSubscriber(new \Gedmo\Sortable\ SortableListener);
}
}

Related

API PLATFORM custom identifier in parent class/table

I have entities that make use of Inheritance Mapping Doctrine inheritance. I have a custom identifier that I generate with #ORM\PrePersist(), which is in a trait and this is used in the parent class.
I want to be able to update properties that the child class has, for this reason, I need to run endpoints on the child entity
When I run an item operation, api platform can't find the resource.
PATCH /api/childas/{hash}
NotFoundHttpException
Not Found
api platform, it doesn't recognize hash as identifier. Take the id as your identified, even if it is false and hash is true.
Trait to generate hashes with which I identify the resource
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiProperty;
use Doctrine\ORM\Mapping as ORM;
trait HashableTrait
{
/**
* #ORM\Column(type="string", length=255)
* #ApiProperty(identifier=true)
*/
private $hash;
public function getHash(): ?string
{
return $this->hash;
}
/**
* #ORM\PrePersist()
*/
public function setHash()
{
$this->hash = \sha1(\random_bytes(10));
}
}
Parent class, is the table where the hash will be stored
<?php
namespace App\Entity;
use App\Entity\HashableTrait;
/**
* #ORM\HasLifecycleCallbacks()
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="type", type="integer")
* #ORM\DiscriminatorMap({
* 1 = "App\Entity\ChildA",
* 2 = "App\Entity\ChildB"
* })
*/
class Parent
{
use HashableTrait;
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
* #ApiProperty(identifier=false)
*/
private $id;
public function getId(): ?int
{
return $this->id;
}
// Properties, setters, getters
}
Child class, on which I want to perform operations, such as updating some property that belongs to this class
<?php
namespace App\Entity;
class ChildA extends Parent
{
// Custom properties for ChildA
}
Config api platform operations for entity Child
App\Entity\ChildA:
collectionOperations:
post: ~
itemOperations:
post: ~
get: ~
patch: ~
delete: ~
I have thought about using data providers, but I keep getting the error.
The error was because both the hash property in the trait and the id property in the parent entity must be accessible from the entity to use.
Doctrine ORM uses reflection class to get information about attributes and their annotations. ReflectionClass::hasProperty obviously does not allow viewing private properties in the parent class.

Unable to find the association target class

I'm using Symfony 3.4 and knp doctrine behaviors for translation.
My entity Article looks like:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
/**
* Article
*
* #ORM\Table(name="article")
* #ORM\Entity(repositoryClass="AppBundle\Repository\ArticleRepository")
*/
class Article
{
use ORMBehaviors\Translatable\Translatable;
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
//...
}
Then I have entity ArticleTranslation
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
/**
* #ORM\Entity
*/
class ArticleTranslation
{
use ORMBehaviors\Translatable\Translation;
/**
* #ORM\Column(type="string", length=128)
*/
protected $headline;
//...
}
Now my app throws me an error:
Unable to find the association target class of "headline" in AppBundle\Entity\Article.
It expects a relation between Article and ArticleTranslation. There is a sentence in the documentation:
The default naming convention (or its customization via trait methods) avoids you to manually handle entity associations. It is handled automatically by the TranslationSubscriber.
Why does this happen? What am I missing?
edit
bin/console doctrine:schema:update
[OK] Nothing to update - your database is already in sync with the current entity metadata.
bin/console debug:config knp_doctrine_behaviors
knp_doctrine_behaviors:
translatable: true
blameable: false
geocodable: false
loggable: false
sluggable: false
soft_deletable: false
sortable: false
timestampable: false
tree: false
I'm using this in sonata admin, with a2lix translatable.
ArticleAdmin.php:
<?php
namespace AppBundle\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use A2lix\TranslationFormBundle\Form\Type\TranslationsType;
final class ArticleAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('headline', TranslationsType::class);
}
//...
}
Try to use
$formMapper->add('translations', TranslationsType::class);
I had the same problem. Probably the field name needs to be exactly translations.

How to implement SOrtablerepository in Gedmo

I would like to ask you how it si possible to implement the sortable repository for gedmo sortable extension into symfony 2. I am a little confused how to inject the EntityManager and ClassMetadata into the constructor and how the repository register correctly in services.yml and entity.
Here is the repository:
https://github.com/l3pp4rd/DoctrineExtensions/blob/master/lib/Gedmo/Sortable/Entity/Repository/SortableRepository.php
Thank you very much!
I recommend you install the StofDoctrineExtensionsBundle
And you can enable the sortable behavior in your config file.
Example:
config.yml
stof_doctrine_extensions:
orm:
default:
sortable: true
Entity class
/**
* Acme\Bundle\ProjectBundle\Entity\Foo
*
* #ORM\Table
* #ORM\Entity(repositoryClass="Gedmo\Sortable\Entity\Repository\SortableRepository")
*/
class Foo
{
/**
* #var integer $position
*
* #Gedmo\SortablePosition
* #ORM\Column(name="position", type="integer")
*/
private $position;
}
Remember to subscribe GedmoListener on boot()
<?php
class AcmeBundle extends Bundle
{
$em = $this->container->get('doctrine.orm.default_entity_manager');
$evm = $em->geteventmanager();
$evm->addeventsubscriber(new \gedmo\sortable\sortablelistener);
}

Extend SonataUserBundle Entity

I want to extend default user entity attributes. In database after extending FOSUserBundle with SonataUserBunle there are 2 tables for storing users: fos_user and fos_user_user. I want to extend fos_user
Here is app/AppKernel.php:
new Sonata\UserBundle\SonataUserBundle('FOSUserBundle'),
new Application\Sonata\UserBundle\ApplicationSonataUserBundle(),
in app/config.yml file I set:
fos_user:
db_driver: orm<br>
firewall_name: main<br>
user_class: Acme\DemoBundle\Entity\User<br>
group:<br>
group_class: Application\Sonata\UserBundle\Entity\Group<br>
sonata_user:
security_acl: true
class:
user: Acme\DemoBundle\Entity\User
admin:
user:
class: Acme\DemoBundle\Admin\UserAdmin
parameters:
sonata.user.admin.user.class: Blogger\BlogBundle\Admin\UserAdmin
sonata.user.admin.user.entity: Blogger\BlogBundle\Entity\User
doctrine:
orm:
auto_mapping: auto
SonataUserBundle is created in src/Application/Sonata/UserBundle
To override SonataUserBundle, i extended UserAdmin by creating another UserAdmin class in src/Acme/DemoBundle/Admin/UserAdmin and all works fine
Now I want to extend User entity (fos_user table) to add new attributes.
Here is my Acme/Demo/Entity/User.php that I want to extend the default User entity
namespace Acme\DemoBundle\Entity;
use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/*
* #ORM\Column(type="string", name="newAttribute")
*/
protected $newAttribute;
public function __construct()
{
parent::__construct();
// your own logic
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}
What should I do to extend default fos_user table with php app/console doctrine:generate:entities Acme/DemoBundle
I've read many posts about this issue but none of the solutions helped me. I tried to extend Model class instead of Entity class but also nothing changed
You don't have to.
new Sonata\UserBundle\SonataUserBundle('FOSUserBundle')
Here your are telling the SonataUserBundle to use the FOSUserBundle as well.
Then in your User entity you set:
use Sonata\UserBundle\Entity\BaseUser as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="User")
*/
class User extends BaseUser
Because you have said to the SonataUserBundle "use the fosuserbundle" and you extend from the sonata user bundle user entity he's gonna "merge" those 2 models into 1 and add your custom fields from in your user entity as well.

How to auto update properties of a doctrine entity?

I've created a doctrine entity class in my symfony 2 project and now I want to auto set a property before saving by the entity manager. Are there some hooks to implement or how can I solve my issue?
Yes, you can:
http://symfony.com/doc/master/book/doctrine.html#lifecycle-callbacks
<?php
namespace MyNS\Dummy;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
*/
class Dummy
{
protected $property;
/**
* #ORM\PrePersist
* #ORM\PreUpdate
*/
public function automaticProperty()
{
$this->property = 'whatever';
}
}

Resources