I know most undefined index notices are the result of not initializing variables. However, what causes them in arrays and such?

I have a few that I cannot wrap my head around:

[E_NOTICE] Undefined offset: 1
On line 27

Line 27:

list($file,$extension) = explode('.', basename($path));

[E_NOTICE] Undefined offset: 1
On line 35

Line 35:

list($key,$val) = preg_split('/=/',$b);

[E_NOTICE] Undefined variable: result
On line 45

Line 45:

$result .= $cat_name['categories_name'];

This is the full code (all notices are coming from this script):

function callback($pagecontent) {
  $pagecontent = preg_replace_callback("/(<[Aa][ \r\n\t]{1}[^>]*href[^=]*=[ '\"\n\r\t]*)([^ \"'>\r\n\t#]+)([^>]*>)/",'wrap_href',$pagecontent);
  return $pagecontent;

}

function transform_uri($param) {
  $uriparts = parse_url($param[2]);
  $newquery='';
  $scheme = $uriparts['scheme'].'://';
  if (($scheme != 'http://') && ($scheme != 'https://')) return $param[1].$param[2].$param[3];
  $host = $uriparts['host'];
  if ($host != $_SERVER['SERVER_NAME'] && $host != $_SERVER['SERVER_ADDR']) return $param[1].$param[2].$param[3];
  

  $path = $uriparts['path'];
  list($file,$extension) = explode('.', basename($path));
  if($extension != 'php') return $param[1].$param[2].$param[3];
  $extension = ".html";
  $path = rtrim(dirname($path),'/');
  $query = isset( $uriparts['query'] ) ? $uriparts['query'] : '';
  $anchor = isset( $uriparts['anchor'] ) ? $uriparts['anchor'] : '';
  if ($a = explode('&',$query)){
    foreach ($a as $b) {
	  list($key,$val) = preg_split('/=/',$b);
	  switch ($key) {
		case 'cPath':
		    if(preg_match('/^[_0-9]*$/',$val)){
			  if($cat_arr = explode('_', $val)){
			    $count = false;
			    foreach($cat_arr as $value){
				  $cat_Q = tep_db_query("select c.categories_id, cd.categories_name from " . TABLE_CATEGORIES . " c, " . TABLE_CATEGORIES_DESCRIPTION . " cd where c.categories_id = '" . $value . "'  and c.categories_id = cd.categories_id");
				  $cat_name = tep_db_fetch_array($cat_Q);
				  if(!$count){
				    $result .= $cat_name['categories_name'];
					$count = true;
				  }
				  else{
				    $result .= '_' . $cat_name['categories_name'];
				  } 
				}
				$cat = '/category/'. str_replace(' ' , '+' , $result);
			  }
			  else{			
			    $cat = '/category/'.$val;
			  }
			}
			else{
			  $cat = '/category/'.$val;
			}
		    break;
		case 'language':
			$lan = $val.'/'.$path;
		    break;
		case 'products_id':
			$name_Q = tep_db_query("select products_name from " . TABLE_PRODUCTS_DESCRIPTION . " where products_id = '" . $val . "'");
	        $pro = ($t = tep_db_fetch_array($name_Q)) ? '/product/' . str_replace(" ", "_" , $t['products_name']) : '/product/'.$val;
		    break;
		case 'manufacturers_id':
		    $band_Q = tep_db_query("select manufacturers_name, manufacturers_type from " . TABLE_MANUFACTURERS . " where manufacturers_id = '" . $val . "'");
	        $man = ($t = tep_db_fetch_array($band_Q)) ? '/'.$t['manufacturers_type'].'/'.str_replace(" ", "_" , $t['manufacturers_name']) : $man = '/band/'.$val;
		    break;
		case 'catid':
		    if(strstr($_SERVER["HTTP_USER_AGENT"],'Mozilla'))  $newquery .= $key.'='.$val.'&';
		    break;
		default:
		    if($newquery || $key) $newquery .= $key.'='.$val.'&';	  
	  }
    }
  }
  if ($newquery) $newquery = '?'.rtrim($newquery,'&');
  $path = '';
  if(isset($man)) $path .= $man;
  if(isset($cat)) $path .= $cat;
  if(isset($pro)) $path .= $pro;

  ((isset($man) || isset($cat) || isset($pro))) ? $host .= '' :$host .= '/';
  if($file == 'index' || $file == 'product_info'){
    if((isset($man) || isset($cat) || isset($pro))) $file= '';
  }
  if(preg_match('/^reviews$/',$file)) $file = '/' . $file;
  return $param[1].$scheme.$host.$file.$path.$extension.$newquery.$anchor.$param[3];

  
}
function wrap_href($param) {
  return transform_uri($param);
}

