Cant seem to append to array in php - php

This simple script should theoretically check the form for errors and then print any errors it finds.
The formValidate function takes in a form array, each field in the form has a value which is validated. The field also has an errors key whose value is an empty array. I am trying to append any errors I find to the errors array of the particular field. I then return the form array when I am done.
I later print out all the errors for the fields. Unfortunately the errors never show up.
I have been breaking my head over this for many hours now and I cant for the life of me figure out why the form errors in my script are not appeding.
Any help would be greatly appreciated!
# get value from array
function array_get(array $array, $key, $default = null)
{
return (array_key_exists($key, $array)) ? $array[$key] : $default;
}
# get string value from array
function array_get_string(array $array, $key, $default = '', $trim = true)
{
$val = array_get($array, $key);
if (is_string($val)) {
return ($trim) ? trim($val) : $val;
}
return $default;
}
function validateForm($form)
{
// validateField each field
foreach ($form as $field)
{
foreach ($field['validation'] as $validate)
{
switch($validate)
{
case 'email':
if(!filter_var($field['value'], FILTER_VALIDATE_EMAIL)) {
$field['errors'][] = $field['value'] . ' is an invalid email address.';
}
break;
case 'number':
if(!preg_match('/^[0-9 ]+$/', $field['value'])) {
$field['errors'][] = $field['value'] . ' is an invalid number.';
}
break;
case 'alpha':
if(!preg_match('/^[a-zA-Z ]+$/', $field['value'])) {
$field['errors'][] = $field['value'] . ' contains invalid characters. This field only accepts letters and spaces.';
}
break;
}
}
}
return $form;
}
// $post = filter_input_array( INPUT_POST, FILTER_SANITIZE_SPECIAL_CHARS );
$post = $_POST;
$ajax = array_get_string($post, "request_method") == 'ajax';
# select data that needs validation
$form = array(
'fullname' => array(
'value' => array_get_string($post, "full-name"),
'validation' => array('alpha', 'required'),
'errors' => array(),
),
'emailaddress' => array(
'value' => array_get_string($post, "email-address"),
'validation' => array('email'),
'errors' => array(),
),
'activites' => array(
'value' => array_get_string($post, "activites"),
'validation' => array('default'),
'errors' => array(),
),
'country' => array(
'value' => array_get_string($post, "country"),
'validation' => array('default'),
'errors' => array(),
),
'contactpreference' => array(
'value' => array_get_string($post, "contact-preference"),
'validation' => array('default'),
'errors' => array(),
),
'message' => array(
'value' => array_get_string($post, "message"),
'validation' => array('alpha'),
'errors' => array(),
),
);
// validate the form
$form = validateForm($form);
foreach ($form as $field)
{
foreach ($field['errors'] as $error)
{
echo $error . '<br />';
}
}

foreach creates a copy of the array and works on it. If you need to make changes to the original array, pass it by reference like so:
foreach($form as &$field) {
...
}

Related

check in_array for nested array

