Using PHP..
Here is what I have.. I'm gonna explain the whole thing and maybe someone can help me with the logic and maybe point me in the right direction.
I have a mail system I am working on. In the cc part, I am allowing the user to seperate the values by a semicolon, like so: 1;2;3;4...
When these values are passed to my function, I am using explode to get them into an array. What I want to do is some checking first. I want to firstly make certain that the format is correct and that every value is correctly seperated. If not, I should show an error. Once this is done, I want to make certain that every number is actually valid. I can query the database, put the reslts into an array and was thinking to use the in_array() function to verify this but I'm not certain that it will work. Can someone please help me out with the best way to handle this?
Thanks.
EDIT:
What is the best way to detect a bogus value in the CSV list of values?
In order to verify that each number was correct seperated, you want to check that there is no whitespace in the answer. So something like this should work:
$text = trim($id);
if(strpos(" ", $id) !== false)
{
//error
}
Next, to check for the values, it is very simple
if(!in_array($id, $database_ids))
{
// error
}
Finally, if you are only using numeric values, check that the id is numeric
if(!is_numeric($id))
{
//error
}
To combine, wrap it into an array
foreach($exploded_array as $key => $id)
{
$id = trim(id);
if(!is_numeric($id))
{
//error
}
if(strpos(" ", $id) !== false)
{
//error
}
if(!in_array($id, $database_ids))
{
// error
}
}
I hope the code was pretty self explanatory where it got the variables, but if you need me to explain more, feel free to ask.
You are looking for something like:
foreach ($array as $value) {
//do checking here
}
array_filter could be an option.
As whichdan suggested, here is an implementation that relies on array_filter():
<?php
function checkValue($value)
{
$id = trim(id);
if(!is_numeric($id))
{
return false;
}
if(strpos(" ", $id) !== false)
{
return false;
}
if(!in_array($id, $database_ids))
{
return false;
}
return true;
}
$values = '1;2;3;4';
$values_extracted = explode(';', $values);
if(count($values) == count(array_filter($values_extracted), 'checkValue'))
{
// Input was successfully validated
}
?>
Related
i'm sorry if my english not good.
I have a problem in my code. how I can stop access when in my array have duplicate. I mean, when one or more data in array have duplicate, user must repeat input from first page. and when array have not duplicate, user can access next page.
this is my code I have try.
$no_id=array('100100','100200','100300','100200','100200','100100');
$array = array();
foreach ($no_id as $key => $value)
{
if(isset($array[$value]))
{
$array[$value] += 1;
} else
{
$array[$value] = 1;
}
}
foreach ($array as $alert => $n)
{
if($n >= 2)
{
header('location:../../home');
} else
{
header('location:../../questionnair');
}
}
but when found the duplicate data (in array 100100 have two data and 100200 three data), the system still bring user to access questionnair page, not home.
thanks for helping.
I think the main problem is that you should always use exit() after using header() with location, otherwise the page will continue to execute.
This would still cause a problem though if the first value was a unique value as the first loop would always exit;.
You could fix this (only ever call header() if the value is > 2, then the default of all are unique is after the loop), but an alternative is to use array_count_values() which counts how many each value exists in the list and then use max() to find the most occurring one, then test against that...
$no_id=array('100100','100200','100300','100200','100200','100100');
$n = max(array_count_values($no_id));
if($n >= 2)
{
header('location:../../home');
exit;
} else
{
header('location:../../questionnair');
exit;
}
Update:
An alternative and slightly quicker version would be to use your original first loop, but as soon as it detects the value is already set, then it can stop working and just return then...
$no_id=array('100100','100200','100300','100200','100200','100100');
$array = array();
foreach ($no_id as $key => $value)
{
if(isset($array[$value]))
{
header('location:../../home');
exit;
} else
{
$array[$value] = 1;
}
}
header('location:../../questionnair');
exit;
If you just need to check if the array does have dupliate, you can use array_unique and compare the new array with the old array. If the arrays are not the same, it means there are duplicates.
With code:
$no_id = array('100100','100200','100300','100200','100200','100100');
$new_array = array_unique($no_id);
if (count($no_id) == count($new_array)) {
// 2 arrays have same number of items => they are equal => no duplicates
$redirect = "questionnair.php";
} else {
// 2 arrays have different number of items => they are not equal => duplicates
$redirect = "home.php";
}
header("location: {$redirect}");
NOTE
You have to redirect to an another PHP page (ex. home.php and not just home).
First of all, it's simplier to use array_unique function, which will remove all duplicated values.
After that you can make checks, if nothing was changed, then there is no duplicated items.
Like this:
$no_id=array('100100','100200','100300','100200','100200','100100');
$no_id_unique = array_unique($no_id);
if(count($no_id)===count($no_id_unique)){
header('location:../../questionnair');
}else{
header('location:../../home');
}
exit();
Next thing that you using ../ in path which means go to parent directory.
I don't know your environment, but must likely it's a bad idea.
According to documentation it's better to specify full url of page where user must be forwarded:
header("Location: http://www.example.com/home/");
Also, please be aware, that you need to prevent all others output from a script, especcially before the header() call. Read more here.
you can use foreach (array_unique($no_id) as $key => $value)
You can use array_count_values for this, not tested, but could be like:
$counts = array_count_values($no_id);
$duplicate = false;
foreach ($no_id as $value) {
if ($counts[$value] > 1) {
$duplicate = true;
break; // found a duplicate, no need to check further.
}
}
if ($duplicate === true) {
header('location:../../home');
} else {
header('location:../../questionnair');
}
Using array_flip()
$no_id = array('100100','100200','100300','100200','100200','100100');
$no_id_unique = array_flip($no_id);
if(count($no_id) === count($no_id_unique)){
header('location:../../questionnair');
}else{
header('location:../../home');
}
exit();
I have a list of 230 names in a database and I'd like to monitor a Twitter feed for mentions of occurrences of those names, particularly when multiple names are used in the one tweet.
I'm not quite sure how to do this.
My initial thought is:
Store names in an array and run every tweet through a function like this:
function contains($str, array $arr)
{
foreach($arr as $a) {
if (stripos($str,$a) !== false) return true;
}
return false;
}
Is there an easier way to do this?
Seems like a fine approach, though I would consider a variation which returns a little more information through the interface than a boolean, since you said you are interested in multiple mentions. It will execute longer when there is a mention but seems worth it:
function referenceCount($str, array $arr)
{
$count = 0;
foreach($arr as $a) {
if (stripos($str,$a) !== false) $count++;
}
return $count;
}
When dealing with arrays I am forced to add a bunch of repetitive code to handle arrays with one child versus multiple:
//If more than one step, process each step, elcse processs single
if(!array_key_exists('command',$pullcase['steps']['step'])) {
foreach($pullcase['steps']['step'] as $step) {
$command=$step['command'];
$parameter=$step['parameter'];
if(isset($step['value'])){
$value = $step['value'];
$this->runCommands($command,$parameter,$value);
} else {
$this->runCommands($command,$parameter);
}
}
} else {
$command = $pullcase['steps']['step']['command'];
$parameter = $pullcase['steps']['step']['parameter'];
if(isset($pullcase['steps']['step']['value'])){
$value = $pullcase['steps']['step']['value'];
$this->runCommands($command,$parameter,$value);
}
else { $this->runCommands($command,$parameter); }
}
As you can see, I'm having to duplicate my efforts depending on if there is a single item in an array versus multiple:
$pullcase['steps']['step'][0]['command']
vs
$pullcase['steps']['step']['command']
How can I simplify this code so that I can use a single variable for all instances?
If you control the creation of the array, make step an array of one even if there is only one so you always have an array. Is that possible?
You either have a step array [step][0][command] or you have a single step [step][command]. So when you create the array instead of [step][command] make it [step][0][command] etc. Standard way of doing it, problem solved as you only need the foreach.
If you can't do it at array creation then consider doing it before the loop:
if(is_array($pullcase['steps']['step'])) {
$steps = $pullcase['steps']['step'];
} else {
$steps[] = $pullcase['steps']['step'];
}
foreach($steps as $step) {
$value = isset($step['value']) ? $step['value'] : null;
$this->runCommands($step['command'], $step['parameter'], $value);
}
Also, if runCommands() can detect a empty argument, then an alternative to the if/else for the function call is used above.
The following may help. It doesn't do much but call the function "runcommands" on a value if the key is 'command'. I am using it to show how you can use array_walk_recursive to possibly solve your problem.
First, you need the function to use:
function runcommandswhencommand($value, $key)
{
if($key == 'command') runcommands($value);
}
Now, you can use the recursive walk on your array:
array_walk_recursive($pullcase, 'runcommandswhencommand');
With this, whenever the key is 'command', the value of that index will be used in the parameter of the function runcommands().
I have an interesting situation. I am using a form that is included on multiple pages (for simplicity and to reduce duplication) and this form in some areas is populated with values from a DB. However, not all of these values will always be present. For instance, I could be doing something to the effect of:
<?php echo set_value('first_name', $first_name); ?>
and this would work fine where the values exist, but $user is not always set, since they may be typing their name in for the first time. Yes you can do isset($first_name) && $first_name inside an if statement (shorthand or regular)
I am trying to write a helper function to check if a variable isset and if it's not null. I would ideally like to do something like varIsset('first_name'), where first_name is an actual variable name $first_name and the function would take in the string, turn it into the intended variable $first_name and check if it's set and not null. If it passes the requirements, then return that variables value (in this case 'test'). If it doesn't pass the requirements, meaining it's not set or is null, then the function would return '{blank}'.
I am using CodeIgniter if that helps, will be switching to Laravel in the somewhat near future. Any help is appreciated. Here is what I've put together so far, but to no avail.
function varIsset($var = '')
{
foreach (get_defined_vars() as $val) {
if ($val == $var) {
if (isset($val) && $val) {
echo $val;
}
break;
}
}
die;
}
Here is an example usage:
<?php
if (varIsset('user_id') == 100) {
// do something
}
?>
I would use arrays and check for array keys myself (or initialize all my variables...), but for your function you could use something like:
function varIsset($var)
{
global $$var;
return isset($$var) && !empty($$var);
}
Check out the manual on variable variables. You need to use global $$var; to get around the scope problem, so it's a bit of a nasty solution. See a working example here.
Edit: If you need the value returned, you could do something like:
function valueVar($var)
{
global $$var;
return (isset($$var) && !empty($$var)) ? $$var : NULL;
}
But to be honest, using variables like that when they might or might not exist seems a bit wrong to me.
It would be a better approach to introduce a context in which you want to search, e.g.:
function varIsset($name, array $context)
{
return !empty($context[$name]);
}
The context is then populated with your database results before rendering takes place. Btw, empty() has a small caveat with the string value "0"; in those cases it might be a better approach to use this logic:
return isset($context[$name]) && strlen($name);
Try:
<?php
function varIsset($string){
global $$string;
return empty($$string) ? 0 : 1;
}
$what = 'good';
echo 'what:'.varIsset('what').'; now:'.varIsset('now');
?>
So, i have this code that seems to be doing the mechanical work correctly, avoiding to write on tables if one or more fields from a form are left empty, but the echos and messages aren't working as they supposed to:
SOLUTION TO THE PROBLEM:
I don't believe this will be useful to anyone, but just for the record, the solution is simple:
$campos = array('nome','morada','email','telemovel','codigopostal','vat');
foreach ($campos as $key => $campo) {
$campos[$key] = $_GET[$campo];
if(!isset($_GET[$campo])|| empty($_GET[$campo])){
header("Location: ../index.php?erro=".$campo);
$verifica=FALSE;
die();
}else{
$verifica=TRUE;
}
}
This will give me some problems, not what i really wanted but solves the logical problems i was having. Thanks to you all guys.
$campos = array('nome','morada','email','telemovel','codigopostal','vat');
foreach ($campos as $key => $campo) {
$campos[$key] = ($_GET[$campo]);
while(list($key, $campo)= each($campos))
if(!isset($_GET[$campo])|| $_GET[$campo]==""){
echo("não preencheu um dos campos");
$verifica = FALSE;
die();
}else{
echo $_GET[$campo]." \r\n";}
$verifica = TRUE;
}
if($verifica==TRUE){
some irrelevant code.
}
As i said, the code itself is working flawlessly, BUT if i only left 2 empty fields on the form, the echo $_GET[$campo] will be working even though the variable $verifica will be set as FALSE
AN HINT:
One of the fields is making the code to fail, is the second one, so, if i do this:
../phcexport.php?nome=myname&morada=&codigopostal=postcode&email=#.com&vat=123123&telemovel=00800
And ignore the second value from the array, the code will work like a charm, i can try as many combinations as i can as long as i left the second field empty, it will work properly, giving me the error "some field is empty", in this case i know it is, the "morada" is empty, and if i fill it in the code says "its ok, all filled in" BUT the "morada" should be the last to be filled so the code works. Funny... (I'm sorry about all the text to describe the problem, i'm Portuguese)
EDIT2: For the rest of the code i need to use $campos[$key], so attribute a key to the arrays is essencial.
The problem is that you reset $verifica in the else. So regardless if you set it once to FALSE, the last foreach iteration will determine the outcome. But you can "simplify" the whole approach to:
$verify = array_search(0, array_map("strlen", $campos)) === false;
This simply checks for the string length of each array entry. If none of them is 0, then the expression will return true for $verify;
instead of doing $_GET[$campo]=="", you can maybe use the empty function :
empty($_GET[$campo])
This should address all problems related to different data types.
Your also maybe running in a problem because you're using a variable named $campo in two different loops, try changing the variable name in the while loop to see if it works better.
Check the exact value of $campo that is causing the incorrect behaviour, then consult this table to make sure you are using the right kind of comparison
http://www.php.net/manual/en/types.comparisons.php#types.comparisions-loose
try following solution, empty fields can not pass the test
<?php
$campos = array('nome', 'morada', 'email', 'telemovel', 'codigopostal', 'vat');
$verifica = TRUE;
foreach ($campos as $campo) {
if (!isset($_GET[$campo]) || empty($_GET[$campo])) {
echo "não preencheu um dos campos" ;
$verifica = FALSE;
break;
} else {
echo $_GET[$campo] ."\r\n";
}
}
if ($verifica == TRUE) {
// some irrelevant code.
} else {
die();
}