views:

121

answers:

4

The error message

[23-Mar-2010 08:36:16] PHP Fatal error: Cannot redeclare humanize() (previously declared in /Users/tmclssns/Sites/nadar/nadar/trunk/webapp/application/filer/models/Filer/Aggregate.php:133) in /Users/tmclssns/Sites/nadar/nadar/trunk/webapp/application/filer/models/Filer/Aggregate.php on line 133

I have a "Filer" model which contains several methods to generate graphs. Each method in there related to generating graphs has the suffix "Graph" in the method name. As we have some performance issues, I try to render the graphs in advance (using cron) instead of rendering them on each request. The code below is what I came up with:

public function generategraphsAction()
    {
        $this->_helper->viewRenderer->setNoRender();
        $config = Zend_Registry::get('config');
        $id = $this->_getParam('filerid');

        $filer = new Filer($id);
        $filer_methods = get_class_methods($filer);

        foreach ($filer_methods as $filer_method) {
            if (preg_match('/^(.*)Graph$/i', $filer_method, $matches)) {
                $path = $config->imaging_caching_dir . "/$id/{$matches[1]}.png";
                $filer->$matches[0]($path);
            }
        }

        // var_dump(get_class_methods($filer)); die;
    }

The result from the var_dump(), when uncommented, is:

array
  0 => string '__construct' (length=11)
  1 => string 'find_by_name' (length=12)
  2 => string 'getPartner' (length=10)
  3 => string 'getSlots' (length=8)
  4 => string 'getGroups' (length=9)
  5 => string 'grouplist' (length=9)
  6 => string 'getAggregates' (length=13)
  7 => string 'getVolumes' (length=10)
  8 => string 'getAggregateVolumes' (length=19)
  9 => string 'getShelves' (length=10)
  10 => string 'getAutoSupportHistory' (length=21)
  11 => string 'getAutoSupportMail' (length=18)
  12 => string 'getOrphans' (length=10)
  13 => string 'getAll' (length=6)
  14 => string 'getDiskRevOverview' (length=18)
  15 => string 'getDiskTypeOverview' (length=19)
  16 => string 'getDiskTypeSizeFunctionOverview' (length=31)
  17 => string 'getLicenses' (length=11)
  18 => string 'removeGroup' (length=11)
  19 => string 'addGroup' (length=8)
  20 => string 'hasGroup' (length=8)
  21 => string 'aggdefaultGraph' (length=15)
  22 => string 'aggbarGraph' (length=11)
  23 => string 'voldefaultGraph' (length=15)
  24 => string 'volbarGraph' (length=11)
  25 => string 'replicationGraph' (length=16)
  26 => string 'getReplicationData' (length=18)
  27 => string 'humanize' (length=8)
  28 => string 'getFiler' (length=8)
  29 => string 'getOptions' (length=10)
  30 => string 'getCifsInfo' (length=11)
  31 => string 'getCifsStats' (length=12)
  32 => string '__get' (length=5)
  33 => string 'tr' (length=2)
  34 => string 'trs' (length=3)
  35 => string 'fieldList' (length=9)

The generategraphsAction() method finds the 'Graph' methods correctly:

array
  0 => string 'aggdefaultGraph' (length=15)
  1 => string 'aggdefault' (length=10)

array
  0 => string 'aggbarGraph' (length=11)
  1 => string 'aggbar' (length=6)

array
  0 => string 'voldefaultGraph' (length=15)
  1 => string 'voldefault' (length=10)

array
  0 => string 'volbarGraph' (length=11)
  1 => string 'volbar' (length=6)

array
  0 => string 'replicationGraph' (length=16)
  1 => string 'replication' (length=11)

However when the first graph is generated, it generates the above listed PHP fatal error. Anyone can come up with a solution to this? I tried to pass by reference or switch a few things around (like re declare the Filer model, $current_filer = new Filer($id); and unset() it again after the request, but resulted in the same error) without much success.

The referenced method "humanize" isn't used for anything I'm doing at the moment, but belongs to the Model because it's used in several other places. Of course, removing the method is not really an option right now, and the model contains several other methods as well so I assume if I just move the humanize method around, it will generate an error on the next one.

For reference, the humanize() method:

public function humanize ($kbytes, $unit = null) {
       // KiloByte, Megabyte, GigaByte, TeraByte, PetaByte, ExaByte, ZettaByte, YottaByte
       $units = array('KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
       if (null !== $units) {
           $i = array_search(substr($unit, -2), $units);
           if (! $i) {
               $i = floor((strlen($kbytes) - 1) / 3);
           }
       } else {
           $i = floor((strlen($kbytes) - 1) / 3);
       }
       $newSize = round($kbytes / pow(1024, $i), 2);
       return $newSize . $units[$i];
   }

Thanks in advance for the help offered.

A: 

I expect your parenthesise are wrong and your function humanize declaration is inside a while loop hence the redeclaration.

Unless of course you are including the file that defines this function twice somewhere?

Chris
Tom
A: 

I found the cause, inside the first method aggdefaultGraph, a call is made to another model:

Filer_Aggregate::sums($this->aggregates);

Inside the Filer_Aggregate model however, a call is made back again to the Filer model:

$dataset[] = array('The rest: '.Filer::humanize($rest), $rest, 'rest', 'white', array_shift($colors));

That's the reason why it shows up that redeclare error. Now I need to find a solution to this issue.

Tom
A: 
public static function sums ($aggregates) {
    function humanize(&$item, $key) {
        $item = Filer::humanize($item);
    }

    $sums = array('size_total' => 0, 'size_usable' => 0, 'size_snapshot_reserve' => 0,
                  'size_snapshot_used' => 0, 'size_snapshot_free' => 0,
                  'size_active_fs_used' => 0, 'size_active_fs_free' => 0,
                  'size_active_fs_reserved' => 0);
    foreach ($aggregates as $aggregate) {
        if ($aggregate->state !== 'online') continue;
        $sums['size_total'] += $aggregate->size_total;
        $sums['size_usable'] += $aggregate->size_usable;
        $sums['size_snapshot_reserve'] += $aggregate->size_snapshot_reserve;
        $sums['size_snapshot_used'] += $aggregate->size_snapshot_used;
        $sums['size_snapshot_free'] += $aggregate->size_snapshot_free;
        $sums['size_active_fs_used'] += $aggregate->size_active_fs_used;
        $sums['size_active_fs_free'] += $aggregate->size_active_fs_free;
        $sums['size_active_fs_reserved'] += $aggregate->size_active_fs_reserved;
    }
    $humanSums = $sums;
    array_walk($humanSums, 'humanize');
    return array($sums, $humanSums);
}

The function inside function is the culprit.

Tom
A: 

Problem fixed.
Adding if(!function_exists('humanize')) block around the method declaration solved it.

Tom