Отправляет email-рассылки с помощью сервиса Sendsay

PHP 5: Новые возможности.

  Все выпуски  

ZEND FRAMEWORK: Класс Zend_Measure


PHP 5: Новые возможности.

Класс Zend_Measure и его потомки предоставляют простой и легкий способ работы с системами мер. Используя эти классы, вы можете конвертировать меры в другие единицы измерений того же типа. Они могут прибавляться, вычитаться и сравниваться между собой. Меры могут быть автоматически извлечены из введенных пользователем данных. Поддерживаются многочисленные типы мер и единиц измерения.

Например, вот так можно легко преобразовать метры в ярды.

<?php

$unit = new Zend_Measure(100, Zend_Measure::LENGTH);
echo $unit, ' is equal to ', $unit->convertTo(Zend_Measure_Length::YARD);
        
100 m is equal to 109.36132983377 yd
[Подсказка]Подсказка

Полезно обратить внимание на единый формат данных, который используется для представления различных типов мер и единиц измерений: Zend_Measure_<TYPE>::NAME_OF_UNIT, где <TYPE> соответствует хорошо известному физическому или численному свойству (подробнее см. «Типы»), а NAME_OF_UNIT - название единицы измерения.

При создании нового объекта класса Zend_Measure или одного из его специализированных наследников в конструктор передается до трех параметров (обязательными являются только первые два параметра). Первый параметр - это собственно величина, причем, она может быть представлена в виде целого числа, числа с плавающей запятой или строки. Второй параметр - это тип предыдущего значения (см. «Типы»). Наконец, третий, необязательный, параметр - это язык.

Приведем несколько примеров создания таких объектов.

<?php

$unit = new Zend_Measure_Length(1234.56, Zend_Measure_Length::STANDARD);
print $unit;
        
1234.56 m
<?php

$unit = new Zend_Measure_Number('MMVII', Zend_Measure_Number::ROMAN);
print $unit;
        
MMVII
<?php

$string = 'The current Frequency is 50Hz.';
$unit = new Zend_Measure_Frequency($string, Zend_Measure_Frequency::STANDARD);
print $unit;
        
50 Hz

Можно также создать объект «основного» класса Zend_Measure, указав в качестве второго параметра тип меры, как показано ниже.

<?php

$unit = new Zend_Measure(331.46, Zend_Measure::SPEED);
print $unit;
        
331.46 m/s

Вывод данных может быть произведен несколькими способами, показанными ниже. Для этого сначала создадим объект, с которым и будем работать впоследствии.

<?php

$unit = new Zend_Measure_Weight(16, Zend_Measure_Weight::STANDARD);
        

Автоматический вывод. С помощью выражений print или echo на печать выводится непосредствено сам объект. Именно этим способом мы пользовались до сих пор.

print $unit;
16 kg

Вывод значения. Производится с помощью метода getValue().

print $unit->getValue();
16

Тип значения. Производится с помощью метода getType().

print $unit->getType();
KILOGRAM
[Замечание]Замечание

В будущих версиях появится также возможность локализованного вывода.

С помощью соответствующих методов, рассмотренных ниже, появляется возможность производить различные манипуляции с данными (такие, как преобразование, сложение и вычитание, сравнение и т. п.).

[Внимание]Внимание

К сожалению, в версии Zend Framework 0.8.0 существуют определенные разногласия между поставляемой документацией и реальным кодом. В действительности, некоторые из перечисленных ниже методов доступны только для объектов класса Zend_Measure, но не его потомков. Таким образом, при необходимости определенныз манипуляций с данными, следует создавать объекты именно этого класса (см. «Создание»). Однако, в этом случае передаваемая конструктору величина должна быть выражена только в стандартных для создаваемого типа мер единицах измерения.

Методы, доступные только для объектов класса Zend_Measure

  • convertTo()

  • add()

  • sub()

  • compare()

Преобразование. Возможно при помощи метода convertTo(). В качестве параметра передается запрашиваемый тип данных.

[Важно]Важно

Преобразование возможно только в рамках текущего класса (то есть, можно преобразовать, например, метры в футы или килограммы в фунты, но не амперы в градусы или ньютоны).

<?php

$unit = new Zend_Measure(1, Zend_Measure::ANGLE);
echo $unit, ' is equal to ', $unit->convertTo(Zend_Measure_Angle::GRAD);
        
1 rad is equal to 63.661977236758 gr

Сложение и вычитание. Выполняется с помощью методов add() и sub() соответственно. Результат возвращается в виде нового объекта; исходные объекты при этом не изменяются. Возможна организация своего рода цепочечных вычислений.

<?php

$unit1 = new Zend_Measure(1, Zend_Measure::LENGTH);
$unit2 = new Zend_Measure(2, Zend_Measure::LENGTH);
$unit3 = new Zend_Measure(3, Zend_Measure::LENGTH);
print $result = $unit3->add($unit2->sub($unit1));   // 3 + 2 - 1
        
