Symfony World blog is not maintained anymore. Check new sys.exit() programming blog.

update record changes with sfDoctrineActAsSignablePlugin: Signable behavior

sfDoctrineActAsSignablePlugin


The plugin is fairly simple, it contains only a Doctrine temlate and a template event listener (basic stuff to implement a new Doctrine Behavior). It was initially released by Vitaliy Tverdokhlib.


Signable Doctrine Behavior


The plugin provides a Signable behavior ready to be used in your models:

Model:
  actAs:
    Signable: ~
It works very similarly to Timestampable behavior: created_at and updated_at timestamp columns are added, storing information about the datetime that a record was created and last updated. Signable adds created_by and updated_by columns storing information about the user that created or last updated a record.


The plugin may be used along with sfDoctrineGuardPlugin. This gives you a possibility to refer to the sf_guard_user table. No additional configuration is needed, the plugin automatically checks if sfDoctrineGuardPlugin is installed.


configuration


The most important thing you can configure is to choose the type of the user field: it can be either string or integer:

Model:
  actAs:
    Signable:
      created:
        type: string
      updated:
        type: integer
If string type is chosen, you can simply display the name of the user (e.g. in frontend blog article display page), but can do nothing further. If you choose integer, you store ID of the user, which gives you a possibility to refer to the user in the user database table (which gives you all possibilities of using user Doctrine model).


You can configure the behavior to meet your needs. Let's take a look at some examples:


  • The created_by and updated_by column names are the default ones. You may change them:
    Model:
      actAs:
        Signable:
          created:
            name: creator_id
            type: integer
          updated:
            name: update_username
            type: string
    

  • You want to know which user has created a record only (meaning that the user who updated the record is not important). In this case, disable udpated option:
    Model:
      actAs:
        Signable:
          updated:
            disabled: true
    

  • You want to add the Signable behavior to models of an existing project that already maintaines lots of data. And you want the created_by/updated_by user to be not null, because there's always someone who creates or updates a record. In a big project (a CRM, ERP, etc.) it's a good solution to create a system user (with id=1 for example) who represents all system actions (a daemon creating/updating objects from cron tasks):
    Model:
      actAs:
        Signable:
          created:
            options:
              notnull: true
              default: 1
          updated:
            options:
              notnull: true
              default: 1
    
    In this case, adding created_by/updated_by database columns will fill them initially with 1 (system user) and you can refer to the user (e.g. using getUser() method), being sure that there's always a user referenced. And all further modifications will store real user ids.


real world examples



  • Blog articles are being added by application users. You add Signable behavior (with type: string) and you may use:
    echo $article->getCreatedBy();
    in the app frontend to display who submitted the article.

  • An E-commerce applications management system: users (employees) log in to the system and create orders that customers submit. You add Signable behavior (with type: integer). Whenever an order is created, the created_by is filled with the user ID. The application can generate statistics on which users added the most orders.


No matter if your project is a complex management system with extended backend - or a small company website with mainly frontend developed - you'll find this plugin useful!

2 comments:

  1. Really helpful extra example you have provided here.

    I found a problem when user update a Signable record (say an Article) by submitting the form
    created_by set to null
    updated_by set to the correct user id.

    The way I solve this problem is by adding the following to ArticleForm configure() method
    unset($this['created_by'])
    unset($this['update_by'])

    ReplyDelete
  2. Seems strange... Actually, Signable behavior works in such way:
    * new record sets created_by and updated_by to the same value
    * updating record sets only updated_by and leaves create_by alone.

    Just take a look at the listener's code: http://trac.symfony-project.org/browser/plugins/sfDoctrineActAsSignablePlugin/trunk/lib/listener/Signable.php - there are preInsert and preUpdate methods which do all the job. If created_by is changed during record update (set to null or set to anything, just changed) - this means there has to be another mechanism which modifies the model record. Examine your form and controller code - maybe you're trying to set created_by manually during update?

    ReplyDelete