Права в една колона от таблица

dakata__92

Super Moderator
Здравейте колеги ! Чудих се доста и се замислих как мога и дали е възможно изобщо ако в една тавлица table имам колони user и prava като имам потребител на който искам да задам права. Обаче искам в полето права да записвам няколко права наведнъш. Примерно да има достъп до форума с цифра 1 да има достъп до определена директория с цифрата 1 пак но да е блокиран да пише съобщения с цифрата 2 примерно. Проблема ми е как в колоната права да добавя цифрите по отделно и после да ги проверя по отделно или да ги ъпдейтвам .
_____
table |
-----------------
user | prava
daniel | 1 1 2
-----------------
Примерно искам да имам 3 форми, които по отделно да ъпдейтват определена цифра.
HTML:
<form action='' name='1' method='post'><input type='text' name='avatar'><input type='submit1' name='submit' value='Submit'></form>

<form action='' name='2' method='post'><input type='text' name='banforum'><input type='submit2' name='submit' value='Submit'></form>

<form action='' name='3' method='post'><input type='text' name='url'><input type='submit3' name='submit' value='Submit'></form>

Незнам дали го обясних правилно, незнам дали е и добър вариант, защото иначе ще трябва да съсдам много колони в таблицата за да задам различните права на абоната :)
 
Използвай двойчната система. За всяко нещо определяш по един бит, ако е 1 има право, ако е 0 - не.

Например :

Първи бит - право да чете
Втори бит - право да записва
Трети бит - нещо друго.

Заявкате ще бъде нещо подобно:

Това ще установи първи бит в 1
UPDATE `db` SET `prava` = `prava` | 1 WHERE `id` = $userID LIMIT 1


Това ще установи втория бит в 1
UPDATE `db` SET `prava` = `prava` | 2 WHERE `id` = $userID LIMIT 1


За да ги нулираш използваш това:
UPDATE `db` SET `prava` = `prava` & 0xFE WHERE `id` = $userID LIMIT 1

и т.н.

За да вдигнеш или нулираш няколко бита наведнъж, трябва да използваш подходящото двойчно число:
Това ще установи първи, втори, трети и четвъртия бит:
UPDATE `db` SET `prava` = `prava` | 0xF WHERE `id` = $userID LIMIT 1


Това ще нулира петия, шестия седмия и осмия бит:
UPDATE `db` SET `prava` = `prava` & 0x0F WHERE `id` = $userID LIMIT 1

Надявам се да си схванал идеята.
 
Горе долу зацепих, но не съм правил нещо подобно и ми се струва че ще се омешам много ... Примерно имам 000 като първата 0 е да кажем достъпа до админ панела, втората е дали има право да пише съобщения а третата е дали не е баннат. Искам да го банна и трябва да стане 001 фактически трябва да ползвам:
UPDATE `db` SET `prava` = `prava` | 3 WHERE `id` = $userID LIMIT 1
Защо `prava` = `prava` не разбирам , колоната е равна на себеси ? Да не си имал в предвид `prava` = `$promenliva на цифрата от 0 към 1`. Има ли някъде подобна готова системка и как после д а правя проверките смисъл може предходните цифри да са различни от очакваното.
if($prava == 000)
{
ne bannat
}
if($prava == 001)
{
bannat
}
Но 00 също са променливи числа може да е 011 или, 100 или 101...
 
Не съвсем. Полето е от типа TINYINT (ако ти трябват повече битове използваш друг тип)

TINYINT има осем бита 2^8 = 256 комбинации.

десетично -> двойчно

1 -> 1
2 -> 10
4 -> 100
8 -> 1000

255 -> 11111111

Първият бит е най-десния, най-левият е осми.

В БД записваш едно число от 0 до 255, но чрез логическите опертори му променяш отделните битове.

Примерно ако искаш да провериш третия бит (след като си прочел полето от ДБ и си го сложил в PHP променлива $prava), използваш нещо подобно:

if ($prava & 0x4) {бита е единица} esle {бита е нула}

За първия (най-десния) бит if ($prava & 0x1)

За най-левия : if ($prava & 0x80)

0x80 (HEX) е равно на 128 (DEC)

За да провериш едновременно първи и осми бит : if ($prava & 0x81) ...

http://php.about.com/od/programingglossary/qt/binary.htm
 
Идеята ми допада, но сега като се замислих аз давам примери само с 01 но принципно някой от цифрите ще са 2 3 4 а в двоичната система са само 0 и 1 . Има ли начин да се ползва десетичната система 020, 032 ... Принципно правата ще имат степени затова сега чак се осетих че с двоичната система имам само два избора и ще трябва да добавям още една цифра за проверка 0101 и така вместо да проверявам 011 дали е баннат и с модераторски пост трябва след първата единица да добавя още една нула 0101 като последната единица е баннат, и се получава че ако 0101 е баннат модератор но ако променя нулата между 101 на 1 става 0111 баннат дминистратор. Няма ли начин примеро 011 да е в десетична система и когато примерно стане 021 да е модератор, а 031 да е администратор :) Малко омешана работа :D Ако има и по-лесни вариянти да задам правата на потреител ще е по-добре, но не ми се искаше да са много колони...
 