I have an array in this format, and I want to check if a var is in the array from any of the keys link
$nav = array(
'Account Settings' => array(
'icon' => 'fa-cog',
'Account Settings' => array(
'link' => '/voip/settings?seq='.$seq,
'icon' => 'fa-cog',
),
'Provisioning' => array(
'link' => '/voip/provisioning?seq='.$seq,
'icon' => 'fa-wrench',
),
'E999 Data' => array(
'link' => '/voip/e999?seq='.$seq,
'icon' => 'fa-life-ring',
),
'Delete Account' => array(
'link' => '/voip/delete?seq='.$seq,
'icon' => 'fa-trash',
),
),
'Mailboxes' => array(
'link' => '/voip/mailboxes?seq='.$seq,
'icon' => 'fa-envelope',
),
'Telephone Numbers' => array(
'link' => '/voip/numbers?seq='.$seq,
'icon' => 'fa-hashtag',
),
);
I tried if(in_array($_GET["nav"], $nav) but it doesn't pick up the nested values
Is there a way to do this?
There's no readymade function to do that. Let's say you have:
$key = 'link';
$value = '/voip/e999?seq=' . $seq;
// and $nav your multidimensionnal array
You can write your own recursive function:
function contains_key_value_multi($arr, $key, $value) {
foreach ($arr as $k => $v) {
if ( is_array($v) && contains_key_value_multi($v, $key, $value) ||
$k === $key && $v === $value )
return true;
}
return false;
}
var_dump(contains_key_value_multi($nav, $key, $value));
You can use the spl classes to be able to loop over leafs of your multidimensionnal array. This time you don't need a recursive function:
$ri = new RecursiveIteratorIterator(new RecursiveArrayIterator($nav));
function contains_key_value($arr, $key, $value) {
foreach ($arr as $k => $v) {
if ( $k === $key && $v === $value )
return true;
}
return false;
}
var_dump(contains_key_value($ri, $key, $value));
Since you say the value is in link key then you can use array_column to isolate the link items.
if(in_array($_GET["nav"], array_column($nav['Account Settings'], "link")) || in_array($_GET["nav"], array_column(array_slice($nav, 1), "link"))){
This will first look at all link items in account settings, then slice out account settings and look at the other two subarrays for link items.
Test it here:
https://3v4l.org/pP2Nk

Skipping insert if array item is not found?

I am currently inserting data from json api url into my database, except some arrays are not completed filled out resulting in 'undefined index' errors.
Is there a good way to deal with this? Ofcourse checking each item index with an if isset statement and only setting it if it is available would work but that would be quite tedious for each entry.
foreach($items['response']['groups'] as $item) {
foreach($item['items'] as $item) {
Bar::firstOrCreate([
'lat' => $item['venue']['location']['lat'],
'long' => $item['venue']['location']['lng'],
'postalCode' => $item['venue']['location']['postalCode'],
'city' => $item['venue']['location']['city'],
'state' => $item['venue']['location']['state'],
'country' => $item['venue']['location']['country'],
'address' => $item['venue']['location']['address'],
'rating' => $item['venue']['rating'],
'website' => $item['venue']['url'],
]);
}
}
use simplest way like:
foreach($items['response']['groups'] as $item1) {
foreach($item1['items'] as $item) {
Bar::firstOrCreate([
'lat' => isset($item['venue']['location']['lat'])?$item['venue']['location']['lat'] : '',
'long' => isset($item['venue']['location']['lng'])?$item['venue']['location']['lng'] : '',
'postalCode' => isset($item['venue']['location']['postalCode'])?$item['venue']['location']['postalCode'] : '',
'city' => isset($item['venue']['location']['city'])?$item['venue']['location']['city'] : '',
'state' => isset($item['venue']['location']['state'])?$item['venue']['location']['state'] : '',
'country' => isset($item['venue']['location']['country'])?item['venue']['location']['country'] : '',
'address' => isset($item['venue']['location']['address'])?$item['venue']['location']['address'] : '',
'rating' => isset($item['venue']['rating'])?$item['venue']['rating'] : '',
'website' => isset($item['venue']['url'])?$item['venue']['url'] : '',
]);
}
}
Your problem here is that you rewrite value of $item on each iteration.
foreach($items['response']['groups'] as $item) {
foreach($item['items'] as $item) {
// after first iteration here `$item` doesn't have `items` key
}
Use different variables in every foreach.
Check each array for completeness and only Bar::firstOrCreate() if it's really complete:
foreach($items['response']['groups'] as $item) {
foreach($item['items'] as $item) {
if(
isset($item['venue']) &&
isset($item['venue']['location']) &&
isset($item['venue']['location']['lat']) &&
isset($item['venue']['location']['lng']) &&
isset($item['venue']['location']['postalCode']) &&
isset($item['venue']['location']['city']) &&
isset($item['venue']['location']['state']) &&
isset($item['venue']['location']['country']) &&
isset($item['venue']['location']['address']) &&
isset($item['venue']['location']['lng']) &&
isset($item['venue']['rating']) &&
isset($item['venue']['url'])
)
Bar::firstOrCreate([
'lat' => $item['venue']['location']['lat'],
'long' => $item['venue']['location']['lng'],
'postalCode' => $item['venue']['location']['postalCode'],
'city' => $item['venue']['location']['city'],
'state' => $item['venue']['location']['state'],
'country' => $item['venue']['location']['country'],
'address' => $item['venue']['location']['address'],
'rating' => $item['venue']['rating'],
'website' => $item['venue']['url'],
]);
}
}
you can use these simple steps
remove all the keys from nested arrays that contain no value, then
remove all the empty nested arrays.
$yourArray= array_map('array_filter', $yourArray);
$yourArray= array_filter( $yourArray);
You will have to check the existence of an index somewhere ! If you don't want to do it in the controller, you could have an entity like which checks every field :
<?php
class MyEntity
{
private $lat;
private $long;
private $postalcode;
...
public static function createInstanceFromArray(array $item)
{
if (isset($item['lat']) {
$this->setLat($item['lat']);
}
... and so on
// you could also do it automatic :
foreach($item as $key => $value) {
$methodName = 'set' . ucfirst($key);
if (method_exists($this, $methodName)) {
$this->{$methodName}($value);
}
}
}
public function setLat($lat)
{
$this->lat = $lat;
return $this;
}
public function getLat()
{
return $this->lat;
}
}
Then you could do the following to your original code :
foreach($items['response']['groups'] as $item) {
foreach($item['items'] as $subItem) {
$myEntity = MyNamespace\MyEntity::cretaInstanceFromArray($subItem['venue']);
}
}
Then you could set the fields of your entity with your methods :
'lat' => $myEntity->getLat();
....
this way, even if the array field does not exists, the entity returns a default value.
If you don't want to use objects, you could use array_merge with default values to ensure you will not have undefindex indexes :
$item = array_merge([
'lat' => '',
'long' => '',
'postalCode' => '',
...
], $item['venue']);
And put that treatment in a function for an exemple.

How can i use $data->id in the checkBoxHtmlOptions yii

I am using yii cgridview and i want to add alt in the checkboxes. I am successfull to add this but i want to add $data->rem_type i mean variable in this . here is the code i have tried
array(
'name' => 'check',
'id' => 'selectedIds',
'value' => '$data->rem_id',
'class' => 'CCheckBoxColumn',
'selectableRows' => '100',
'checkBoxHtmlOptions'=>array(
'alt'=>'$data->rem_type'),
),
but it producing the html like this
<input alt="{$data->rem_type}" value="12" id="selectedIds_0" type="checkbox" name="selectedIds[]">
If i removed the quotes (i.e 'alt'=>$data->rem_type)) it show me the error Undefined variable: data
can anybody help me ??
Ok, so I haven't tested this but I think you can do it like this:
extend the CCheckBoxColumn to CheckBoxColumn and overwrite the getDataCellContent function:
class CheckBoxColumn extends CCheckBoxColumn {
public function getDataCellContent($row) {
$data = $this->grid->dataProvider->data[$row];
if ($this->value !== null)
$value = $this->evaluateExpression($this->value, array('data' => $data, 'row' => $row));
elseif ($this->name !== null)
$value = CHtml::value($data, $this->name);
else
$value = $this->grid->dataProvider->keys[$row];
$checked = false;
if ($this->checked !== null)
$checked = $this->evaluateExpression($this->checked, array('data' => $data, 'row' => $row));
$options = $this->checkBoxHtmlOptions;
if ($this->disabled !== null)
$options['disabled'] = $this->evaluateExpression($this->disabled, array('data' => $data, 'row' => $row));
if (array_key_exists("alt", $options)) { //checks if you have set an alt
$options['alt'] = $this->evaluateExpression($options['alt'], array('data' => $data, 'row' => $row)); //if you have it will evaluate the expression
}
$name = $options['name'];
unset($options['name']);
$options['value'] = $value;
$options['id'] = $this->id . '_' . $row;
return CHtml::checkBox($name, $checked, $options);
}
}
I have copied most of the code from the original function
And added this part:
if (array_key_exists("alt", $options)) { //checks if you have set an alt
$options['alt'] = $this->evaluateExpression($options['alt'], array('data' =>data, 'row' => $row)); //if you have it will evaluate the expression
}
There is probably a way to do this better, i.e. not copy the code but I'll let you to this.
Save this in your components folder, include it in your config.php.
And use this class in your widget:
array(
'name' => 'check',
'id' => 'selectedIds',
'value' => '$data->rem_id',
'class' => 'CheckBoxColumn',// <-- instead of CCheckBoxColumn
'selectableRows' => '100',
'checkBoxHtmlOptions'=>array(
'alt'=>'$data->rem_type'),
),
Let me know if it works!

Recursive function returning false

I have no idea why this keeps returning false.
The best part is at the echo statements it actually echo's. This function is in a plugin that I am writing for WordPress.
function find_field($field_name,$array) {
if(array_key_exists($field_name,$array)) {
echo 'Here';
echo $array[$field_name];
return $array[$field_name];
}
foreach($array as $value) {
if(is_array($value)) {
find_field($field_name,$value);
}
}
return false;
}
If I run this: echo find_field('cellphone_number',$arr);
And this is my $arr:
array(
'page' => 'wp_crm_add_new',
'wp_crm' => array(
'user_data' => array(
'user_id' => array(
(int) 0 => array(
'value' => ''
)
),
'user_pass' => array(
(int) 1428 => array(
'value' => ''
)
),
'role' => array(
(int) 2718 => array(
'value' => ''
)
),
'display_name' => array(
(int) 14454 => array(
'value' => 'Albert'
)
),
'user_email' => array(
(int) 26059 => array(
'value' => 'albert#domain.com'
)
),
'company' => array(
(int) 85772 => array(
'value' => ''
)
),
'cellphone_number' => array(
(int) 62506 => array(
'value' => '0820000000'
)
),
'last_visit' => array(
(int) 45073 => array(
'value' => ''
)
)
)
),
'meta-box-order-nonce' => '1374268beb',
'closedpostboxesnonce' => '92fffdd685',
'wp_crm_update_user' => '42d35393d7',
'show_admin_bar_front' => 'false',
'color-nonce' => 'c02f4b0a88',
'admin_color' => 'sunrise',
'original_publish' => 'Publish',
'publish' => 'Save'
)
I get false as the result, every time. What am I doing wrong?
This is happening because you return false. Here's the logic break-down:
function find_field($field_name,$array) {
if(SOMETHING) {
DO SOMETHING
return SOMETHING;
}
foreach($array as $value) {
if(SOMETHING) {
CALL RECURSIVE FUNCTION
}
}
return false;
}
Put like this... if you call the function at any point and send a value that passes the first if statement, then you return a value. If you do not pass that if statement (aka the array_key doesn't exist) then you move into a foreach loop, which does some stuff, calls a recursive function which eventually returns a value (and does nothing with it) before moving on to the final line of code... return false.
It is important to first think of a recursive function as a one-time function before compounding it into a recursive one.
Just like any other function, this recursive function is going to execute every line of code (although interrupted) before it is done. The last line of code you execute is always a "return false" which is throwing your result.
Perhaps you should be returning the inner foreach loop value when you call the recursive function:
function find_field($field_name,$array) {
if(array_key_exists($field_name,$array)) {
echo 'Here';
echo $array[$field_name];
return $array[$field_name];
}
foreach($array as $value) {
if(is_array($value)) {
return find_field($field_name,$value);
}
}
return false;
}

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