xoops forums

hervet

Friend of XOOPS
Posted on: 2009/8/13 17:45
hervet
hervet (Show more)
Friend of XOOPS
Posts: 2267
Since: 2003/11/4
#1

Parameters class for methods of classes ...

All my projects are made of classes and each classes are made of methods.
Sometimes those methods contains several parameters. I estimate that over 4
parameters it's not possible to maintain easily those methods (and there
clients).

For example, in a method like this :
class myclass
{
    function 
mymethod($param1$param2$param3$param4$param5)
    {
    
    }
}

There are too much parameters, it's difficult to maintain them in the
method itself and in the clients of this method, it's hard to remember
what parameters are used for (each of them).
If your parameters' list grow, it's becoming a nightmare.

So I have made a new class to solve this.
Put the class at the end of this post in a Php file.
This class will only runs with Php 5 (a recent version).

When you create a method which needs several parameters, like this one :
function mymethod($param1$param2$param3$param4$param5)
    {
    
    }


You change its declaration's code to this :
function mymethod(mymodule_parameters $parameters)
    {
    
    }


Then in your class, you set the default's values like this.
For example, if your method needs 4 parameters, "start", "limit", "sort" and "order", you merge the parameters passed to your method with the default values awaited like this :
(the extend method mimic the jQuery's equivalent)

$parameters $parameters->extend(new mymodule_parameters(array('start' => 0'limit' => 10'sort' => 'firstname''order' => 'ASC')));


So, your method looks like this :
function mymethod(mymodule_parameters $parameters)
    {
        
$parameters $parameters->extend(new mymodule_parameters(array('start' => 0'limit' => 10'sort' => 'firstname''order' => 'ASC')));
        
$criteria = new Criteria('myfield'10'>');
        
$criteria->setSort($parameters['sort']);
        
$criteria->setOrder($parameters['order']);
        
$criteria->setStart($parameters['start']);
        
$criteria->setLimit($parameters['limit']);
        
    }


It's like using associative arrays as parameters but with more power because the class extends ArrayObject (from the SPL)
Now I can call this method like this :

1/ "Without" parameters :
$myobject->mymethod(new mymodule_parameters());


2/ With only one parameter:
$myobject->mymethod(new mymodule_parameters(array('sort' => 'lastname')));


3/ I can define my parameters elsewhere, as I want and pass them to the method, later:
$parameters = new mymodule_parameters(array('sort' => 'lastname'));
$myobject->mymethod($parameters);


or like this (chaining):
$parameters = new mymodule_parameters();
$parameters->setSort('lastname')->setStart($start)->setLimit(10)->setOrder('DESC');
$myobject->mymethod($parameters);


or even like this (like an array):
$parameters = new mymodule_parameters();
$parameters['sort'] = 'lastname';
$parameters['start'] = $start;
$parameters['limit'] = 10;
$parameters['order'] = 'DESC';
$myobject->mymethod($parameters);


or like this too (as class properties):
$parameters = new mymodule_parameters();
$parameters->sort 'lastname';
$parameters->start $start;
$parameters->limit 10;
$parameters->order 'DESC';
$myobject->mymethod($parameters);


You can display a parameter in two ways:
echo $param['sort'];
echo 
$param->limit()


I have just made this class so it can contains errors, it's not yet fully tested.

PROS
- When you call a method, you can call it with parameters in any order you want
- When you call a method, you can just pass the parameters you want
- You are using named parameters
- It's more easy to maintain (for the clients of the methods) when your parameters change (you don't have to review all your code)

CONS
- It must be slower (but the class extends ArrayObject which is made in C)
- In IDEs like Zend Studio or Netbeans, the autocompletion of your methods can lake the parameters (except if you use phpDocumentor comments)
- Even when you want to call a method without giving it parameters, you have to pass it a "mymodule_parameters" object
But it can be solved by changing your methods declarations.

