CakePHP en gigabyte vs gibibyte

Iedereen kent het wel. Je koopt een harde schijf van 3 TB, je stopt hem in je PC en ineens is hij nog maar +/-2.7 TB. Wanneer fabrikanten / besturingssystemen de juiste eenheden zouden gebruiken zou dit al een stuk duidelijker zijn.  Voor meer informatie hierover zie Wikipedia.

CakePHP haalt GB en GiB helaas ook door elkaar in de CakeNumber en de NumberHelper class en ik stoorde me daaraan. De oplossing is simpel maar het werkt perfect.

In app/Lib/ van je CakePHP project maak je een nieuw bestand aan genaamd FixedCakeNumber.php. Hierin plaats je de volgende code:

<?php
App::uses('CakeNumber', 'Utility');

class FixedCakeNumber extends CakeNumber {
    
    public static function toReadableSize($size, $si = false) {
        $units = array(1 => 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y');
        
        // defaut values
        $divider = ($si) ? 1000: 1024;
        $binString = ($si) ? '' : 'i';
        
        // exception for byte(s)
        if ($size < pow($divider, $power)) {
            return __dn('cake', '%d Byte', '%d Bytes', $size, $size);
        }

        // caculate size
        $size = max($size, 0); 
        $power = floor(($size ? log($size) : 0) / log($divider)); 
        $power = min($power, count($units) - 1);
        $size = round($size / pow($divider, $power), 2);

        return __d('cake', '%s ' . $units[$power] . $binString . 'B', $size);
    }
}

Nu moeten we een nieuwe Helper aanmaken die gebruikt maakt van de bovenstaande class. Maak een nieuw bestand aan in app/View/Helper/ genaamt FixedNumberHelper.php. Plaats daar de volgende code in:

<?php
App::uses('FixedCakeNumber', 'Lib');
App::uses('NumberHelper', 'View/Helper');

class FixedNumberHelper extends NumberHelper {

    public function __construct(View $View, $settings = array()) {
        parent::__construct($View, $settings);
        $this->_engine = new FixedCakeNumber($settings);
    }
    
    public function toReadableSize($size, $si = false) {
        return $this->_engine->toReadableSize($size, $si);
    }
}

Vervolgens kun je in je controller de helper aanroepen met de volgende regel:

<?php
public $helpers = array('FixedNumber', 'Html', 'Etc');

In je view blijft niets veranderd en kun je de (Fixed)NumberHelper op de normale manier blijven gebruiken. Eventueel kun je, wanneer je dat zou willen. Gebruik maken van de SI eenheid door als tweede parameter true mee te geven.

<?php 
$size = 1000 * 1000 * 1000 * 1000; // 1 TB
echo $this->Number->toReadableSize($size); // output: 931.32 GiB
echo $this->Number->toReadableSize($size, true); // output: 1.00 TB

Leave a Reply