Development

sfGuardDoctrinePlugin

You must first sign up to be able to contribute.

The sfGuardDoctrine Plugin

Description

sfGuardDoctrinePlugin was originally a port of the propel sfGuardPlugin. It has since changed and new functionality has been added. The plugin now has 6 modules: sfGuardUser, sfGuardGroup, sfGuardPermission, sfGuardAuth, sfGuardRegister, and sfGuardForgotPassword. The plugin is still beta because of sfDoctrinePlugin still being beta, as well as Doctrine itself.




Installation

Prerequisites

symfony 1.0.x+, and the latest version of sfDoctrine are required.

Download the plugin

sfGuardDoctrine is a regular symfony plugin. Please do not install it via the command line. Currently only the subversion method is supported.

Download the plugin from svn by running:

 svn co http://svn.symfony-project.com/plugins/sfGuardDoctrinePlugin/branches/symfony-1.0 sfGuardDoctrinePlugin

and place that in the plugins directory of your project. To update:

> svn update

You may also browse the source code of sfGuardDoctrine.

Setting the plugin as an svn:externals

To have the plugin updated when you do a svn update run:

> svn propedit svn:externals plugins

and type:

sfGuardDoctrinePlugin  http://svn.symfony-project.com/plugins/sfGuardDoctrinePlugin/branches/symfony-1.0




Setup

Build the model

To build the Doctrine model classes for sfGuardDoctrine, run:

> symfony doctrine-build-model

Insert new tables

This will insert the tables sql for the new models you just generated. You must clear your cache first.

> symfony cc
> symfony doctrine-insert-sql <app_name>

Loading Data

** WARNING! Fixtures dump/load functionality in sfDoctrine does not function 100%, use at your own risk. **

The default sfGuardDoctrine fixture is located in project/plugins/sfGuardDoctrinePlugin/data/fixtures/fixtures.yml. You should copy this file into your project data/fixtures directory to maintain the independence of the svn plugin. Another benefit of this is that you can then use your existing load_data batch file. Be sure that

create_tables:  true

is set in your doctrine.yml (this is the default).

Remaining Setup

sfGuardDoctrine follows an identical setup to sfGuardPlugin, you can follow all instructions there after the propel-specific instructions, which end with:

> symfony propel-load-data

near the top of the page.


Troubleshooting

The module "sfGuardAuth|sfGuardUser|sfGuardRegister|sfGuardForgotPassword" is not enabled.

For some reason (at least for me), the enabled_modules instructions given on the sfGuardPlugin page don't work.

all:
  .settings:
    enabled_modules: [default, sfGuardAuth]

is ignored, I had to explicitly set these same values for each environment i was using them in. so:

dev:
  .settings:
    enabled_modules: [default, sfGuardAuth]

worked for myapp_dev.php/login.

'Field 'permission_id' doesn't have a default value' error

if you get the following error when loading the default sfGuardDoctrine fixture:

>> Filling   class "sfGuardUserGroup"
.
  [Doctrine_Connection_Mysql_Exception]
  SQLSTATE[HY000]: General error: 1364 Field 'permission_id' doesn't have a default value

there is a simple fix. change:

sfGuardGroupPermission:
  adminGroupPermission:
    sfGuardGroup:       adminGroup
    sfGuardPermission:  adminPermission

to:

sfGuardGroupPermission:
  adminGroupPermission:
    sfGuardPermission:  adminPermission
    sfGuardGroup:       adminGroup

to avoid this foreign-key-related error.

Getting the message 'Override this function in your sfGuardUserTable class so it queries for the user based on the username or email address'

After generating the default model you also need to add this function 'retrieveByUsernameOrEmailAddress' to the generated sfGuardUserTable.class.php in your own application directory, so it will override the default plugin's function. NEVER change it in the plugin directory itself, because you will lose your changes after updating.

Using the sfGuardRegister module

If you want to use the sfGuardRegister you'll have to create a module with the same name in your application's modules directory (easiest is to do symfony init-module appname modulename) and extend it. Do not forget to include the BasesfGuardRegisterActions? class.

I don't like using sf_guard_user_profile, I want my own user information available

This can be done very easily and with doctrine it will only create one query which is very nice.

Override the getGuardUser() function in myUser.class.php

class myUser extends sfGuardSecurityUser
{

    public function getGuardUser()
    {
        if ( !$this->user && $id = $this->getAttribute( 'user_id', null, 'sfGuardSecurityUser' ) )
        {
            $q = new Doctrine_Query();
            $q->select('s.*, u.*, p.*, p2.*, a.*, a2.*');
            $q->from('sfGuardUser s');
            $q->leftJoin('s.User u');
            $q->leftJoin('u.Phone p')->leftJoin('p.PhoneType p2');
            $q->leftJoin('u.Address a')->leftJoin('a.AddressType a2');
            $q->where('s.id = ?', $id);

            $this->user = $q->execute()->getFirst();

            if ( !$this->user )
            {
                // the user does not exist anymore in the database
                $this->signOut();

                throw new sfException( 'The user does exist anymore in the database.' );
            }
        }

        return $this->user;
    }
}

You'll notice I have User, Phone, PhoneType?, Address, AddressType? as tables for each of my users. I have my schema.yml file looking like this. I'll only show the abbreviated User, Phone, and PhoneType?. Address is the same as Phone

User:
  tableName: user
  columns:
    prefix: string(5)
    first_name: string(20), notblank: true
    middle_name: string(20)
    last_name: string(20), notblank: true
    suffix: string(10)
    company: string(45)
    date_of_birth: date, notblank: true
    updated_at: timestamp
    created_at: timestamp
    sf_guard_user_id:
      foreignClass: sfGuardUser
      foreignName: sfGuardUser
      localName: User
      cascadeDelete: true
      unique: true

Phone:
  tableName: phone
  columns:
    user_id:       
      foreignClass: User
      foreignName: User
      localName: Phone
      cascadeDelete: true
    phone_type_id:
      foreignClass: PhoneType
      foreignName: PhoneType
      localName: Phone
    number: string(20)
    extension: string(10)
    is_primary: boolean
    updated_at: timestamp
    created_at: timestamp

Phone:
  tableName: phone
  columns:
    user_id:       
      foreignClass: User
      foreignName: User
      localName: Phone
      cascadeDelete: true
    phone_type_id:
      foreignClass: PhoneType
      foreignName: PhoneType
      localName: Phone
    number: string(20)
    extension: string(10)
    is_primary: boolean
    updated_at: timestamp
    created_at: timestamp

Now when ever you need information about the logged in user you can simply call in the template:

sfGuardUser Username: <?php echo $sf_user->getUsername() ?> <br />
User First Name:      <?php echo $sf_user->getGuardUser()->User->getFirstName() ?>
Phone Numbers:
<?php foreach($sf_user->getGuardUser()->User->Phone as $phone): ?>
Phone Type(__toString(), going to be name): <? echo $phone->getPhoneType(); ?>
Phone Name:           <? echo $phone->getNumber(); ?>
Phone Extension:      <? echo $phone->getExtension(); ?>
<?php endforeach; ?>




Active tickets

#2602
[sfGuardDoctrinePlugin] remove user assignment when editing group or make it configurable
#3506
[PATCH]: sfGuardDoctrinePlugin/trunk: unique constraint on algorithm instead of username
#3507
[PATCH]: sfGuardDoctrinePlugin/trunk: wrong column in PluginsfGuardUserTable (is_Active)