#19 Preferences Control

5.0-svn
open
General (59)
9
2007-03-07
2007-02-23
No

Write the preferences system.

The database will only have two columns available, so preferences with multiple values would need to be serialized.

Examples:

default_timezone=>en_CA
force_timezone=>false
acl=>serialize(Zend_Acl)
default_view=>month

Preferences should be separated into sections.
- General
- View
- Date and Time
- Users & Groups
- _My Controls_ (Edit the personal options on the user currently logged in)

Discussion

  • Arthur Wiebe

    Arthur Wiebe - 2007-02-23

    Logged In: YES
    user_id=873680
    Originator: YES

    The class interface might look something like this:

    class Preferences {
    protected static $instance;
    protected $preferences;

    public static function getInstance();
    public function __get($name);
    public function set($name, $value); // Must serialize arrays and objects
    public function saveAll(); // Throw exception on failure
    }

     
  • Nick Neufeld

    Nick Neufeld - 2007-03-01

    Logged In: YES
    user_id=1725527
    Originator: NO

    I'm not too comfortable with the Zend Framework yet, but I'll give this a shot.

     
  • Nick Neufeld

    Nick Neufeld - 2007-03-01
    • assigned_to: nobody --> neufelni
     
  • Arthur Wiebe

    Arthur Wiebe - 2007-03-01

    Logged In: YES
    user_id=873680
    Originator: YES

    This class should be easy to write. Good for starters.

    Just a tip, use ACal::get_db(); to get your Zend_Db database object.
    For example:
    $db = ACal::get_db();
    $preference = $db->fetchRow("SELECT * FROM preferences WHERE name = :name", array('name' => $name));

     
  • Arthur Wiebe

    Arthur Wiebe - 2007-03-03

    Logged In: YES
    user_id=873680
    Originator: YES

    Another possible implementation:

    interface Preferences {
    public static $prefs;
    public static $db;

    public static function init(); // Called from index.php
    public static function get($name);
    public static function set($name, $value);
    public static function save(); // Save all changes into database
    }

    init should have an array of initial preference settings and insert them all into the database if no rows yet exist.

    --I'll post one more possible implementation in a few moments.--

     
  • Arthur Wiebe

    Arthur Wiebe - 2007-03-03

    Logged In: YES
    user_id=873680
    Originator: YES

    I hope this is the final possible implementation from me! :)

    Use Zend::register to provide a singleton of the preferences class to the entire code base.
    http://framework.zend.com/manual/en/zend.register.html

    In that case the class would look like this:

    interface Preferences {
    public $prefs; // array of all preference values
    private $db; // Zend_Db object

    public function __construct(); // Does the same thing as init would in the static implementation posted right before this one.

    public function __set($name, $value); // Set preference in $this->prefs[$name] = $value
    public function __get($name); // Get preference from $this->prefs[$name]

    public function save(); // Save all changes to the database
    }

     
  • Arthur Wiebe

    Arthur Wiebe - 2007-03-03

    Logged In: YES
    user_id=873680
    Originator: YES

    It's also possible that the magic __set method could save the value into the database right away so that there would be no need for a separate save() method. This might actually be the easiest and most efficient way. (Hmm, I like it :) )

     
  • Nick Neufeld

    Nick Neufeld - 2007-03-06

    Logged In: YES
    user_id=1725527
    Originator: NO

    So which implementation do you all think would work best? I personally think that the best one would be the last one that you posted, the one that uses Zend::register. I think that the initial one that I started is the worst one of the three. So I think that I will use the last one(with Zend::register) instead. And I also agree that its a good idea to just save the value to the database in the __set method. I'm not too familair with Zend_Db yet, but I'm guessing there isn't much involved in saving a value to the database, so we probably don't really need a seperate method for it. So let me know what you think.

     
  • Arthur Wiebe

    Arthur Wiebe - 2007-03-07

    Logged In: YES
    user_id=873680
    Originator: YES

    I certainly agree with you. The less code and the simpler the code the better. It's much easier to maintain and work on.

    After looking at your latest commit r117, it looks much better. Just some suggestions and pointers though.

    39 $pref = new Preference;
    40 $def_prefs = $pref->__construct();
    41 echo $def_prefs['default_language'];

    Could be changed to:
    $pref = new Preference(); // Automatically calls __construct()
    echo $pref->default_language

    The __get() method would need to be
    return $this->preferences[$name]

    And I suppose the save method can be removed in favor of saving in __set().

    The constructor should not actually set $this->preferences[] but check the preferences database table and if there are no existing rows, add the default prefs into the preferences database table and then some unconditional code should read all the prefs from the database and set the $this->preferences array.

    So far good work! Just one more pointer though.

    In the __set() method, http://ca.php.net/is_object should be used to find out if the input $value is an object, and if it is it should be serialized using the serialize function before being saved. This might be needed for the AC/Auth system.
    And when using __get() this serialized string would have to be unserialized. For example.

    $value = @unserialize($this->preferences[$name]) or
    $value = $this->preferences[$name];
    return $value;
    The @ symbol is used for error message suppression. See http://ca3.php.net/manual/en/language.operators.errorcontrol.php

    Hope this comment is of use to you. Have a good night.

     
  • Arthur Wiebe

    Arthur Wiebe - 2007-03-07
    • priority: 8 --> 9
     

Log in to post a comment.