Dieses Blog durchsuchen

Wird geladen...

Dienstag, 20. Januar 2015

SYMFONY2: SonataAdmin + SonanaUser + FosUser um eigene Felder erweitern [symfony 2.3]

Das SonataAdminBundle in Verbindung mit dem FosUserBundle ist ohne Zweifel eine tolle Erleichterung bei der Erstellung eines Backends.

Wenn man sich an die Anleitung hält geht es relativ schnell voran und in ca. 15 Minuten kann man bereits Benutzer und Gruppen bequem bearbeiten.

Was aber wenn man dem Benutzer neue Felder zuordnen will?
Dies ist leider nicht mehr so ganz einfach. Es gibt mehrere Wege dies zu erreichen. Ich werde hier einen Weg über ein neues Bundle beschreiben, da es für Ordnung in der App-Struktur sorgt.

Nachdem Sie das SonataAdminBundle und SonataUserBundle installiert haben erstellen Sie ein neues Bundle mit Hilfe des SonataEasyExtendsBundle:

  php app/console sonata:easy-extends:generate SonataUserBundle -d src

Nach der Installation müssen Sie das neue Bundel im AppKernel registrieren:

// AppKernel.php
class AppKernel {
  public function registerbundles(){
    return array(
       // Application Bundles
       // ...
       new Application\Sonata\UserBundle\ApplicationSonataUserBundle(),
       // ...
       )}}


Jetzt sind wir bereit den User um eine neues Feld zu erweitern. 
Als Beispiel werden wir dem User eine neues Feld mit dem Namen „foo“ hinzufügen

1.  Als erstes def1inieren wir eine vom SonataUserBundle abgeleitete Klasse User
und erweitern dies um eine neue Variable $foo:
 
 Pfad: Application\Sonata\UserBundle\Entity\User.php
   
 namespace Application\Sonata\UserBundle\Entity;
 use Doctrine\ORM\Mapping as ORM;
 use Sonata\UserBundle\Entity\BaseUser as BaseUser;

 /**
  * @ORM\Entity
  * @ORM\Table(name="fos_user_user")
  */
 class User extends BaseUser {
  /**
   * @ORM\Id
   * @ORM\Column(type="integer")
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  protected $id;

  public function __construct() {
   parent::__construct();
   // your own logic
  }

  public function getId() {
   return $this->id;
  }

  // my new "foo" field
  /**
   * @var string
   * @ORM\Column(type="string", length=255, nullable=true, name="foo")
   */
  protected $foo;

  /**
   * Set foo
   *
   * @param string $foo
   * @return User
   */
  public function setFoo($foo) {
   $this->foo = $foo;
   return $this;
  }

  /**
   * Get foo
   *
   * @return string 
   */
  public function getFoo() {
   return $this->foo;
  }
 }       
 

2. Nun müssen wir den ORM mapper um das neue Feld erwitern:
 
 Pfad: Application\Sonata\UserBundle\Resources\config\doctrine\User.orm.xml
 
 <?xml version="1.0" encoding="UTF-8"?>
 <doctrine-mapping 
    xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
    http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

  <entity name="Application\Sonata\UserBundle\Entity\User" table="fos_user_user">
     <id name="id" column="id" type="integer">
        <generator strategy="AUTO" />
     </id> 

     // my new field foo
     <field name="foo" column="foo" type="string"  />
  </entity>
 </doctrine-mapping> 
 
3. Als nächstes können wir die Datenbank updaten:       
 
    php app/console doctrine:schema:update --force  