4 m

Сравнение. С помощью метода equals() можно определить, равны (идентичны) ли два объекта (для утвердительного ответа должны совпадать как их значения, так и типы). Для более полного сравнения служит метод compare(), который возвращает -1, 0 или 1 в зависимости от того, меньше, равен или больше проверяющий объект.

<?php

$unit1 = new Zend_Measure(1, Zend_Measure::LENGTH);
$unit2 = new Zend_Measure(2, Zend_Measure::LENGTH);
$unit3 = new Zend_Measure(2, Zend_Measure::LENGTH);
        
Zend::dump($unit2->equals($unit1));
bool(false)
Zend::dump($unit2->equals($unit3));
bool(true)
print $unit1->compare($unit2);
-1
print $unit2->compare($unit1);
1
print
$unit2->compare($unit3);
0

Изменение типа. Ручное изменение типа возможно при помощи метода setType().

<?php

$unit = new Zend_Measure(1, Zend_Measure::LENGTH);
$unit->setType(Zend_Measure_Length::CENTIMETER);
print $unit;
        
100 cm

Изменение значения. Ручное изменение значения возможно при помощи метода setValue(). В качестве второго параметра может быть передана новая единица измерения.

<?php

$unit = new Zend_Measure(0, Zend_Measure::LENGTH);
$unit->setValue(10, Zend_Measure_Length::CENTIMETER);
print $unit;
        
10 cm

Класс Zend_Measure и его потомки поддерживают целый ряд разнообразных мер. Получить полный их список можно с помощью метода getAllTypes().

<?php

$unit = new Zend_Measure(0, Zend_Measure::BINARY);
Zend::dump($unit->getAllTypes());
        
array(28) {
  [0] => string(12) "Acceleration"
  [1] => string(5) "Angle"
  [2] => string(4) "Area"
  [3] => string(6) "Binary"
  [4] => string(11) "Capacitance"
  [5] => string(14) "Cooking_Volume"
  [6] => string(14) "Cooking_Weight"
  [7] => string(7) "Current"
  [8] => string(7) "Density"
  [9] => string(6) "Energy"
  [10] => string(5) "Force"
  [11] => string(9) "Flow_Mass"
  [12] => string(9) "Flow_Mole"
  [13] => string(11) "Flow_Volume"
  [14] => string(9) "Frequency"
  [15] => string(12) "Illumination"
  [16] => string(6) "Length"
  [17] => string(9) "Lightness"
  [18] => string(6) "Number"
  [19] => string(5) "Power"
  [20] => string(8) "Pressure"
  [21] => string(5) "Speed"
  [22] => string(11) "Temperature"
  [23] => string(6) "Torque"
  [24] => string(17) "Viscosity_Dynamic"
  [25] => string(19) "Viscosity_Kinematic"
  [26] => string(6) "Volume"
  [27] => string(6) "Weight"
}
        

Массив доступных для каждого типа единиц измерений возвращает метод getTypeList().

Zend::dump($unit->getTypeList());   // BINARY
array(36) {
  ["BIT"] => array(2) {
    [0] => string(5) "0.125"
    [1] => string(1) "b"
  }
  ["CRUMB"] => array(2) {
    [0] => string(4) "0.25"
    [1] => string(5) "crumb"
  }
  ["NIBBLE"] => array(2) {
    [0] => string(3) "0.5"
    [1] => string(6) "nibble"
  }
  ["BYTE"] => array(2) {
    [0] => string(1) "1"
    [1] => string(1) "B"
  }
  ["KILOBYTE"] => array(2) {
    [0] => string(4) "1024"
    [1] => string(2) "kB"
  }
  [ ...SKIPPED... ]
}
        
  1. Предложите адекватную замену методу convertTo().

  2. Предложите способ обойти ограничение, связанное с отсутствием поддержки некоторых методов наследниками класса Zend_Measure (см. «Манипуляции») и вынуждающее создавать объекты только со стандартными единицами измерений.

    Для этого доработайте следующий пример. Пускай необходимо сложить две длины. Если они выражены в стандартных единицах измерения (в данном случае, в метрах), то решение достаточно просто.

    <?php
    
    $unit1 = new Zend_Measure(1, Zend_Measure::LENGTH);
    $unit2 = new Zend_Measure(2, Zend_Measure::LENGTH);
    print $unit1->add($unit2);
                    
    3 m

    Если же эти длины выражены в других единицах, например, сантиметрах, то создать корректный объект класса Zend_Measure уже не удастся (если только не произвести соответствующие преобразования вручную, что решением, конечно же, не является). С другой стороны, нельзя создать и специализированный объект класса Zend_Measure_Length с подходящей единицей измерения Zend_Measure_Length::SANTIMETER, так как он не поддерживает метод add().

    Какой, тем не менее, существует способ решить проблему?

«Ответы и решения к Глава 17, Класс Zend_Measure»

Created with DocBook


В избранное