2012-04-18 3 views
18

Мне нужно проверить, не memory_limit не менее 64M в моем установщике скриптов. Это всего лишь часть PHP-кода, который должен работать, но, вероятно, из-за этого «M» он не правильно считывает значение. Как это исправить?проверка memory_limit в PHP

//memory_limit 
    echo "<phpmem>"; 
    if(key_exists('PHP Core', $phpinfo)) 
    { 
     if(key_exists('memory_limit', $phpinfo['PHP Core'])) 
     { 
      $t=explode(".", $phpinfo['PHP Core']['memory_limit']); 
      if($t[0]>=64) 
       $ok=1; 
      else 
       $ok=0; 
      echo "<val>{$phpinfo['PHP Core']['memory_limit']}</val><ok>$ok</ok>"; 
     } 
     else 
      echo "<val></val><ok>0</ok>"; 
    } 
    else 
     echo "<val></val><ok>0</ok>"; 
    echo "</phpmem>\n"; 
+0

Я использую XML-код, так что это невозможно. – Spacedust

+0

Можете ли вы показать 'var_dump ($ phpinfo);' или, по крайней мере, 'var_dump ($ phpinfo ['PHP Core']);', чтобы мы могли видеть, с чего вы начинаете? – DaveRandom

ответ

19

Попробуйте сначала преобразовать значение (например: 64M -> 64 * 1024 * 1024). После этого сделайте сравнение и распечатайте результат.

<?php 
$memory_limit = ini_get('memory_limit'); 
if (preg_match('/^(\d+)(.)$/', $memory_limit, $matches)) { 
    if ($matches[2] == 'M') { 
     $memory_limit = $matches[1] * 1024 * 1024; // nnnM -> nnn MB 
    } else if ($matches[2] == 'K') { 
     $memory_limit = $matches[1] * 1024; // nnnK -> nnn KB 
    } 
} 

$ok = ($memory_limit >= 640 * 1024 * 1024); // at least 64M? 

echo '<phpmem>'; 
echo '<val>' . $memory_limit . '</val>'; 
echo '<ok>' . ($ok ? 1 : 0) . '</ok>'; 
echo '</phpmem>'; 
+4

Предоставленное регулярное выражение является неполным, неточным и приведет к неправильным результатам на различных установках. – hakre

+0

Функция ini_get() генерирует исключение на некоторых серверах, есть ли у вас какие-либо корректировки? – Sahan

+0

Не забывайте обрабатывать memory_limit из -1 – Kieran

4

Пока ваш массив $phpinfo['PHP Core']['memory_limit'] содержит значение memory_limit, он работает следующим образом:

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

Пример:

# Memory Limit equal or higher than 64M? 
$ok = (int) (bool) setting_to_bytes($phpinfo['PHP Core']['memory_limit']) >= 0x4000000; 

/** 
* @param string $setting 
* 
* @return NULL|number 
*/ 
function setting_to_bytes($setting) 
{ 
    static $short = array('k' => 0x400, 
          'm' => 0x100000, 
          'g' => 0x40000000); 

    $setting = (string)$setting; 
    if (!($len = strlen($setting))) return NULL; 
    $last = strtolower($setting[$len - 1]); 
    $numeric = (int) $setting; 
    $numeric *= isset($short[$last]) ? $short[$last] : 1; 
    return $numeric; 
} 

Подробная информация о сокращенной записи являются наброски в a PHP manual's FAQ entry и крайние детали являются частью Protocol of some PHP Memory Stretching Fun.

Позаботьтесь, если настройка -1 PHP здесь не ограничивается, но система делает это. Поэтому вам нужно решить, как установщик относится к этой ценности.

+0

Это компактный код, но он ломается под PHP 7.1+: '$ numeric = 0 + $ setting;' генерирует исключение, потому что параметр $ не является числовым значением из-за суффикса (сообщение «Нечетко сформированное числовое значение, встречающееся в [...]»). в (как минимум) 7.2 вместо этого: вместо $ '$ numeric = (int) $ $'; –

+0

@GabrielMagana: Хорошо, это было довольно давно, я написал это, и использование (int) cast предпочтительнее 0 + в любом случае для преобразования числа. Отредактировал ответ. – hakre

10

Вот еще один простой способ проверить это.

$memory_limit = return_bytes(ini_get('memory_limit')); 
if ($memory_limit < (64 * 1024 * 1024)) { 
    // Memory insufficient  
} 

/** 
* Converts shorthand memory notation value to bytes 
* From http://php.net/manual/en/function.ini-get.php 
* 
* @param $val Memory size shorthand notation string 
*/ 
function return_bytes($val) { 
    $val = trim($val); 
    $last = strtolower($val[strlen($val)-1]); 
    switch($last) { 
     // The 'G' modifier is available since PHP 5.1.0 
     case 'g': 
      $val *= 1024; 
     case 'm': 
      $val *= 1024; 
     case 'k': 
      $val *= 1024; 
    } 
    return $val; 
} 
2

не настолько точны, но более простое решение:

$limit = str_replace(array('G', 'M', 'K'), array('000000000', '000000', '000'), ini_get('memory_limit')); 
if($limit < 500000000) ini_set('memory_limit', '500M');      
0

очень старый пост. но я просто оставлю это здесь:

/* converts a number with byte unit (B/K/M/G) into an integer */ 
function unitToInt($s) 
{ 
    (int)preg_replace_callback('/(\-?\d+)(.?)/', function ($m) { 
     return $m[1] * pow(1024, strpos('BKMG', $m[2])); 
    }, strtoupper($s)); 
} 

$mem_limit = unitToInt(ini_get('memory_limit')); 
+2

Что это? Не просто отправьте код, пожалуйста. Объясните, как и почему этот ваш код решит проблему. – UmarZaii

+0

извините за это. отредактированный код. – Gibz

Смежные вопросы