4. Im nächsten Schritt müssen wir die Klasse UserAdmin aus dem SonataUserBundle 
   ableiten und um das neue Feld erweitern. 
   Gleichzeitig setzen wir den Translator für das neue Feld auf die Domäne "admin", 
   damit die Labels korrekt übersetzt werden.
 
        Pfad: Application\Sonata\UserBundle\Model\UserAdmin.php

 namespace Application\Sonata\UserBundle\Model;
 use Sonata\AdminBundle\Form\FormMapper;
 use Sonata\AdminBundle\Datagrid\DatagridMapper;
 use Sonata\AdminBundle\Datagrid\ListMapper;
 use Sonata\AdminBundle\Show\ShowMapper;
 use Sonata\UserBundle\Admin\Model\UserAdmin as SonataUserAdmin;

 class UserAdmin extends SonataUserAdmin {
  /**
   * {@inheritdoc}
   */
  protected function configureFormFields(FormMapper $formMapper) {
   parent::configureFormFields($formMapper);
   $formMapper
     ->tab('New Group)
      ->with('label.my_group', array('class' => 'col-md-6'))->end()
       ->end();
   $formMapper
    ->tab('Test')
     ->with('label.my_group', array(
         'translation_domain' => 'admin',
       ))
        ->add('foo', null, array('label' => 'label.foo'), array(
        'translation_domain' => 'admin',
         ));
  }} 
 
5. Zusätzlich müssen wir die vorhin erwähnte Translator-Domäne erstellen:
 
 Pfad: app\Resources\translations\admin.de.xlf         // Global
 oder 
 Pfad: Your\Bundle\Resources\translations\admin.de.xlf // im Bundle

 <?xml version="1.0"?>
 <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
  <file source-language="de" datatype="plaintext" original="file.ext">       
   <body>
    <!--ADMIN-->
    <trans-unit id="label.my_group">
     <source>label.my_group</source>
     <target>Foo Group</target>
    </trans-unit> 
    <trans-unit id="label.foo">
     <source>label.foo</source>
     <target>Foo</target>
    </trans-unit>
   </body>
  </file>
 </xliff> 
 
6. Jetzt müssen wir nur noch dem SonataBundle klar machen,
   dass es die neuen Klassen nutzen soll:

 Pfad: app\config\config.yml

 parameters:
  # set custom name for the section
  sonata.user.admin.groupname: my_section_name 

 fos_user:
  user_class:     Application\Sonata\UserBundle\Entity\User

  group:
   group_class:   Application\Sonata\UserBundle\Entity\Group
   group_manager: sonata.user.orm.group_manager   

 sonata_user:  
  class:
   user:    Application\Sonata\UserBundle\Entity\User
   group:   Application\Sonata\UserBundle\Entity\Group
   
  admin:  
   user:
    class:          Application\Sonata\UserBundle\Model\UserAdmin       
    controller:     SonataAdminBundle:CRUD
    translation:    SonataUserBundle    
   group:
    class:          Application\Sonata\UserBundle\Model\GroupAdmin       
    controller:     SonataAdminBundle:CRUD
    translation:    SonataUserBundle 
 
7. Als letzes müssen wir noch den cash löschen 
   und danach können wir das neuse Feld "foo" in dem Benutzer-Template sehen:


Dienstag, 7. Mai 2013

COMET: Webanwendungen die in Echtzeit laufen und auf Änderungen zeitnah reagieren.


Oft will man den Benutzer informieren, dass zwischenzeitlich eine Änderung durch einen anderen Benutzer durchgeführt wurde. Im Normalfall geht es nicht, da der Server nur dann Daten an den Browser senden kann, wenn er dazu aufgeforder wird. Eine Lösung wäre den Server in einem bestimmten Intervall per AJAX abzufragen und auf Änderungen entsprechend zu reagieren. Dies ist aber sehr unelegant und nicht besonders ressourcenschonend.
In der letzten Zeit hat sich eine neue Technologie mit dem Namen Comet herauskristallisiert. Es ist ähnlich wie bei AJAX ein Oberbegriff für mehrere Ansätze die als Ziel haben, die Daten vom Server zum Browser zu pushen, ohne dass der Browser die anfordern muss.

Ein Lösungsansatz der auf dieser Idee basiert ist "CometD Bayeux Ajax Push" (http://cometd.org/)
Das Projekt in der neuesten Version kann man hier herunterladen: http://download.cometd.org/
Wir werden folgend das Projekt unter Windows einrichten.

1. VORBEREITUNG:

Voraussetzung für CometD sind:
- Java JDK ab 5.0
- Maven ab 3.0
- Jetty ab 2.5

Falls Java nicht installiert ist, dann Java installieren. Mit "java -version" in der Kommandozeile kann man testen ob Java bereits auf dem System installiert wurde.

Maven (http://maven.apache.org/) ist ein Build-Management-Tool der Apache Software Foundation der auf Java basiert. Mit ihm kann man u.a. Java-Programme standardisiert erstellen und verwalten.
Maven wird folgend unter Windows installiert:
- Maven runterladen: http://maven.apache.org/download.cgi
- das Archiv entpacken, am besten direkt im Root, also z.B. C:\maven\.
- wichtig: man darf keine Leerstellen im Pfad benutzen.
- die JAVA_HOME Systemvariable setzen (Bsp. C:\Program Files\Java\jdk1.7.0_15)
- die PATH Systemvariable um den Maven-Pfad erweitern (Bsp. PATH= ...;C:\maven\bin\)
- Windows neu starten.
- testen in der Kommandozeile, ob die Installation erfolgreich war: mvn -version

Jetty (http://www.eclipse.org/jetty) ist ein in Java geschriebener Servlet-Container und Webserver. Wir brauchen insbesondere seine Servlet Fähigkeiten. Als Servlets bezeichnet man Java-Klassen, deren Instanzen innerhalb eines Webservers Anfragen von Clients entgegennehmen und beantworten.
Jetty wird wie folgt unter Windows installiert:
- Jetty herunterladen: http://download.eclipse.org/jetty/stable-9/dist/
- das Archiv entpacken, am besten direkt im Root, also z.B. C:\jetty\
- in der Konsole in den Ordner wechseln und mit "java -jar start.jar" starte.
- die Frage der Windows-Firewalj ggf. bejahen.
- im Browser "localhost:8080" eintragen.
- wenn alles gut gelaufen ist, dann erscheint die Begrüßungsseite des Jetty-Servers

2. TEST

Jetzt sind wir bereit den Echtzeit-demo-chat zu starten und anzutesten.
-  CometD herunterladen: http://download.cometd.org/
- das Archiv entpacken.
- in das "cometd-demo" Verzeichnis wechseln.
- in der Konsole "mvn jetty:deploy-war" ausführen.
- im Browser "localhost:8080" eintragen.
- wenn alles gut gelaufen ist, dann erscheint im Browser die CometD Startseite.
- hier können wir verschiedene Chat-Versionen ausprobieren.

Im nächsten Teil werden wir diese Technologie in eigene Anwendung anbinden.