[Symfony] Zachowanie translatable z DoctrineExtensionsBundle


(Mr Radzik) #1

Przerabiam książkę Gajdy odnośnie Symfony 2 i utknąłem na dłużej z pakietem DoctrineExtensionsBundle. W książce i na serwerze są przykłady i opisy odnoszące się do Symfony 2.0, aktualna wersja to Symfony 2.1.7. i są mniej lub bardziej znaczne różnice, czego efektem jest mój problem. Po kolei:

Do najnowszej wersji Symfony (with vendors) dodałem poprzez Composera pakiet DoctrineExtensionsBundle, automatycznie zainstalowało się także DoctrineExtensions.

Poprawnie działa zachowanie sluggable i timestampable - zrobiłem projekt, który ich używa, wszystko jest w porządku, w bazie danych mam slugi czasy dodania/edycji.

Kolejnym krokiem było wykorzystanie translatable do zrobienia wersji językowych. Idąc wg instrukcji z książki:

  • zedytowałem plik /app/config/config.yml do postaci:

    inna konfiguracja...

    Doctrine Configuration

    doctrine:

    dbal:
    
        driver: "%database_driver%"
    
        host: "%database_host%"
    
        port: "%database_port%"
    
        dbname: "%database_name%"
    
        user: "%database_user%"
    
        password: "%database_password%"
    
        charset: UTF8
    
    
    orm:
    
        auto_generate_proxy_classes: "%kernel.debug%"
    
        auto_mapping: true
    
    
        mappings:
    
            StofDoctrineExtensionsBundle: ~

    stof_doctrine_extensions:

    default_locale: pl_PL
    
    orm:
    
        default:
    
            tree: false
    
            loggable: false
    
            timestampable: false
    
            sluggable: false
    
            translatable: true
  • stworzyłem pakiet My/FrontendBundle - poleceniem

    php app/console generate:doctrine:entity

stworzyłem model MyFrontendBundle:Color - zmodyfikowałem powstały plik src/My/FrontendBundle/Entity/Color.php:

<?php


namespace My\FrontendBundle\Entity;


use Doctrine\ORM\Mapping as ORM;

use Gedmo\Mapping\Annotation as Gedmo;


/**

 * Color

 *

 * @ORM\Table()

 * @ORM\Entity

 */

class Color

{

    /**

     * @var integer

     *

     * @ORM\Column(name="id", type="integer")

     * @ORM\Id

     * @ORM\GeneratedValue(strategy="AUTO")

     */

    private $id;


    /**

     * @var string

     *

     * @ORM\Column(name="rgb", type="string", length=16)

     */

    private $rgb;


    /**

	 * @Gedmo\Translatable

     * @ORM\Column(name="name", type="string", length=255)

     */

    private $name;



    /**

     * @Gedmo\Locale

     */

    private $locale;


	public function setTranslatableLocale($locale)

    {

        $this->locale = $locale;

    }


    /**

     * Get id

     *

     * @return integer 

     */

    public function getId()

    {

        return $this->id;

    }


    /**

     * Set rgb

     *

     * @param string $rgb

     * @return Color

     */

    public function setRgb($rgb)

    {

        $this->rgb = $rgb;


        return $this;

    }


    /**

     * Get rgb

     *

     * @return string 

     */

    public function getRgb()

    {

        return $this->rgb;

    }


    /**

     * Set name

     *

     * @param string $name

     * @return Color

     */

    public function setName($name)

    {

        $this->name = $name;


        return $this;

    }


    /**

     * Get name

     *

     * @return string 

     */

    public function getName()

    {

        return $this->name;

    }

}
  • poleceniem

    php app/console doctrine:database:create

stworzyłem nową bazę danych - faktycznie, pojawiła się pusta baza w phpMyAdminie - poleceniem

php app/console doctrine:schema:update --force

utworzyłem tabelę w bazie danych i tu jest problem: - powinny być co najmniej 2: color i ext_translation - jest 1: color dalszym krokiem jest przygotowanie pliku /src/My/FrontendBundle/DataFixtures/ORM/LoadData.php:

<?php


namespace My\FrontendBundle\DataFixtures\ORM;


use Doctrine\Common\DataFixtures\FixtureInterface;

use Doctrine\Common\Persistence\ObjectManager;

use My\FrontendBundle\Entity\Color;

use Symfony\Component\Yaml\Yaml;


class LoadData implements FixtureInterface

{

	public function load(ObjectManager $manager)

	{

		$yml = Yaml::parse('data/kolory.yml');

		foreach ($yml as $c)

		{

			$color = new Color();

			$color->setRgb($c['rgb']);

			$color->setName($c['name']);

			$manager->persist($color);

			$manager->flush();


			foreach ($c['translations'] as $lang => $translation)

			{

				$color->setTranslatableLocale($lang);

				$color->setName($translation);

				$manager->persist($color);

				$manager->flush();

			}

		}

	}

}

i wykonanie polecenia

php app/console doctrine:fixtures:load

które zwraca wynik:

> purging database

> loading My\FrontendBundle\DataFixtures\ORM\LoadData


  [Doctrine\Common\Persistence\Mapping\MappingException]                       

  The class 'Gedmo\Translatable\Entity\Translation' was not found in the chain configured namespaces My\FrontendBundle\Entity

Przeszukałem całe google, manuala DoctrineExtensionsBundle i wszystko inne co znalazłem, i nie mogę sobie z tym poradzić. Przykład na serwerze autora działa dobrze, ale jest jak pisałem w nieco starszej wersji Symfony i porównanie plików nic mi nie dało, więc proszę o pomoc.


(Muaddib 5g) #2

Witaj mr.radzik

Pozmieniało się trochę, oto modyfikacja, którą należy wprowadzić aby Twój przykład zadziałał:

W konfiguracji w pliku config.yml ZAMIAST:

mappings:

    StofDoctrineExtensionsBundle: ~

wpisz:

mappings:

    #StofDoctrineExtensionsBundle: ~

    gedmo_translatable:

        type: annotation

        prefix: Gedmo\Translatable\Entity

        dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"

        alias: GedmoTranslatable # this one is optional and will default to the name set for the mapping

        is_bundle: false

Teraz gdy wykonasz

php app/console doctrine:schema:update --force

W bazie danych pojawi się również tabela ext_translations Warto dodać, że plik LoadData.php, dołączony do przykładu zawiera błąd i próba wykonania kroku 8 zakończy się niepowodzeniem. Aby tego uniknąć plik powinien wyglądać tak:

<?php


namespace My\FrontendBundle\DataFixtures\ORM;


use Doctrine\Common\DataFixtures\FixtureInterface;

use Doctrine\Common\Persistence\ObjectManager;

use My\FrontendBundle\Entity\Color;

use Symfony\Component\Yaml\Yaml;



class LoadData implements FixtureInterface

{


    public function load(ObjectMAnager $manager)

    {

        $yml = Yaml::parse('data/kolory.yml');

        foreach ($yml as $c) {

            $Color = new Color();

            $Color->setRgb($c['rgb']);

            $Color->setName($c['name']);

            $manager->persist($Color);

            $manager->flush();


            foreach ($c['translations'] as $lang => $translation) {

                $Color->setTranslatableLocale($lang);

                $Color->setName($translation);

                $manager->persist($Color);

                $manager->flush();

            }

        }

    }


}

Teraz po wykonaniu polecenia

php app/console doctrine:fixtures:load

Baza danych wypełni się sgodnie z plikiem kolory.yml UWAGA!!!