Using Groups With FOSUserBundle

2.0 version
Maintained

Using Groups With FOSUserBundle

FOSUserBundle allows you to associate groups to your users. Groups are a way to group a collection of roles. The roles of a group will be granted to all users belonging to it.

Note

Symfony supports role inheritance so inheriting roles from groups is not always needed. If the role inheritance is enough for your use case, it is better to use it instead of groups as it is more efficient (loading the groups triggers the database).

To use the groups, you need to explicitly enable this functionality in your configuration. The only mandatory configuration is the fully qualified class name (FQCN) of your Group class which must implement FOS\UserBundle\Model\GroupInterface.

Below is an example configuration for enabling groups support.

  • YAML
    1
    2
    3
    4
    5
    6
    7
    # app/config/config.yml
    fos_user:
        db_driver: orm
        firewall_name: main
        user_class: AppBundle\Entity\User
        group:
            group_class: AppBundle\Entity\Group
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    <!-- app/config/config.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:fos-user="http://friendsofsymfony.github.io/schema/dic/user"
    >
        <fos_user:config
            db-driver="orm"
            firewall-name="main"
            user-class="AppBundle\Entity\User"
        >
            <fos_user:group group-class="AppBundle\Entity\Group" />
        </fos_user:config>
    </container>
    

The Group class

The simplest way to create a Group class is to extend the mapped superclass provided by the bundle.

a) ORM Group class implementation

  • Annotations
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <?php
    // src/AppBundle/Entity/Group.php
    
    namespace AppBundle\Entity;
    
    use FOS\UserBundle\Model\Group as BaseGroup;
    use Doctrine\ORM\Mapping as ORM;
    
    /**
     * @ORM\Entity
     * @ORM\Table(name="fos_group")
     */
    class Group extends BaseGroup
    {
        /**
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
         protected $id;
    }
    
  • YAML
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # src/AppBundle/Resources/config/doctrine/Group.orm.yml
    AppBundle\Entity\Group:
        type:  entity
        table: fos_group
        id:
            id:
                type: integer
                generator:
                    strategy: AUTO
    

Note

Group is a reserved keyword in SQL so it cannot be used as the table name.

b) MongoDB Group class implementation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?php
// src/AppBundle/Document/Group.php

namespace AppBundle\Document;

use FOS\UserBundle\Model\Group as BaseGroup;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;

/**
 * @MongoDB\Document
 */
class Group extends BaseGroup
{
    /**
     * @MongoDB\Id(strategy="auto")
     */
    protected $id;
}

c) CouchDB Group class implementation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?php
// src/AppBundle/CouchDocument/Group.php

namespace AppBundle\CouchDocument;

use FOS\UserBundle\Model\Group as BaseGroup;
use Doctrine\ODM\CouchDB\Mapping\Annotations as CouchDB;

/**
 * @CouchDB\Document
 */
class Group extends BaseGroup
{
    /**
     * @CouchDB\Id
     */
    protected $id;
}

Defining the User-Group relation

The next step is to map the relation in your User class.

a) ORM User-Group mapping

  • Annotations
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    <?php
    // src/AppBundle/Entity/User.php
    
    namespace AppBundle\Entity;
    
    use FOS\UserBundle\Model\User as BaseUser;
    
    /**
     * @ORM\Entity
     * @ORM\Table(name="fos_user")
     */
    class User extends BaseUser
    {
        /**
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        protected $id;
    
        /**
         * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Group")
         * @ORM\JoinTable(name="fos_user_user_group",
         *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
         *      inverseJoinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id")}
         * )
         */
        protected $groups;
    }
    
  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # src/AppBundle/Resources/config/doctrine/User.orm.yml
    AppBundle\Entity\User:
        type:  entity
        table: fos_user
        id:
            id:
                type: integer
                generator:
                    strategy: AUTO
        manyToMany:
            groups:
                targetEntity: Group
                joinTable:
                    name: fos_user_group
                    joinColumns:
                        user_id:
                            referencedColumnName: id
                    inverseJoinColumns:
                        group_id:
                            referencedColumnName: id
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <?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="AppBundle\Entity\User" table="fos_user">
            <id name="id" column="id" type="integer">
                <generator strategy="AUTO" />
            </id>
            <many-to-many field="groups" target-entity="Group">
                <join-table name="fos_user_group">
                    <join-columns>
                        <join-column name="user_id" referenced-column-name="id"/>
                    </join-columns>
                    <inverse-join-columns>
                        <join-column name="group_id" referenced-column-name="id" />
                    </inverse-join-columns>
                </join-table>
            </many-to-many>
        </entity>
    </doctrine-mapping>
    

b) MongoDB User-Group mapping

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
// src/AppBundle/Document/User.php

namespace AppBundle\Document;

use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;

/**
 * @MongoDB\Document
 */
class User extends BaseUser
{
    /** @MongoDB\Id(strategy="auto") */
    protected $id;

    /**
     * @MongoDB\ReferenceMany(targetDocument="AppBundle\Document\Group")
     */
    protected $groups;
}

c) CouchDB User-Group mapping

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
// src/AppBundle/CouchDocument/User.php

namespace AppBundle\CouchDocument;

use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ODM\CouchDB\Mapping\Annotations as CouchDB;

/**
 * @CouchDB\Document
 */
class User extends BaseUser
{
    /**
     * @CouchDB\Id
     */
    protected $id;

    /**
     * @CouchDB\ReferenceMany(targetDocument="AppBundle\CouchDocument\Group")
     */
    protected $groups;
}

Enabling the routing for the GroupController

You can import the routing file group.xml to use the built-in controller to manipulate groups.

1
2
3
4
# app/config/routing.yml
fos_user_group:
    resource: "@FOSUserBundle/Resources/config/routing/group.xml"
    prefix: /group

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.