Тогава може да използваш нещо такова:

$param = '00238';

$access = preg_split('//', $param, -1, PREG_SPLIT_NO_EMPTY);

$access[1] = 4;

$new_param = implode("",$access); // 04238
 
Вместо да си играете с певобразуване от десетична в двоична система и обратно, можете просто да си направите полето VARCHAR и да си правиш стринг с права. В PHP можеш да разгледаш стринга като масив от букви.
PHP:
$prava=$row[prava];
$ban=$prava[0];
$banforum=$prava[1];
Това е прост пример за това, което ти трябва.
 
madmax3_ каза:
Това съм имал в предвид в последния пример.
Да но защо му е да използва друга фунцкия, след като стринга е масив от символи. Най-простият пример е да направи var_dump на стринг.
 
Добре де, съгласен съм че твоя вариант е по-добър. Аз лично не бях се сетил, но това е хубавото на форумите, че може да се видят различни мнения.
 
HerpaMoTeH каза:
Вместо да си играете с певобразуване от десетична в двоична система и обратно, можете просто да си направите полето VARCHAR и да си правиш стринг с права. В PHP можеш да разгледаш стринга като масив от букви.
PHP:
$prava=$row[prava];
$ban=$prava[0];
$banforum=$prava[1];
Това е прост пример за това, което ти трябва.

Това е интересно, но нещо като се замисля не ми се струва, доста неправилно за случая... Как примерно да имам стринг в полето като имам 4 параметра които да са правата. Примерно имам стринг PRAV и всяка буква отговаря на дадено правило и трябва да се променя. Разбирам, че имаш предвид, че ако имам PRA 3 буквен низ, то ако добавя 4-тата буква съм го блокирал примерно защото низа става с една буква повече... Защо си мисля, че с числа е много по добре защото мога да налагам повече от една степен на права, а в случая с низа съм пак като с двоичните числа, само има буква яма буква :)
 
Не съм сигурен дали съм разбрал точно, но ето и моето мнение:
Може да използваш нещо от сорта на 0;1;0;1
При записване ще използваш:
$pravo1 = 0;
$pravo2 = 1;
$pravo3 = 0;
...
$prava = $pravo1.$pravo2.$pravo3; ...
И си запазваш променливата в БД.
При изкарване правиш един explode();
И където ти трябва си взимаш стойността, с дадения ключ на масива.
Отново казвам, не съм съвсем сигурен дали съм те разбрал, но виж примера ми дали ще ти свърши някаква работа :D
 
Извинявам се, чеовдигам темата но тя още ме вълнува ! Последното мнение (това преди моето сега) доста ме заинтригува, но немога да го осъществя моля ви за помощ :(
 
Направи си правата като низ

PHP:
$prava = array(
'forum' => 1,
'druga 4ast ot saita' => 1,
'admin panel' => 0);

Примерно. После за да си запишеш въпросния низ го сериализираш , за да може да се запише в БД

PHP:
$nov = serialize($prava);

и го записваш в БД. После след като вземеш съдържанието от съответната колона трябва да го върнеш да стане отново низ

PHP:
$prava = unserialize($row['prava']);

примерно и вече имаш низ с правата на дадения потребител за всяка секция от сайта която си си добавил в низа

лесно нали :)
 
serialize($prava);

Това какво прави сериализирането и обратното действие ? Този начин ми е чужд смисъл не съм го ползвал никога ! Някъде код с подобно въвеждане да ми предложиш :)
 
ем погледни в manual-a

http://php.net/manual/en/function.serialize.php

не можеш да записваш низове в БД, сериализирането е един вид превръщане на низа в стринг и обратното при десериализирането ;)
 
Аз ще предложа нещо подобно на метода на @Radko. За такъв тип системи за привилегии на мен лично ми допада bit sum метода, който се използва в конфигурацията на някои linux приложения.

На кратко настройките/привилегиите се определят от сбора на стойностите им.

Да предположим, че искаш да дадеш права за добавяне, редактиране и триене на новина. Задаваш мислена стойност за всяко едно действие започвайки от 1 и умножавайки за следващите по 2.

добавяне - 1
редактиране - 2 (1*2)
триене - 4 (2*2)

Да се върнем към таблицата ти с привилегиите. Ако искаш потребител daniel да има права за добавяне само задаваш стойността на колоната prava на 1. Ако искаш -"- права за редактиране задаваш 2 и за триене 4. Но ти искаш потребителя хем да добавя, хем да редактира - тогава стойността е 3 (1+2). Да, но в един момент решаваш, че трябва да може и да трие, тогава стойността става 7 (1+2+4). Сега идва въпроса - как да разбереш какви права има daniel?