ob_start("callback");

The complaint about $result is that you are appending to an uninitialized variable. $result could be initialized early in the function to an empty string for example. $result=''; I don't use list() very often so not sure about the other notices. Seems like "offset 1" would be the second element of the returned array. If you exploded a path of '.' or '..' there would be no extension and therefore no element 1.

Member Avatar for nevvermind

I know most undefined index notices are the result of not initializing variables.

How can an error for not initializing variables say "undefined index"?!

Undefined index - variable exists, but not the "associative index" you're pointing at.

$y = array('surname' => 'Bill', 'name' => 'Murray');

echo $y['address'] // Notice: undefined index 2
// list() works only in numeric array

Undefined offset - variable exists, but not the "numeric index" you're pointing at.

$y = array('Bill', 'Murray');

echo $y[2] // Notice: undefined offset 2
list($surname, $name, $address) = $y; // Notice: undefined offset 2

Look just silent the array or variable with @ sign.

You must have just had apache update lately i think.

USE @ to suppress the warning. its not error. Dont touch your working code ok?

Explore :)

Line 27:

list($file,$extension) = explode('.', basename($path));

explode is not returning 2 array pieces. So that means $path does not contain what you think it does from somewhere higher up. My guess is $path = $uriparts['path']; is not returning a filename but rather a path.

$fileParts = explode('.', $basename($path));
$file = isset($fileParts[0]) ? $fileParts[0] : '';
$extension = isset($fileParts[1]) ? $fileParts[1] : '';

Line 35:

list($key,$val) = preg_split('/=/',$b);

Again preg_split is not returning an array with two items.
It looks like your trying to parse the query string into variable = value pieces.
Look at parse_str in the manual, it does just this.
Also when splitting by something as simple as an '=' avoid regular expressions they're very slow compared to straight string manipulations.

$query = isset( $uriparts['query'] ) ? $uriparts['query'] : '';
  $anchor = isset( $uriparts['anchor'] ) ? $uriparts['anchor'] : '';
  if ($a = explode('&',$query)){
    foreach ($a as $b) {
	  list($key,$val) = preg_split('/=/',$b);
	  switch ($key) {

TO

$query = isset( $uriparts['query'] ) ? $uriparts['query'] : '';
$anchor = isset( $uriparts['anchor'] ) ? $uriparts['anchor'] : '';
$a = array();
//parse the string and put into the array $a
parse_str($query, $a);
if( !empty($a) ){
  foreach($a as $key => $value ){
     switch( $key ) {

    //Do rest of code or skip if $a has no key value pairs
}

Line 45:

$result .= $cat_name['categories_name'];

This last one is easy.

function transform_uri($param) {
  //Define the result variable
  $result = '';
  ....

As far as using the @ operator to suppress errors. DON'T DO IT. Learn to develop so that your code isn't throwing warnings or errors that need suppressed. Initialize your variables before you use them, and check if variables are set before you try to work with them. There is also a large performance hit that comes with using the @ operator.

If you really want to suppress error messages, set an error handler http://php.net/manual/en/function.set-error-handler.php that will notify you, via email, log file, etc. so that you can still be aware of an issue when one exists.

Well written code should not need error suppression it should have sufficient mechanisms for handling errors or failed conditions. The purpose of turning off error reporting on a production environment in my opinion, is to prevent the user from seeing nasty messages if something would go wrong, and it also prevents your site from exposing potentially sensitive data to a random user.

Thanks for clearing my misconceptions, nevvermind.

mschroeder - Your guide codes have proven to be extremely helpful! I studied them and switched around my code and was able to rid these notices.

Thanks for sharing your expertise!

Glad I could be of help.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.