I'm using Zend_Form subclasses to pass array of data to my controllers and sometimes I need some extra logic in the controllers, as such:
$post = $request->getPost();
if (array_key_exists('signatureData', $post) && !empty($post['signatureData'])) {
...
}
To avoid getting php warnings, first, I need to check if the signatureData key exists and only then I can check if the value is not empty.
Anyway I can make this IF statement a little shorter without adding custom php function?
Accepted standard :
if (isset($post['signatureData']) && !empty($post['signatureData']))
Apparently, this is also possible :
if (!empty($post['signatureData']))
-edit-
If you're really lazy, there's a dirty way :
if (#$post['signatureData'])
I'd recommend against it though.
As pointed out in the comments, don't actually use this. It's bad, bad, bad bad, bad. Really though, please don't ever use it. It's only here as a reference.
Using zf, use this
If ($request->getParam('signatureData', false))
Best practice IMO
Related
I have a method like this:
public function create (array $hash) {
$id = $hash[ID_KEY];
$this->store[$id] = $hash;
}
I want to guard it against bugs caused by bad input.
For instance, my code can mistakenly pass $hash with
$id = '' or $id = null,
in which case it will be stored silently referenced by null. Instead I want to see a warning and revise my code to get rid of it. So I guess the best way is to throw Exception:
if (! $id) throw new Exception("Hash with empty id");
Note that I am using empty strings as default values for several method arguments and for default return values, so this kind of bug can easily occur. (Using null instead of empty string here doesn't seem to change anything, even if it is not recommended by Uncle Bob.)
The problem is -- there are many methods like that. Is it really best practice to guard each of them for each argument that can become null but shouldn't?
For instance, another method does only reading. Then it seems there is no need to guard against null because nothing will ever be stored referenced by null, right? Or shall I still guard defensively, to prepare for the case I may somewhere in the future decide to allow storage referenced by null and forget to adjust the guards?
This sounds kind of the safest way but would clutter all methods with bulks of guarding code for all indices involved there. Is this really the best way?
EDIT.
I put more guards and indeed discovered few bugs that I wouldn't find otherwise. Also my tests didn't spot them.
Furthermore, it helped to better understand the role of read methods - to return value if found or return empty Array if not. The input $id = null goes under not found and hence also returns empty Array. That way the method is clean and consistent.
You can use PHP's is_null() and empty() to easily manage this kind of output.
Also I suggest you to write a list of function used only in debug (since you want to perfectionate your code). Call these function in each method you want to test and set a constant like DEBUG_MODE to handle the debug functions' behavior. All of this could be also done using unit testing, which would require more attention and time. But if you have both or want to learn something new, unit testing is clearly a better choice.
Also it is a good practice to handle ALL CASES you can think of. For instance, if your "reading method" expects not to find a null value (because you think there are none because you eradicated by testing over testing), if this "reading method" happens to find a null value a "ugly" PHP error would be shown somewhere, or worse, if error_report is shut you might never see a problem, or even worse, the code might continue its execution and utterly damage further data.
I was wondering if it is always necessary to use something like is_array() before every foreach i do.
In case the variable is not an array, it throws an error.
So i always use:
if(is_array($users)) {
foreach($users as $user){
}
}
What would you recommend me?
Thanks.
Well if you know your code well enough, there should be no reason to have to check if it is an array.
Otherwise, if the variable changes type that often I would suggest tweaking your code a bit so it does not do that.
Other than that, using that if statement is the way to go.
If you're sure that something is an array or otherwise implements Iterable, you obviously don't need the extra if condition. If you're not sure, then obviously checking the type will make your code more reliable.
Some hacks I've seen include casting the variable to an array: (array)$users. This is not recommended though, it's better to explicitly check the type.
Also, if this is code inside a function you can use argument typing:
function mycode(array $users)
{
foreach ($users as $user) { }
}
When the function is called with the wrong type it will trigger an error.
Assuming this happens in a function:
function doSomethingWithUsers($users)
{
if(!is_array($users))
{
throw new Exception('$users is expected to be an array');
}
foreach($users as $user){
...
}
}
This way you'll immediately see whenever it's called with the wrong parameters.
In general, it's better not to.
A good general principle in programming is not to hide or ignore errors.
If a variable should be an array, it does you no service to specifically ignore the situation if it's not an array. Instead, it is better for you to be informed of the problem with the built-in error handling. Otherwise, you're not fixing the problem, just hiding its effects. This can make debugging subsequent problems difficult.
However, there's a number of assumptions here:
This is assuming that the variable is supposed to be an array. If you're using foreach () on it, I assume this to be the case. If you're running foreach () on something that might legitimately not be an array it might be an indication your code may need re-working.
Your error reporting and/or logging (reporting on a development server, logging on production) needs to be set up correctly in order to benefit from what PHP errors tell you. Specifically, it's almost never a good idea to ignore PHP warnings - despite being called "warnings" they usually indicate a failure which (in my opinion) should stop execution.
That said, it's not necessarily wrong to use an is_array() in front of a foreach ().
What would you recommend me?
Yes it is good idea and such considerations make you a defensive programmer :)
It's better for me:
foreach (is_array($arr) ? $arr : array() as $key=>$val) {
//..
}
I am new to PHP.
I have been advised to sanitize $_GET and $_POST. I have been following this advice.
However, if I just want to check the variable with
if(isset($_GET['login']))
do I need to do any sanitization on that?
Also, do I need to sanitize $_SESSION values I use?
No, you do not have to do any kind of sanitization or anything : isset() will allow you to check if the variable (or item array, in your case) exists -- and that's pretty much it.
Here, as you are testing whether the item/variable exists or not, you cannot sanitize it : to sanitize the data, you need it to exist.
Note, though : isset() will return false if that item exists, but is null !
Which, in the case of a $_GET item, will quite not probably happen.
No. If you just want to check whether variable exists or not - then your code is just fine.
No, there's no risk in doing that.
Sanitization is required before you proceed to use the values in $_GET/$_POST in your business logic (e.g. building database queries with it or displaying it to the user as part of your HTML output); here you are just testing if a value exists at all.
No, you don't. But better way to do this would be:
if(key_exists('login',$_GET)) {
}
I think there is no need for sanitation, if you need only to check if the key login is setted, it is better to doing so:
if(array_key_exists('login',$_GET))
Because if the key is not setted your code will throw a notice error.
I'm a little confused with the benefit of using filter_has_var($_POST['id']) over isset($_POST['id']).
Can Somebody please tell me if it's simply an alias function?
Not alot ;) According to the manual page for filter_has_var one user finds filter_has_var a little quicker. Also worth noting... filter_has_var isn't working on the live array ($_POST) but on the actual provided input... if you ever add/remove/update what's in that array you won't see those changes with a filter_has_var call (while isset will reflect the current state)
By the way the usage is filter_has_var(INPUT_POST,"id");
Update: Perhaps worth mentioning, filter_has_var was introduced in PHP 5.2.0 (somewhat new) while isset has been around for all of PHP4+5. Most servers keep up to date on this, but isset will always work (no one still runs PHP3 do they?)
First of all, it's not
filter_has_var($_POST['id'])
It's
filter_has_var(INPUT_POST, 'id')
Secondly, it doesn't actually query the $_POST superglobal. It analyzes the request parameter that came in with the request, so it's a better method to use in case $_POST gets dirtied in some way by the PHP script.
I think you mean filter_has_var(INPUT_POST, 'id') over isset($_POST['id']).
There is a small difference in that isset returns false if $_POST['id'] is NULL; you'd have to use key_exists('id', $_POST) to have similar behavior in that regard.
Besides that, the only difference is that filter_has_var doesn't consider modifications to the $_POST array (see this comment).
Function doesn't check live array
<?php
$_GET['a'] = 1;
echo filter_has_var(INPUT_GET, 'a') ? 'Exist' : 'Not exist';
will print Not exist
I am not really clear about declaring functions in php, so I will give this a try.
getselection();
function getselection($selection,$price)
{
global $getprice;
switch($selection)
{
case1: case 1:
echo "You chose lemondew <br />";
$price=$getprice['lemondew'].'<br>';
echo "The price:".$price;
break;
Please let me know if I am doing this wrong, I want to do this the correct way; in addition, php.net has examples but they are kind of complex for a newb, I guess when I become proficient I will start using their documentation, thank you for not flaming.
Please provide links that might also help me clear this up?
Your example seems valid enough to me.
foo('bar');
function foo($myVar)
{
echo $myVar
}
// Output: bar
See this link for more info on user-defined functions.
You got off to a reasonable start. Now all you need to do is remove the redundant case 1:, close your switch statement with a } and then close your function with another }. I assume the global array $getprice is defined in your code but not shown in the question.
it's good practice to declare functions before calling them. It'll prevent infrequent misbehavior from your code.
The sample is basically a valid function definition (meaning it runs, except for what Asaph mentions about closing braces), but doesn't follow best practices.
Naming conventions: When a name consists of two or more words, use camelCase or underscores_to_delineate_words. Which one you use isn't important, so long as you're consistent. See also Alex's question about PHP naming conventions.
Picking a good name: a "get" prefix denotes a "getter" or "accessor"; any method or function of the form "getThing" should return a thing and have no affects visible outside the function or object. The sample function might be better called "printSelection" or "printItem", since it prints the name and price of the item that was selected.
Globals: Generally speaking, globals cause problems. One alternative is to use classes or objects: make the variable a static member of a class or an instance member of an object. Another alternative is to pass the data as an additional parameter to the function, though a function with too many parameters isn't very readable.
Switches are very useful, but not always the best choice. In the sample, $selection could easily hold the name of an item rather than a number. This points to one alternative to using switches: use an index into an array (which, incidentally, is how it's done in Python). If the cases have the same code but vary in values used, arrays are the way to go. If you're using objects, then polymorphism is the way to go--but that's a topic unto itself.
The $price parameter appears to serve no purpose. If you want your function to return the price, use a return statement.
When you called the function, you neglected to pass any arguments. This will result in warnings and notices, but will run.