Написал съм ти кратък код с пояснения:
PHP:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<?php
//Функцията приема integer параметър
function GetPrivs($bitsum) {
	if(is_numeric($bitsum)) { //Проверява параметъра дали е int, ако не е връща стринг за грешка
		$res = array(); //Създаваме масив с резултатите, които ще върнем по-късно
		while($bitsum > 0) { //Цикъла ще се изпълнява докато параметъра е по-голям от 0
			for($i=0, $val=0; $val <= $bitsum; $val = pow(2, $i), $i++) { //Цикъла създава 2 променливи и повтаря действието, докато получи последната степен на числото 2, с която полученото ще е по малко от параметъра
				$last = $val; //И го присвоява в променливата $last
			}
			$res[] = $last; //След като приключи добавя числото в масива
			$bitsum -= $last; //За да вземем следващото число от сумата (параметъра) изваждаме последното получено, така while цикъла отново се завърта докато условието стане false ин се спре изпълнението
		}
		sort($res); //Подреждаме резултатите в масива
		return $res; //Връшаме масив със стойности (правата)
	} else {
		return "Параметъра трябва да е число."; //Връщаме стринг
	}
}

//Ето и приложение на горната функция
//За по-лесно присвояваме стойностите към константа
define("PRIV_POST", "1");
define("PRIV_EDIT", "2");
define("PRIV_DELETE", "4");

//Взимаме привилегиите на потребителя. За примера съм задал примерна стойност. Ти ще ги взимаш от базата данни подобно на:
//$getprivs = GetPrivs($row[prava]);
$getprivs = GetPrivs(7);
print_r($getprivs); //За примера виждаме какво има в масива
//Ще върне
//Array(  [0] => 1
//		[1] => 2
//		[2] => 4
//) 
//Ако променим параметъра на 6, в масива ще има 2 и 4

echo "<br />";

//Вече можеш да провериш дали потребителя има дадени права, използвайки присвоените константи
if(in_array(PRIV_POST, $getprivs)) { echo "Има права за постване.<br />"; }
if(in_array(PRIV_EDIT, $getprivs)) { echo "Има права за промяна.<br />"; }
if(in_array(PRIV_DELETE, $getprivs)) { echo "Има права за изтриване.<br />"; }
?>
 
http://php.net/manual/en/language.operators.bitwise.php
http://en.wikipedia.org/wiki/Bit_field
Накратко генерираш си число, което съдържа привилегиите и го записваш в базата данни. Като ти потрябва го вадиш това число и проверяваш... Ето едно демо без база данни:
Код:
<?php
	// definirame privilegiite
	define('PRIV_NONE', 0);
	define('PRIV_ADMIN', 1 << 0);
	define('PRIV_BAN', 1 << 1);
	define('PRIV_WRITE', 1 << 2);
	define('PRIV_RENAME', 1 << 3);
	define('PRIV_DELETE', 1 << 4);
	//define .........
	define('PRIV_ALL', PRIV_ADMIN | PRIV_BAN | PRIV_WRITE | PRIV_RENAME | PRIV_DELETE);

	function print_priv() // pomoshtna funkciq
	{
		global $userpriv;
		echo "--prava--<br />\n";
		if ($userpriv & PRIV_ADMIN) echo "admin<br />\n";
		if ($userpriv & PRIV_BAN) echo "ban<br />\n";
		if ($userpriv & PRIV_WRITE) echo "write<br />\n";
		if ($userpriv & PRIV_RENAME) echo "rename<br />\n";
		if ($userpriv & PRIV_DELETE) echo "delete<br />\n";
		echo "------------<br />\n";
	}

	$userpriv = PRIV_NONE; // privilegiite koito ima daden potrebitel

	print_priv(); // printirame pravata

	$userpriv = PRIV_ALL; // slagame vsichkite privilegii

	print_priv();

	$userpriv = PRIV_NONE; // mahame mu vsichki prava

	print_priv();

	$userpriv = $userpriv | PRIV_ADMIN | PRIV_WRITE; // dobavqme prava admin i write kum $userpriv

	print_priv();

	$userpriv = $userpriv & ~PRIV_ADMIN; // premahvame admin ot $userpriv, no write oshte e tam

	print_priv();

	$userpriv = ($userpriv | PRIV_DELETE | PRIV_RENAME) & ~PRIV_WRITE; // dobavqme delete i rename kum $userpriv, no premahvame write

	print_priv();

	echo $userpriv; // pravata vuv vid na chislo, koeto zapisvame v bazata danni

?>
Добавяне на прaва с |, махане с &~ и проверка с &.
 
HerpaMoTeH каза:
Вместо да си играете с певобразуване от десетична в двоична система и обратно, можете просто да си направите полето VARCHAR и да си правиш стринг с права. В PHP можеш да разгледаш стринга като масив от букви.
PHP:
$prava=$row[prava];
$ban=$prava[0];
$banforum=$prava[1];
Това е прост пример за това, което ти трябва.
Пробвах всичко описано тук ! Благодаря много на отзовалите се наистина нещата са доста добре описани от вас, но се указва, че най-простото решение в случая го е дал HerpaMoTeH с примера си за масива. Цаката е просто да се подаде по дефаут в таблицата число започващо с 1 примерно 1212121 и вече си вадите чрез масива нещата :) +1 за решението му страшно просто и не товарещо страниците е, само трябва да се внимава при добавяне в полетата кое чило къде отговаря при ъпдейта :?:
 

Back
Горе