2014-01-12 2 views
3

Я регистрирую пользователей через проверку подлинности Windows, а затем сохраняю эти права пользователя в переменной сеанса. Я использую ограниченный способ хранения прав в базе данных, а именно:in_array vs strpos для производительности в php

$rights //retrieved from database 
= 'read,edit,delete,admin' 

так что мой вопрос должен я;

//generate variable 
$_SESSION['userrights'] = $rights ($rights is retrieved from database) 

//use strpos to find if right is allowed 
if (strpos($_SESSION['userrights'],"admin") !== false) { // do the function } 

ИЛИ

//make array of rights 
$_SESSION['userrights'] = explode(',',$rights) 

//use in_array to find if right is allowed 
if (in_array("admin",$_SESSION['userrights'])) { // do the function } 

немного OCD вопрос, как я полагаю, разница будет в значительной степени ничтожна за то, что я делаю, но который был бы быстрее (использовать меньше ресурсов) метод?

Любые ответы, оцененные за исключением тех, которые оскорбляют мой метод хранения прав!

+2

Используйте второй способ, конечно. Проверка определенного значения в массиве - гораздо лучший метод по сравнению с поиском значения внутри строки. Обратите внимание, что порядок аргументов 'in_array' - это« игла, стог сена », а не« сена, игла », как у вас там. – jszobody

+0

2:50 ленивая копия и вставка! оцените ответ! – DJB

+2

Почему вы не храните их в качестве ключей в ассоциативном массиве? Это должно быть быстрее, чем либо. – Barmar

ответ

4

StrPos это самый быстрый способ для поиска текста иголки, PHP.net сайта:

If you only want to determine if a particular needle occurs within haystack, use the  faster and less memory intensive function strpos().... 
-1

Рассматривали ли вы возможность делать запрос к базе данных, если $_SESSION['userrights'] существует в базе данных? Вы уже делаете запрос, чтобы получить список прав в своем примере, почему бы не сделать запрос для определенного $_SESSION['userrights'] и проверить, есть ли какие-либо строки?

+0

У меня создалось впечатление, что запрос будет гораздо более интенсивным, чем strpos или in_array. Я уже запрашиваю базу данных и сохраняю значение в сеансе var, поэтому у меня есть значения, которые нужно передать. Если я неправильно понимаю, вы предлагаете мне запрашивать каждый раз, когда я хочу проверить, имеет ли пользователь определенный уровень прав? (У меня есть отображение нескольких вещей на основе того, есть ли у пользователя один или другой) – DJB

+0

Сколько раз вы просматриваете права пользователя на странице? – Hayden

+0

Приложение еще не закончено, но я предполагаю, что максимум сейчас будет 2/3 – DJB

8

Поскольку я часто работаю с большими наборами данных, я бы пошел с isset или !empty на ассоциативный массив и проверить ключ, как предлагает @Barmar. Вот быстрый 1M тест на ™ i3-540 (3,06 ГГц) Intel® Core

$test = array("read", "edit", "delete", "admin"); 

echo "<pre>"; 

// --- strpos($rights,$test[$i%4]) --- 

$rights = 'read,edit,delete,admin'; 
$mctime = microtime(true); 
for($i=0; $i<=1000000; $i++) { if (strpos($rights,$test[$i%4]) !== false) { }} 
echo ' strpos(... '.round(microtime(true)-$mctime,3)."s\n"; 

// --- in_array($test[$i%4],$rights) --- 

$rights = array("read", "edit", "delete", "admin"); 
$mctime = microtime(true); 
for($i=0; $i<=1000000; $i++) { if (in_array($test[$i%4],$rights)) { }} 
echo 'in_array(... '.round(microtime(true)-$mctime,3)."s\n"; 

// --- !empty($rights[$test[$i%4]]) --- 

$rights = array('read' => 1, 'edit' => 1, 'delete' => 1, 'admin' => 1); 
$mctime = microtime(true); 
for($i=0; $i<=1000000; $i++) { if (!empty($rights[$test[$i%4]])) { }} 
echo ' !empty(... '.round(microtime(true)-$mctime,3)."s\n"; 

// --- isset($rights[$test[$i%4]]) --- 

$rights = array('read' => 1, 'edit' => 1, 'delete' => 1, 'admin' => 1); 
$mctime = microtime(true); 
for($i=0; $i<=1000000; $i++) { if (isset($rights[$test[$i%4]])) { }} 
echo ' isset(... '.round(microtime(true)-$mctime,3)."s\n\n"; 

echo "</pre>"; 

Побеждает isset:

strpos(... 0.393s 
in_array(... 0.519s 
    !empty(... 0.232s 
    isset(... 0.209s 
+0

Характеристики производительности исходят от использования ассоциативного массива вместо списка. Хотя ваш тест немного испорчен, вы не включаете никакого баланса и проверяете только худший сценарий «strpos» и 'in_array' (последняя запись в массиве/строке). Чтобы сделать его более справедливым, вы должны использовать modulo 4 на $ i и извлекать его из массива. Однако ассоциативные массивы лучше масштабируются, а ложные результаты также быстрее с ними. – Aidiakapi

+0

@Aidiakapi Спасибо за ваш комментарий! Немного изменил его. –

+2

@ Jonny5 Благодарим вас за это усилие, чтобы успокоить мой ocd! Я использую isset из-за ваших ответов и ответов Barmar .. высоко ценят – DJB

0

Ориентиром, что доказательств того, что strpos не самый быстрый метод, но быстрее, чем in_array:

<?php 

echo phpversion() . PHP_EOL; 

// build random array 
$array = array_fill(0, 10000, 16); 
$array = array_map('openssl_random_pseudo_bytes', $array); 
$array = array_map('bin2hex', $array); 
$array_flipped = array_flip($array); 
$string = implode($array); 
$random_keys = array_rand($array_flipped, 10); 

$loops = 10000; 

$start = microtime(true); 
for ($i = 0; $i < $loops; $i++) { 
    strpos($string, $random_keys[ rand(0, 9) ]); 
} 
echo __LINE__ . ': ' . round(microtime(true) - $start, 5) . PHP_EOL; 

$start = microtime(true); 
for ($i = 0; $i < $loops; $i++) { 
    in_array($random_keys[ rand(0, 9) ], $array); 
} 
echo __LINE__ . ': ' . round(microtime(true) - $start, 5) . PHP_EOL; 

$start = microtime(true); 
for ($i = 0; $i < $loops; $i++) { 
    isset($array_flipped[ $random_keys[ rand(0, 9) ] ]); 
} 
echo __LINE__ . ': ' . round(microtime(true) - $start, 5) . PHP_EOL; 

$start = microtime(true); 
for ($i = 0; $i < $loops; $i++) { 
    $array_flipped = array_flip($array); 
    isset($array_flipped[ $random_keys[ rand(0, 9) ] ]); 
} 
echo __LINE__ . ': ' . round(microtime(true) - $start, 5) . PHP_EOL; 

?> 

Результат:

5.6.31 
19: 1.11484 
25: 1.3109 
31: 0.00237 
38: 13.64204 

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

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