Here is the full code of my class:
<?php
/**
 * ****************************************************************************
 * mymodule - MODULE FOR XOOPS
 * Copyright (c) Hervé Thouzard of Instant Zero (http://www.instant-zero.com)
 *
 * You may not change or alter any portion of this comment or credits
 * of supporting developers from this source code or any supporting source code
 * which is considered copyrighted (c) material of the original comment or credit authors.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @copyright       Hervé Thouzard of Instant Zero (http://www.instant-zero.com)
 * @license         http://www.fsf.org/copyleft/gpl.html& ...  public license
 * @package         mymodule
 * @author             Hervé Thouzard of Instant Zero (http://www.instant-zero.com)
 *
 * Version : $Id:
 * ****************************************************************************
 */

/**
 * Class used for parameters passing to classes methods
 *
 * @copyright       Hervé Thouzard of Instant Zero (http://www.instant-zero.com)
 * @license         http://www.fsf.org/copyleft/gpl.html& ...  public license
 * @package         mymodule
 * @author             Hervé Thouzard of Instant Zero (http://www.instant-zero.com)
 * @version 1.0
 *
 * Example :
 *
 * // Instanciate it like this
 * $param = new mymodule_parameters();
 *
 * // Create several parameters in one time:
 * $param->setLimit(10)->setSort('manu_name');
 *
 * // Set a parameter with the array convention:
 * $param['sort'] = 'first_name';
 *
 * // Set a parameter as a class property:
 * $param->order = 'DESC';
 *
 * // Display a parameter, first way:
 * echo "<br />value=".$param['sort'];    // DESC
 *
 * // Another method to show it, as a class method:
 * echo $param->limit();    // 10
 *
 * // Set the default values
 * $newParameters = $param->extend(new mymodule_parameters(array('sort' => 'firstName', 'start' => 0, 'limit' => 15, 'showAll' => true)));
 *
 */
class mymodule_parameters extends ArrayObject
{
    
/**
     * Permet de valoriser un indice de la classe comme si c'était une propriété de la classe
     *
     * @example $enregistrement->nom_du_champ = 'ma chaine'
     *
     * @param string $key    Le nom du champ à traiter
     * @param mixed $value    La valeur à lui attribuer
     * @return object
     */
    
function __set($key$value)
    {
        
parent::offsetSet($key$value);
        return 
$this;
    }

    
/**
     * Valorisation d'un indice de la classe en utilisant un appel de fonction basé sur le principe suivant :
     *         $maClasse->setLimit(10);
     * Il est possible de chainer comme ceci : $maClasse->setStart(0)->setLimit(10);
     *
     * @param string $method
     * @param mixed $args
     * @return object
     */
    
function __call($method$args)
    {
        if(
substr($method03) == 'set') {
            
parent::offsetSet(strtolower(substr($method31)).substr($method4), $args[0]);
            return 
$this;
        } else {    
// Affichage de la valeur
            
return parent::offsetGet($method);
        }
    }

    
/**
     * Méthode qui essaye de faire la même chose que la méthode extend() de jQuery
     *
     * On lui passe les valeurs par défaut que l'on attend et la méthode les compare avec les valeurs actuelles
     * Si des valeurs manquent, elles sont ajoutées
     *
     * @param mymodule_parameters $defaultValues
     * @return mymodule_parameters
     */
    
function extend(self $defaultValues)
    {
        
$result = new self;
        
$result $this;
        foreach(
$defaultValues as $key => $value) {
            if(!isset(
$result[$key])) {
                
$result[$key] = $value;
            }
        }
        return 
$result;
    }
}
?>

trabis

Core Developer
Posted on: 2009/8/13 18:44
trabis
trabis (Show more)
Core Developer
Posts: 2269
Since: 2006/9/1 1
#2

Re: Parameters class for methods of classes ...

Thanks for sharing! This is why we need php5 and fast!

trabis

Core Developer
Posted on: 2009/8/13 18:58
trabis
trabis (Show more)
Core Developer
Posts: 2269
Since: 2006/9/1 1
#3

Re: Parameters class for methods of classes ...

This is good method to use on a hooking system. Instead of passing an array has argument we can pass a class.

I use a registry class in mymenus module and I use setEntry, getEntry, no magic calls, but this class extending ArrayObject just give it a new dimension.

Also we could use this methods in callback functions that only accept the class name and one argument.

dbman

Friend of XOOPS
Posted on: 2009/8/14 1:04
dbman
dbman (Show more)
Friend of XOOPS
Posts: 172
Since: 2005/4/28
#4

Re: Parameters class for methods of classes ...

thanks herve