Filtering inputs - php

Alright, so I have written this function to filter inputs received from a form.
For example the correct input would be foobar, but people can misspell it as `fo'bar'. The ' should not be there.
I have written this simple function which does what is required. (Need to remove the ' from the inputs).
But what would be a more better way to perform this ?
My function :
function normalize_string($string)
{
$newString = "";
for($i=0;$i<strlen($string);$i++)
{
if($string[$i] != "'")
{
$newString = $newString . $string[$i];
}
}
return $newString;
}
Array
if (isset($_POST['submit'])){
$db->insert('customers', array(
'Businessname' => $_POST['BusinessnameTextbox'],
'Salutation' => $_POST['SalutationTextbox'],
'Firstname' => $_POST['FirstnameTextbox'],
'Middle' => $_POST['MiddleTextbox'],
'Lastname' => $_POST['LastnameTextbox'],
'Zipcode' => $_POST['ZipcodeTextbox'],
'Housenumber' => $_POST['HousenumberTextbox'],
'Street' => $_POST['StreetTextbox'],
'Place' => $_POST['PlaceTextbox'],
'Country' => $_POST['CountryTextbox'],
'Phone1' => $_POST['Phone1Textbox'],
'Phone2' => $_POST['Phone2Textbox'],
'Phone3' => $_POST['Phone3Textbox'],
'Phone4' => $_POST['Phone4Textbox']
));
}

You could always use regular expressions, as in
$lastname = preg_replace("/'/", "", $_POST['LastnameTextbox']);
Just curious, how would d'Artagnan register at your site?

Related

Check if array contains array matching a value then store result into new array

I have an odd question which I cannot find an answer to on Google or SO.
I have an array containing all the bits of information about the pages on my website. So the array contains multiple of the arrays like the example below:
'home' =>
array (size=7)
'title' => string '' (length=0)
'url' => string 'home.php' (length=8)
'mobile' => string 'home.php' (length=8)
'keywords' => string '' (length=0)
'description' => string 'test123' (length=126)
'login_needed' => boolean false
'original_page' => string 'home' (length=4)
What I need to do is to find each array that contains a value that comes from a search bar. For example if the user searches for "bruidsmode" every array that contains "bruidsmode" should be put into another array which I can then output into elements to display on the website.
Below you will find a stripped example of what I have on my page. (I tried making a working example but was unable to do so):
<?php
$config['menu']["home"] = array (
'title' => '',
'url' => 'home.php',
'mobile' => 'home.php',
'keywords' => '',
'description' => '',
'login_needed' => FALSE
);
$config['menu']["bruidsmode"] = array (
'title' => '',
'url' => 'bruidsmode.php',
// 'mobile' => 'bruidsmode.php',
// 'mobile' => 'bruidsmode.php',
'keywords' => '',
'description' => '',
'login_needed' => TRUE,
'robot' => FALSE
);
if(isset($_POST['generalsearch']) && isset($_POST['generalsearchresult'])){
// Put search value into variable
$searchvalue = $_POST['generalsearchresult'];
// Fill variable with all page items
$array = $config['menu'];
// Set search cretaria to search in array
$key = $searchvalue;
// Search for key value inside array
$result = #$array[$key] ?: null;
if($result == null){
echo "Geen resultaten gevonden...";
}else{
var_dump($result);
}
}
?>
<form method="POST">
<input type="text" name="generalsearchresult">
<input type="submit" name="generalsearch">
</form>
The above code works but only outputs arrays which exactly match the search criteria. So for example the searchterm "bruidsmode" with the above code outputs only the page "bruidsmode" but not the page "bruidsmode-overzicht" for example.
I hope the above is understandable, if not please tell me how to improve it.
Kind regards,
Robbert
Your code isn't really what I would call a search. In order to search you should loop over the array to find potential matches, rather than return the requested property.
function searchMenu($menu, $term) {
$matches = [];
foreach($menu as $key => $value) {
if (stripos($key, $term) !== false) {
$matches[] = $value;
}
}
return $matches;
}
if(isset($_POST['generalsearch']) && isset($_POST['generalsearchresult'])){
$result = searchMenu($config['menu'], $_POST['generalsearchresult']);
if(!count($result)){
echo "Geen resultaten gevonden...";
}else{
var_dump($result);
}
}
If you want to return multiple results, you will need to store them in an array and return that.
If you are going to do that, you can extend the search to check against child fields as well, not just the top level keys:
$page_data =[
'my-cat' => [
'title' => '',
'url' => 'my-cat.php',
'mobile' => 'my-cat.php',
'keywords' => 'cat,kitten',
'description' => 'i love my cat',
'login_needed' => false,
'original_page' => 'mycat',
],
'home' => [
'title' => '',
'url' => 'home.php',
'mobile' => 'home.php',
'keywords' => 'cat,dog,other',
'description' => 'a site about cats',
'login_needed' => false,
'original_page' => 'home',
],
'about' => [
'title' => '',
'url' => 'about.php',
'mobile' => 'about.php',
'keywords' => 'about',
'description' => 'about me',
'login_needed' => false,
'original_page' => 'about',
],
];
function search(array $page_data_to_search, string $search_term, array $fields_to_search): array{
$out=[];
$search_fields = array_flip($fields_to_search); //O(1)
foreach($page_data_to_search as $key => $page_data){
//first test the key
if(isset($search_fields['key']) && strpos($key, $search_term) !==false){
$out[$key]=$page_data;
continue; //no need to check other fields
}
//then the user supplied fields
foreach($search_fields as $field => $unused){
if(isset($page_data[$field]) && strpos($page_data[$field], $search_term) !==false){
$out[$key]=$page_data;
break;
}
}
}
return $out;
}
echo '<pre>';
var_dump(search($page_data, 'cat', ['key', 'keywords', 'description']));

exclude some values in json_encode() with JSON_NUMERIC_CHECK

I use CakePHP framework. I have an array which corresponds a model's records. I have to handle it in the way, that all the integers and floats are output as integers and floats just like in java without quotes(111 or 11.1 instead of this '111.1' or '11.1'). I found the way to return all the values in this way: return json_encode($data, JSON_NUMERIC_CHECK);. The question is: is there any way to exclude some numeric fields to be outpt in this way? In other words: I have two numeric fields: field1 and field2, and they have to be with quotes. Meantime all other numeric fields must be without quotes. How could I implement this ?
My array looks so:
array(
(int) 0 => array(
'password' => '*****',
'id' => '2',
'number' => '2',
'debtor_number' => null,
'name' => 'Ziegler',
'firstname' => 'Lisa',
'address' => 'Frau',
'title' => '',
'name_extension' => '',
'company' => '',
'company_function' => '',
'street' => 'Feldbergstr. 13-15',
'street2' => null,
'postbox' => '',
'street_or_postbox' => '1',
'zip' => '60318',
'city' => 'Frankfurt am Main',
),
(int) 1 => array(
'password' => '*****',
'id' => '3',
'number' => '3',
'debtor_number' => null,
'name' => 'Trappatoni',
'firstname' => 'Günther',
'address' => 'Herr',
'title' => '',
'name_extension' => '',
'company' => '',
'company_function' => '',
'street' => 'Trilluper Weg 17',
'street2' => null,
'postbox' => '',
'street_or_postbox' => '1',
'zip' => '60594',
'city' => 'Frankfurt am Main',
First of all, a little example of how JSON_NUMERIC_CHECK works:
$data = [112, '34', 5.6, '7.8'];
echo json_encode($data) . PHP_EOL;
echo json_encode($data, JSON_NUMERIC_CHECK) . PHP_EOL;
... prints:
[112,"34",5.6,"7.8"]
[112,34,5.6,7.8]
There isn't any feature to determine which values should be parsed (and if they wanted to add it, what would its syntax be?). The only way to get the results you want is to ensure that source data is already using the appropriate PHP data types. And that's something you can certainly do (though the exact details depend on your specs):
$person = [
'age' => 33,
'zip_code' => '09007',
];
$person['age'] = is_null($person['age']) ? null : (int)$person['age'];
echo json_encode($person);
... prints:
{"age":33,"zip_code":"09007"}
Another solution for this issue if it's important enough for you to solve it in a robust way, and that would be to use the JMS Serializer library.
You would need to define a class for your data, but after that, whatever types you have defined via annotation will be honored during serialization.
With that said, Alvaro's post shows that casting will work. So, something like this should also work:
// Fix all Numerics
$data = json_decode(json_encode($data, JSON_NUMERIC_CHECK), true);
// Fix your 2 strings
$callback = function($row) {
if (array_key_exists('field1', $row)) {
$row['field1'] = (string)$row['field1'];
}
if (array_key_exists('field2', $row)) {
$row['field2'] = (string)$row['field2'];
}
return $row;
}
$data = array_map($callback, $data);
// This should be ready for final encode
return json_encode($data);
I tried this and it worked fine for me because I would only check JSON_NUMERIC_CHECK on id and with this
echo json_encode($article, JSON_NUMERIC_CHECK)
,and I got id and telephone as int.
Try this
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$row['id'] = (int)$row['id'];
$row['telephone'] = (string)$row['telephone'];
$db_data[] = $row;
}
//format json
$article->status = true;
$article->message = "success";
$article->employee = $db_data;
//return json
echo json_encode($article);
} else {
}

Compile Error Can't use method return value in write context in code igniter

i got this model which inserts data on the database but the problem is, other fields are not required so i did this,
public function insert(){
if($this->input->post('MNAME') = NULL){
$mname = "n/a";
}else{
$mname = $this->input->post('MNAME');
}
if($this->input->post('EXTENSION') = NULL){
$ext = "n/a";
}else{
$ext = $this->input->post('EXTENSION');
}
if($this->input->post('EMAIL') = NULL){
$email = "n/a";
}else{
$email = $this->input->post('EMAIL');
}
if($this->input->post('CELLNO') = NULL){
$cell = "n/a";
}else{
$cell = $this->input->post('CELLNO');
}
if($this->input->post('AGENCY_NO') = NULL){
$agency = "n/a";
}else{
$agency = $this->input->post('AGENCY_NO');
}
$input = array(
'ID_NUM' => $this->uri->segment(3),
'FNAME' => $this->input->post('FNAME' ),
'SURNAME' => $this->input->post('SURNAME' ),
'DO_BIRTH' => $this->input->post('DO_BIRTH' ),
'POBIRTH' => $this->input->post('POBIRTH' ),
'SEX' => $this->input->post('SEX' ),
'CIVILSTAT' => $this->input->post('CIVILSTAT' ),
'ID_NAT' => $this->input->post('ID_NAT' ),
'HEIGHT' => $this->input->post('HEIGHT' ),
'WEIGHT' => $this->input->post('WEIGHT' ),
'BLOOD_TYPE' => $this->input->post('BLOOD_TYPE' ),
'RES_ADD' => $this->input->post('RES_ADD' ),
'RES_ZIP' => $this->input->post('RES_ZIP' ),
'PERM_ADD' => $this->input->post('PERM_ADD' ),
'PERM_ZIP' => $this->input->post('PERM_ZIP' ),
'MNAME' => $mname,
'EXTENSION' => $ext,
'EMAIL' => $email,
'CELLNO' => $cell,
'AGENCY_NO' => $agency,
'DATE_CREATED' => date("Y-m-d")
);
$insert = $this->db->insert($this->table,$input);
return $insert;
}
but the problem is that i get this error Can't use method return value in write context says that its on line 108. which, the line 108 is the first if of my model. what is my error? and is there any codes which will be shorter?
You're only stating 1 = in your IF statements, for future note: It should be 2 ='s in a match.
I restructured this for you so your code is more readable and short.
// Checking if they're null and appending n/a if they're
$example = array('MNAME','EXTENSION','EMAIL', 'CELLNO', 'AGENCY_NO');
$new = array();
foreach ($example as $_ex)
{
$check = $this->input->post($_ex);
if ($check == null)? array_push($new, 'n/a') : array_push($new, $check);
}
Then replace with this (keeping in mind index's start at 0 in an array):
// Inside your DB insert query
'MNAME' => $new[0],
'EXTENSION' => $new[1],
'EMAIL' => $new[2],
'CELLNO' => $new[3],
'AGENCY_NO' => $new[4],
I hope this helped.

Generate shorted unique username based on array of first names and last names

I have a multi-dimensional array called users that is formatted like the following and I am trying to create a script that will create a "username" based on this information:
$users = [
['first_name' => 'Bob', 'last_name' => 'Smith'],
['first_name' => 'Steve', 'last_name' => 'Little'],
['first_name' => 'Eric', 'last_name' => 'Fielder'],
['first_name' => 'Steve', 'last_name' => 'Richardson'],
['first_name' => 'Bob', 'last_name' => 'Sanders'],
['first_name' => 'Bob', 'last_name' => 'Sanders'],
['first_name' => 'Bob', 'last_name' => 'Smith'],
];
Required Logic:
If there are no duplicate first names it uses only the first name as the username
("Eric").
If there are two names with the same first but different initial letters in the last name it will use the first name as last initial ("Steve L." and "Steve R.").
If multiple people have the last first name and last initial then it return the full name ("Bob Smith" and "Bob Sanders").
Lastly, if the SAME exact name is found then it will append a number to each like this: "Bob Sanders (1)" and "Bob Sanders (2)"
I am hoping this can be done efficiently and not with a lot of loops, but I can not figure it out for the life of me.
This script is not that nifty but pretty much does what you want. Note that it only uses two loops but needs some additional memory to store meta data about the users:
<?php
$users = array(
array("first_name"=>"Bob", "last_name"=>"Smith"),
array("first_name"=>"Steve", "last_name"=>"Little"),
array("first_name"=>"Eric", "last_name"=>"Fielder"),
array("first_name"=>"Steve", "last_name"=>"Richardson"),
array("first_name"=>"Bob", "last_name"=>"Sanders"),
array("first_name"=>"Bob", "last_name"=>"Sanders")
);
$_users_info = array("first_name_count"=>array(),"last_name_count"=>array(),"first_name_last_initial_count"=>array());
foreach($users as $user){
$_users_info["first_name_count"][$user["first_name"]] = isset($_users_info["first_name_count"][$user["first_name"]]) ? ++$_users_info["first_name_count"][$user["first_name"]] : 1;
$_users_info["last_name_count"][$user["last_name"]] = isset($_users_info["last_name_count"][$user["last_name"]]) ? ++$_users_info["last_name_count"][$user["last_name"]] : 1;
$_users_info["first_name_last_initial_count"][$user["first_name"]."#".substr($user["last_name"],0,1)] = isset($_users_info["first_name_last_initial_count"][$user["first_name"]."#".substr($user["last_name"],0,1)]) ? ++$_users_info["first_name_last_initial_count"][$user["first_name"]."#".substr($user["last_name"],0,1)] : 1;
$_users_info["complete_name_count"][$user["first_name"]."#".$user["last_name"]] = isset($_users_info["complete_name_count"][$user["first_name"]."#".$user["last_name"]]) ? ++$_users_info["complete_name_count"][$user["first_name"]."#".$user["last_name"]] : 1;
$_users_info["complete_name_allocated"][$user["first_name"]."#".$user["last_name"]] = 0;
}
print('<pre>');
foreach($users as $user) {
$username = null;
if($_users_info["first_name_count"][$user["first_name"]]==1) $username = $user["first_name"];
else if($_users_info["first_name_last_initial_count"][$user["first_name"]."#".substr($user["last_name"],0,1)]==1) $username = $user["first_name"]." ".substr($user["last_name"],0,1).".";
else if($_users_info["last_name_count"][$user["last_name"]]==1) $username = $user["first_name"]." ".$user["last_name"];
else $username = $user["first_name"]." ".$user["last_name"].sprintf(" (%d)",++$_users_info["complete_name_allocated"][$user["first_name"]."#".$user["last_name"]]);
printf("%s %s => %s\n",$user["first_name"],$user["last_name"],$username);
}
print('</pre>');
?>
I find Nayru's snippet to be excessively wide, hard to follow, and too expensive in terms of memory -- it is storing redundant tallies for the sake of easy lookups. To its credit, it does maintain the order of the rows -- if that matters.
Another technique, is to consolidate the input data into nested groups (with unique levels/keys), then iterate those consolidated levels and use a battery of conditions to generate the desired usernames. This might be the most compact way to track the name collisions. I certainly feel that this is much easier piece of code to maintain and read.
*if your last names might start with a multibyte character, then mb_substr() shoul be used to isolate the first letter
*the result of this snippet does not respect the original order of the input, but it could be refactored for this purpose if necessary.
*it does use several loops, but this is just the most efficient means to iterating the nested levels -- not to be shied away from.
Code: (Demo)
foreach ($users as $row) {
$grouped[$row['first_name']][$row['last_name'][0] ?? ''][$row['last_name']][] = $row;
}
$result = [];
foreach ($grouped as $firstName => $leadingLetterGroup) {
$leadingLetterCount = count($leadingLetterGroup);
foreach ($leadingLetterGroup as $leadingLetter => $lastNameGroup) {
$lastNameCount = count($lastNameGroup);
foreach ($lastNameGroup as $lastName => $rows) {
if (count($rows) === 1) {
if ($leadingLetterCount === 1) {
$username = $firstName;
} elseif ($lastNameCount === 1) {
$username = "$firstName $leadingLetter.";
} else {
$username = "$firstName $lastName";
}
$result[] = $rows[0] + ['username' => $username];
} else {
foreach ($rows as $i => $row) {
$username = sprintf("%s %s (%d)", $firstName, $lastName, $i + 1);
$result[] = $row + ['username' => $username];
}
}
}
}
}
var_export($result);
Output:
array (
0 =>
array (
'first_name' => 'Bob',
'last_name' => 'Smith',
'username' => 'Bob Smith (1)',
),
1 =>
array (
'first_name' => 'Bob',
'last_name' => 'Smith',
'username' => 'Bob Smith (2)',
),
2 =>
array (
'first_name' => 'Bob',
'last_name' => 'Sanders',
'username' => 'Bob Sanders (1)',
),
3 =>
array (
'first_name' => 'Bob',
'last_name' => 'Sanders',
'username' => 'Bob Sanders (2)',
),
4 =>
array (
'first_name' => 'Steve',
'last_name' => 'Little',
'username' => 'Steve L.',
),
5 =>
array (
'first_name' => 'Steve',
'last_name' => 'Richardson',
'username' => 'Steve R.',
),
6 =>
array (
'first_name' => 'Eric',
'last_name' => 'Fielder',
'username' => 'Eric',
),
)

PHP Validation Using An Regex Array

I am working on creating an array of regular expressions based on form values and using a function that fails on the wrong user input. Every time I run the website I receive the following error:
Warning: eregi() [function.eregi]: REG_EMPTY
I do not know what is wrong. Please take a look at my code and help. Thank you!
$error_log = array();
// Checks if user inputed data matches the default values
$arr = array(
'name' => 'First Name Last Name',
'month' => 'MM',
'day' => 'DD',
'year' => 'YYYY',
'address1' =>'Address Line 1',
'address2' => 'Address Line 2',
'email' => 'John#myemail.com'
);
$regex = array(
'name' => "^[a-z .'-]+$",
'month' => "^((0[1-9])|(1[0-2]))$ ",
'day' => "0?[1-9]|[1-2][0-9]|3[0-1]",
'year' => "^(19|20)\d{2}$",
'address1' => "/^[a-zA-Z0-9 ]*$/",
'address2' => "/^[a-zA-Z0-9 ]*$/",
'email' => "^[A-Z0-9._%-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$"
);
/*
Runs validation on the form values and stops procesing if the form does not have the correct values
*/
function regexValidate( $form_value, $regex, $key){
if(!eregi($regex[$key],$form_value) ){
return true;
}
return false;
}
I have a slightly different approach. I have an array such as this - which I ultimatley pass to Smarty to build my for - but upon submission, this array is passed witht he form $_POST into a function that loops round and does the necessary validation (based on the 2nd parameter here);
$arrFields = array(
'stage1' => array(
'accountname' => array('Account Name','text','text','stage1',true),
'presharedaccountkey' => array('Pre-shared Key','text','text','stage1',true),
'ipwhitelist' => array('IP White-list','text','text','stage1',false),
'accountid' => array('Customer ID','text','readonly','stage1',false),
'product' => array('Product','text','select','stage1',false,$platformProducts),
'dtcreated' => array('Created on','text','text','stage1',false),
'createdby' => array('Created By','text','text','stage1',false),
'mode' => array('Mode','text','radio','stage1',true,$platformModes)
)
);
i do some custom stuff but basically to loop it'd be:
function validateFormPost($arrFields,$postfields)
{
$err = array();
//validate required fields
foreach($arrFields as $stagekey => $stageval)
{
foreach($stageval as $key => $val)
{
// your validation based on field type
// i.e. in here would be regex to deal with std type or indeed you could add it as a parameter to the $arrFields construct.
// allow comma or spaced emails but replace with semi colon
if($val[1]=='email')
{
$postfields[$key] = str_replace(",",";",trim($postfields[$key]));
$postfields[$key] = str_replace(" ",";",trim($postfields[$key]));
}
// basic check required fileds are completed
if($val[4]==true && !array_key_exists($key,$postfields))
{
$err[$stagekey][$key] = array($val[0],'This is a required field');
}
elseif(array_key_exists($key,$postfields) && $this->validateField($postfields[$key],$val[1],$val[4])==false)
{
$err[$stagekey][$key] = array($val[0],'Invalid '.$val[1].' value.');
//check values for basic field length
}
elseif(strlen($postfields[$key])>$feildcolset[$key][0] && $feildcolset[$key][0]!=null)
{
$err[$stagekey][$key] = array($val[0],'Field max '.$feildcolset[$key][0].' characters.');
}
}
}
}
HTH - i can expand on it if needed :)

Categories