I would like to store user rights as integer in database, but not sure how... How does it work on PHP with for example error_reporting() ?
You got different constants, like... E_ERROR = 1, E_WARNING = 2, E_PARSE = 4, E_NOTICE = 8 etc... and you can set it like error_reporting(E_ERROR | E_NOTICE) ...
In this case E_WARNING | E_NOTICE == 10.
Ok, so I do understand that this is binary operation "OR" and as far as consecutive constants are multiplied by 2, everything should be reversable... but how?
So I got this (int)10. And how do I check that it is E_WARNING and E_NOTICE?
PS. I do understand that it is 1010 on binary notation.
If you want to check if values are set, you can use the bitwise AND & operator.
$warningEnabled = $val & E_WARNING;
This works because (assume $val is 128)...
1000 0000 & # $value
0000 0010 # E_WARNING
Since the same bit isn't set in both, you can tell that $val doesn't have warnings set.
You can execute this in PHP if you like with bindec() function (wrap the above values as strings), it may help you understand better.
If you want to know if the value contains E_WARNING, do:
if ($value & E_WARNING)
Related
It may sounds like a stupid question, but there is something I don't understand about error_reporting and I could not find the explanation on php.net or after a research on google.
My local workstation error is this :
error_reporting(E_ALL - E_DEPRECATED - E_WARNING);
Everyone else at work is :
error_reporting(E_ALL & ~E_DEPRECATED & ~E_WARNING);
My question is : why does it give the same result ? And why do you have to use a binary operation and not a simple substraction?
Thank you in advance.
Because E_DEPRECATED and E_WARNING have completly different bits set and you substract them from E_ALL were all bits are set.
The real difference occurs, if you try to remove two times the same bitset or combined bitsets. In this case, you would remove the 'bits' more than once, which leads to completely wrong values.
In general, you would probably just remove a single option from the error flags and don't know, which bits are currently set
$level = error_reporting();
// at this point, you simply can't use simple math, as you don't know, if the given error reporting option is set or not
$level = $level & ~E_WARNING;
error_reporting($level);
So when I currently view phpinfo() in PHP, my error_reporting is set to some number, which represents the sum of all the error constant values, right?
Let's say, I accidentally set the value of error_reporting to some weird value by accident in .htaccess for example:
-1
Value that is bigger than E_ALL (32768 for example, if I'm correct)
When setting it with a string, I do a typo (**E_AL** & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED) - typo in E_ALL
What would happen, would it be set to some default value? Or from php.ini? I tried setting all the values above and they all were set in the Local Value without any problems.
I'm curious what will happen with any other value as well, will it default to php.ini or what?
Thanks!
PHP uses bitwise operators to determine whether the error level should be reported.. so whatever your integers value is as binary it would bitwise & to see if the error is reported.
E.g.
if E_DEPRECATED were (not saying this is accurate): 01, E_WARNING is 10, E_NOTICE is 100, using E_DEPRECATED | E_WARNING | E_NOTICE would give the binary 111, thus when an error is reported, like E_WARNING, it would take the value set, and bitwise & it to determine whether the report is displayed:
111 & 010 = True, so the error would be reported.
if you just used E_DEPRECATED | E_NOTICE, the binary is 101, so 101 & 010 = False, so the error won't be reported.
Each of these binaries can be converted to base10, 01 = 1, 10 = 2, 100 = 4 etc.
So if you were curious as to which errors would be reported with your random integer you can do:
int & E_WARNING in your PHP parser, if its True then the error will be shown, if its FALSE then the error will be ignored.
This is a good convention to learn, as its very useful when implementing logging on your application too, you can use the same system, and so you don't have to implement a long switch or if .. elseif .. block to determine whether a log level should be logged or not according to config.
/**
* Determines whether this message should be logged based on the provided type and the set threshold
* #access protected
* #param int $type
* #param string $name name of the log to check.
* #return boolean
*/
protected function should_log($type,$name='default') {
return (bool) ($this->getConfig($name)->threshold & $type);
}
so the threshold would be a binary number in your config (which uses constants for readability) then it bitwises & against the provided log type which returns True or False to determine whether to log the message to the logger by name $name... much more optimised.
This is a language-independent question, though I've tagged with languages just to give some tags relevant to the code samples I'm posting below. I'm somewhat new to programming. In various languages I've seen functions that have parameters separated by what I think is the bitwise OR operator. I've used these functions without understanding exactly how the parameters work.
I'll give some examples in case you're not sure what I'm talking about.
From http://www.php.net/manual/en/function.error-reporting.php:
<?php
// Turn off all error reporting
error_reporting(0);
// Report simple running errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);
// Reporting E_NOTICE can be good too (to report uninitialized
// variables or catch variable name misspellings ...)
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
// Report all errors except E_NOTICE
error_reporting(E_ALL & ~E_NOTICE);
// Report all PHP errors (see changelog)
error_reporting(E_ALL);
// Report all PHP errors
error_reporting(-1);
// Same as error_reporting(E_ALL);
ini_set('error_reporting', E_ALL);
?>
From http://www.cplusplus.com/doc/tutorial/files/:
ofstream myfile ("example.bin", ios::out | ios::app | ios::binary);
What exactly is the deal with functions that take parameters like that? Can someone explain?
If you lookup what those constants are, you'll see they'll be like this: 1, 2, 4, 8, 16, etc.
So by adding them all together basically, (what the bitwise does AFAIK from this: "Bit shifting in PHP is arithmetic.") you get a new "number".
http://us2.php.net/manual/en/language.operators.bitwise.php
The manual page has a lot of good info on how it works.
So basically to answer the question of how that function works, it is accepting one integer, and the bitwise operator is doing the "math" and turning those three constants into one new number.
var_dump(E_ERROR);
var_dump(E_WARNING);
var_dump(E_PARSE);
var_dump(E_ERROR | E_WARNING | E_PARSE);
int(1)
int(2)
int(4)
int(7)
So it's the same as:
error_reporting(7);
The same thing as a + b + c. It's just an expression, with
the | (bitwise or) operator.
These are predefined constants, whose values are combined to produce a bit field.
You can use decbin() in PHP to give an insight into how these constants work. decbin produces a string which shows the binary representation of the number.
printf("%02s", decbin(E_ERROR)); // output 01
printf("%02s", decbin(E_WARNING)); // output 10
printf("%02s", decbin(E_ERROR | E_WARNING)); // output 11
(I padded all the values so that the OR operation is clear)
You're passing a single number to the function, whose value represents the options you want to enable. In the function, the options could be extracted using bitwise &:
function func($flag) {
if ($flag & E_ERROR) echo "E_ERROR enabled";
// etc.
}
These are flags. Sometimes a function receives multiple indications on how to operate, such as whether to open the file in binary mode, or in read-only mode, etc... This modes are not mutually exclusive - file can be opened for reading in both text and binary mode, or for writing in both text and binary mode. So you need to be able to specify both options together if you want.
One simple way to achieve this is with bit flags. You have one integer number that holds all the flags. The least significant bit says, for example, if the file is to be opened in text mode (0 - text, 1 - binary), the second bit from the right says whether to open for read or write, etc...
To implement this you use constants:
BINARY = 1
WRITE = 2
Now, if you want to open in both binary and write mode, you use BINARY | WRITE - which results in 3.
The called function then breaks the number back into bits:
isBinary = (flags & BINARY) != 0;
isWriteMode = (flags % WRITE) != 0;
I think
// Report simple running errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);
is equivalent to the following in C or C++
// Report simple running errors
int const error_filter = E_ERROR | E_WARNING | E_PARSE;
error_reporting( error_filter );
Most probably, the symbols E_ERROR, E_WARNING are numbers with a single bit set, such as for example
E_ERROR = 00000001
E_WARNING = 00000010
E_PARSE = 00000100
So, a bitwise-OR of them returns a number with the bit set in all of those positions
error_filter = E_ERROR | E_WARNING | E_PARSE = 00000111
One tricky thing is the type of error_filter, I wrote int but that may not be pedantically correct. One can say uint32_t. Another alternative is to leave the type altogether as in the original code.
I would like to understand the following code from Zenphoto’s plugin:
$plugin_is_filter = 5|ADMIN_PLUGIN|THEME_PLUGIN;
The snippet was disjointed from context. It is just about the Idea behind it.
Are 5|ADMIN_PLUGIN|THEME_PLUGIN Permissions using bitwise?
When it is useful to use?
Thanks for any hint, links.
Bitfields are useful when you need to provide a set of boolean options in one variable. For example, PHP lets you set your error reporting like this:
error_reporting(E_ERROR | E_WARNING | E_PARSE);
In binary, those constants have these values:
E_ERROR 0001
E_WARNING 0010
E_PARSE 0100
If you OR a set of options like that together, you'll be able to express the settings in one field:
E_ERROR | E_WARNING | E_PARSE 0111
Then, you can check for an option being set using AND:
if ($option & E_ERROR === E_ERROR) {
// E_ERROR is set, do something
}
Yes, that is an example of bitwise OR.
You typically use bitwise operations when you're interested in packing multiple boolean flags into a single integer. Bitwise operators allow you to manipulate the individual bits of a byte, meaning an 8 bit byte can be used to store 8 distinct boolean values. It's a technique which was useful when using a whole 8 bit byte to store a single binary "yes" or "no" was considered wasteful.
Today, there is virtually no reason to ever prefer using this kind of bitpacking in PHP (especially with a magic number like that 5) over a simple configuration array. It is a technique which adds virtually nothing of value to PHP code, increasing complexity and decreasing maintainability for no real gain. I would be very skeptical of any new PHP code produced which makes use of bitwise flags in this way.
The variable $plugin_is_filter is being used to flag which plugins to load. Essentially, it is being treated like an array bits that correspond to an enumerated set plugins. For more information, see the links below.
This explains what ADMIN_PLUGIN and THEME_PLUGIN are.
Search the page for '$plugin_is_filter' to get a brief explanation of how to use this variable.
http://www.zenphoto.org/news/zenphoto-plugin-architecture
I hope this helps.
I see that in PHP there are functions that can accept multiple options into a single argument, for example:
error_reporting(E_ERROR & E_WARNING);
I want to implement this kind of functionality into my javascript function. Do you know examples of functions that take this kind of arguments?
I'm totally confused about how does the function know what are the options that are passed...
(Assume it is instead: error_reporting(E_ERROR | E_WARNING); )
Well, it is a bitmask. So E_ERROR might be a number like this (in binary):
0010000
and E_WARNING might be:
0000010
and when they are combined with |, you get
0010010
(a single integer, with multiple bits set)
The function can then check which bits are set using the & bitwise operator. You can certainly do it in javascript, although it might be less common, and possibly less efficient and reliable as the numbers get bigger since javascript doesn't really have integers, they are really floating point numbers.
In javascript, you might prefer to use something like this:
error_reporting({warning: true, error: true});
(edited to show it in the more sensible way, with | not & to combine them)
Yes, it's possible, but it works with |.
var flag1 = 1,
flag2 = 2; // powers of 2
function get(flags) {
if((flags & flag1) === flag1) { // remove all other bits and check
alert('flag1'); // whether you get the flag itself
}
if((flags & flag2) === flag2) {
alert('flag2');
}
}
get(flag1 | flag2); // alerts both
You could of course create a helper function which does the chekcing so that you don't need those parentheses:
function contains(flags, flag) {
return (flags & flag) === flag;
}
http://jsfiddle.net/pimvdb/NpFYj/1/