Undefined Offset

  • (2 Pages)
  • +
  • 1
  • 2

16 Replies - 1052 Views - Last Post: 16 August 2015 - 02:57 PM Rate Topic: -----

#1 JeremyBenson11  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 239
  • Joined: 10-January 14

Undefined Offset

Posted 16 August 2015 - 10:38 AM

Hello,

I'm working on a script that runs the shopping cart for ad space on my site, so I can't have any bugs here. Right now I'm getting undefined offset on line 116.

Basically the code hauls out all possible placements, and loops through taken placements and removes them from possible placements. It's working great, but this undefined offset error is throwing me off. It hasn't hindered the output, but don't want to run into an instance down the road, or leave lingering bugs..

I have two tables:

ad_placements - which is taken placements.
genres - which is all available placements.

Right now I loop through takenPlacements array up to the count of availablePlacements - 1. If When I find a taken placement I loop through availablePlacements array and unset the index.

Thanks for any help :) I don't dare leave a bug in this script, too sensitive...

<?php

session_start();

//if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SESSION['ID']))
//{
ini_set('xdebug.var_display_max_depth', 5);
ini_set('xdebug.var_display_max_children', 2000);
ini_set('xdebug.var_display_max_data', 2000);

	require('../../data/sqldata.php');
	
	$takenPlacements = array();
	$availablePlacements = array();
	
	$db = new PDO($dsn, $dbUserName, $dbPassword, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
	
	// get all the taken placements
	$getTakenStm = $db->prepare('SELECT * FROM `ad_placements` WHERE `country` = ?');

	try{
		
		//$getTakenStm->execute(array($_POST['country']));
		$getTakenStm->execute(array('Canada'));
		$takenPlacements = $getTakenStm->fetchAll();
		
	}catch(\PDOException $e){}
	
	// get all possible placements
	
	$getPlacementsStm = $db->prepare('SELECT `ID`, `mainGenre`, `genre`, `subGenre` FROM `genres` WHERE `ID` < ?');
	
	try{
		
		$getPlacementsStm->execute(array(333));
		$availablePlacements = $getPlacementsStm->fetchAll();
		
	}catch(\PDOException $e){ }
		
	// remove the taken placements from the possible placements	
		$count = count($availablePlacements);
		$removedBefore = array();
		var_dump($availablePlacements);
		
		for($i = 0; $i <= $count - 1; $i += 1)
		{   

			if(isset($takenPlacements[$i]['ID']))
			{
				// test normal placement space
				$genres = explode('@', $takenPlacements[$i]['placement']);
				var_dump($genres);
				if($takenPlacements[$i]['placement'] != '[email protected]@Index' && $takenPlacements[$i]['placement'] != '[email protected]@Profile')
				{
					//get count from placements
				 $countStm = $db->prepare('SELECT * FROM `ad_placements` WHERE `placement` = ? AND `Country` = ?');
				
				 try{
				
						$countStm->execute(array($takenPlacements[$i]['placement'],
												 'Canada'));
						$normalPlacementCount = $countStm->rowCount();
						
				 }catch(\PDOException $e){}
				
					
					if($normalPlacementCount >= 2 && !in_array($takenPlacements[$i]['placement'], $removedBefore))
					{
						// There are too many of this placement, remove it from available placements
						$removeIndex = 0;
						 // loop to capture index to remove.
						for($j = 0; $j <= $count - 1; $j += 1)
						{
							
							if($availablePlacements[$j]['mainGenre'] == $genres[0] && 
							   $availablePlacements[$j]['genre'] == $genres[1] && 
							   $availablePlacements[$j]['subGenre'] == $genres[2])
							{
								
								$removeIndex = $j;
								unset($availablePlacements[$j]);							
								
							}
							
						}
						
						
						
						array_push($removedBefore, $takenPlacements[$i]['placement']);
						
					}
				
					 // End test normal; start test index
				}elseif($takenPlacements[$i]['placement'] == '[email protected]@Index')
				{
					
						$countStm = $db->prepare('SELECT * FROM `ad_placements` WHERE `placement` = ?');
				
				 
					try{
				
						$countStm->execute(array($takenPlacements[$i]['placement']));
						$indexPlacementCount = $countStm->rowCount();
						
					}catch(\PDOException $e){}
				     
						if($indexPlacementCount >= 1 && !in_array($takenPlacements[$i]['placement'], $removedBefore))
						{	

						// There are too many of this placement, remove it from available placements
							$removeIndex = 0;
						 // loop to capture index to remove.
						for($j = 0; $j <= $count - 1; $j += 1)
						{
							
							if($availablePlacements[$j]['mainGenre'] == $genres[0] && 
							   $availablePlacements[$j]['genre'] == $genres[1] && 
							   $availablePlacements[$j]['subGenre'] == $genres[2])
							{
								
								$removeIndex = $j;
								unset($availablePlacements[$j]);
								
								
							}
							
						}
						
						array_push($removedBefore, $takenPlacements[$i]['placement']);
						
						}
				
					// end index test count, start profile
				}elseif($takenPlacements[$i]['placement'] == '[email protected]@Profile')
				{
					
					$countStm = $db->prepare('SELECT * FROM `ad_placements` WHERE `placement` = ?');
				
				 
					try{
				
						$countStm->execute(array($takenPlacements[$i]['placement']));
						$profilePlacementCount = $countStm->rowCount();
						
					}catch(\PDOException $e){}
					
					if($profilePlacementCount >= 2 && !in_array($takenPlacements[$i]['placement'], $removedBefore))
						{	
							// There are too many of this placement, remove it from available placements
						
							$removeIndex = 0;
						 // loop to capture index to remove.
						for($j = 0; $j <= $count - 1; $j += 1)
						{
							
							if($availablePlacements[$j]['mainGenre'] == $genres[0] && 
							   $availablePlacements[$j]['genre'] == $genres[1] && 
							   $availablePlacements[$j]['subGenre'] == $genres[2])
							{
								
								$removeIndex = $j;
								unset($availablePlacements[$j]);	
								
								
							}
							
						}
							
						array_push($removedBefore, $takenPlacements[$i]['placement']);
						
						}
					
					// end test count for profile placements
				}
				
			 // end of if takenPlacement['ID'] set, for testing placement count
 			}
		 // end loop for looping through available placements				
		}
		
			// Re-index the array before sending it back			
			$availablePlacements = array_values($availablePlacements);
			var_dump($availablePlacements);
			
			// Send array back to JS
			json_encode($availablePlacements);
	
	
//}else{
	
	// go to index with error
	
//}

?>


Is This A Good Question/Topic? 0
  • +

Replies To: Undefined Offset

#2 andrewsw  Icon User is online

  • say what now
  • member icon

Reputation: 6410
  • View blog
  • Posts: 25,909
  • Joined: 12-December 12

Re: Undefined Offset

Posted 16 August 2015 - 11:14 AM

Line 116 is this:
if($availablePlacements[$j]['mainGenre'] == $genres[0] &&
    $availablePlacements[$j]['genre'] == $genres[1] &&
    $availablePlacements[$j]['subGenre'] == $genres[2])

Undefined offset means you are trying to refer, for example, to element [4] when there are only three elements, 0..2. Any of these array references might be wrong. Which one do you think is wrong?

Print out the value of $count. How many elements does the 1st dimension of $availablePlacements have? Does $genres have three elements?

If necessary split this large if condition into separate statements, using some temporary variables, to help you discover the specific issue. Basic debugging 101.

You are in the best position to discover which offset in particular causes the error.

Quote

I don't dare leave a bug in this script, too sensitive...

..so you must understand how to debug and test the code.

This post has been edited by andrewsw: 16 August 2015 - 11:17 AM

Was This Post Helpful? 0
  • +
  • -

#3 andrewsw  Icon User is online

  • say what now
  • member icon

Reputation: 6410
  • View blog
  • Posts: 25,909
  • Joined: 12-December 12

Re: Undefined Offset

Posted 16 August 2015 - 11:20 AM

ini_set('xdebug.var_display_max_depth', 5);

Does this suggest that you know how to step through your code?
Was This Post Helpful? 0
  • +
  • -

#4 CTphpnwb  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3717
  • View blog
  • Posts: 13,493
  • Joined: 08-August 08

Re: Undefined Offset

Posted 16 August 2015 - 11:25 AM

For starters, your code is too long. It should be broken up into functions/classes.

Your specific problem is because you're deleting an element of the array (unset($availablePlacements[$j]);) but not altering the count.
Was This Post Helpful? 1
  • +
  • -

#5 JeremyBenson11  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 239
  • Joined: 10-January 14

Re: Undefined Offset

Posted 16 August 2015 - 12:12 PM

Thanks guys, saved the day :) The following line of code in the beginning of each loop iteration helped.

$availablePlacements = array_values($availablePlacements);
$count = count($availablePlacements);


Was This Post Helpful? 0
  • +
  • -

#6 JeremyBenson11  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 239
  • Joined: 10-January 14

Re: Undefined Offset

Posted 16 August 2015 - 12:21 PM

Shoot. I have a new bug. Now when I send a country other than Canada, because Canada is the only country I have mock indexes to remove for, based on database entries of prior ads, the script sends back an empty array... I kind of know what to do.. I just have to modify the code to say:

if nothing to take away from availableSpaces send full array...

Still, could someone explain why my availableSpaces array is being wiped when there's nothing in $takenPlacements?
Was This Post Helpful? 0
  • +
  • -

#7 JeremyBenson11  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 239
  • Joined: 10-January 14

Re: Undefined Offset

Posted 16 August 2015 - 12:36 PM

Actually my fix didn't work. Even when I bypass all the loops I'm getting and empty array returned. Shouldn't be.. When I var_dump before json_encode($availablePlacements); I get data in my alert on js... so there has to be just something wrong with json_encode...

<?php

session_start();

if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SESSION['ID']))
{

	require('../../data/sqldata.php');
	
	$takenPlacements = array();
	$availablePlacements = array();
	
	$db = new PDO($dsn, $dbUserName, $dbPassword, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
	
	// get all the taken placements
	$getTakenStm = $db->prepare('SELECT * FROM `ad_placements` WHERE `country` = ?');

	try{
		
		$getTakenStm->execute(array($_POST['country']));
		$takenPlacements = $getTakenStm->fetchAll();
		
	}catch(\PDOException $e){}
	
	// get all possible placements
	
	$getPlacementsStm = $db->prepare('SELECT `ID`, `mainGenre`, `genre`, `subGenre` FROM `genres` WHERE `ID` < ?');
	
	try{
		
		$getPlacementsStm->execute(array(333));
		$availablePlacements = $getPlacementsStm->fetchAll();
		
	}catch(\PDOException $e){ }
	
	if(!empty($takenPlacements))
	{
	// remove the taken placements from the possible placements	
		$count = count($availablePlacements);
		$removedBefore = array();
		
		for($i = 0; $i <= $count - 1; $i += 1)
		{   
			$availablePlacements = array_values($availablePlacements);
			$count = count($availablePlacements);
			
			if(isset($takenPlacements[$i]['ID']))
			{
				// test normal placement space
				$genres = explode('@', $takenPlacements[$i]['placement']);
				var_dump($genres);
				if($takenPlacements[$i]['placement'] != '[email protected]@Index' && $takenPlacements[$i]['placement'] != '[email protected]@Profile')
				{
					//get count from placements
				 $countStm = $db->prepare('SELECT * FROM `ad_placements` WHERE `placement` = ? AND `Country` = ?');
				
				 try{
				
						$countStm->execute(array($takenPlacements[$i]['placement'],
												 $_POST['country']));
						$normalPlacementCount = $countStm->rowCount();
						
				 }catch(\PDOException $e){}
				
					
					if($normalPlacementCount >= 2 && !in_array($takenPlacements[$i]['placement'], $removedBefore))
					{
						// There are too many of this placement, remove it from available placements
						$removeIndex = 0;
						 // loop to capture index to remove.
						for($j = 0; $j <= $count - 1; $j += 1)
						{
							
							if($availablePlacements[$j]['mainGenre'] == $genres[0] && 
							   $availablePlacements[$j]['genre'] == $genres[1] && 
							   $availablePlacements[$j]['subGenre'] == $genres[2])
							{
								
								$removeIndex = $j;
								unset($availablePlacements[$j]);
								
								
							}
							
						}
						
						
						
						array_push($removedBefore, $takenPlacements[$i]['placement']);
						
					}
				
					 // End test normal; start test index
				}elseif($takenPlacements[$i]['placement'] == '[email protected]@Index')
				{
					
						$countStm = $db->prepare('SELECT * FROM `ad_placements` WHERE `placement` = ?');
				
				 
					try{
				
						$countStm->execute(array($takenPlacements[$i]['placement']));
						$indexPlacementCount = $countStm->rowCount();
						
					}catch(\PDOException $e){}
				     
						if($indexPlacementCount >= 1 && !in_array($takenPlacements[$i]['placement'], $removedBefore))
						{	

						// There are too many of this placement, remove it from available placements
							$removeIndex = 0;
						 // loop to capture index to remove.
						for($j = 0; $j <= $count - 1; $j += 1)
						{
							
							if($availablePlacements[$j]['mainGenre'] == $genres[0] && 
							   $availablePlacements[$j]['genre'] == $genres[1] && 
							   $availablePlacements[$j]['subGenre'] == $genres[2])
							{
								
								$removeIndex = $j;
								unset($availablePlacements[$j]);
								
								
								
							}
							
						}
						
						array_push($removedBefore, $takenPlacements[$i]['placement']);
						
						}
				
					// end index test count, start profile
				}elseif($takenPlacements[$i]['placement'] == '[email protected]@Profile')
				{
					
					$countStm = $db->prepare('SELECT * FROM `ad_placements` WHERE `placement` = ?');
				
				 
					try{
				
						$countStm->execute(array($takenPlacements[$i]['placement']));
						$profilePlacementCount = $countStm->rowCount();
						
					}catch(\PDOException $e){}
					
					if($profilePlacementCount >= 2 && !in_array($takenPlacements[$i]['placement'], $removedBefore))
						{	
							// There are too many of this placement, remove it from available placements
						
							$removeIndex = 0;
						 // loop to capture index to remove.
						for($j = 0; $j <= $count - 1; $j += 1)
						{
							
							if($availablePlacements[$j]['mainGenre'] == $genres[0] && 
							   $availablePlacements[$j]['genre'] == $genres[1] && 
							   $availablePlacements[$j]['subGenre'] == $genres[2])
							{
								
								$removeIndex = $j;
								unset($availablePlacements[$j]);	
							
								
							}
							
						}
							
						array_push($removedBefore, $takenPlacements[$i]['placement']);
						
						}
					
					// end test count for profile placements
				}
				
			 // end of if takenPlacement['ID'] set, for testing placement count
 			}
		 // end loop for looping through available placements				
		}
		
			// Re-index the array before sending it back			
			$availablePlacements = array_values($availablePlacements);
			
			// Send array back to JS
			json_encode($availablePlacements);
			// end if $takenPlacements ! empty.
	}else{
			// send back full array, nothing to take away.
			json_encode($availablePlacements);
		
	}
	
}else{
	
	// go to index with error
	
}

?>

This post has been edited by JeremyBenson11: 16 August 2015 - 12:39 PM

Was This Post Helpful? 0
  • +
  • -

#8 CTphpnwb  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3717
  • View blog
  • Posts: 13,493
  • Joined: 08-August 08

Re: Undefined Offset

Posted 16 August 2015 - 12:51 PM

You've got 200 lines of code! That's too much for one function, and since you have no functions, your code is basically one long function. Break it up!! It's no easier for us to read it than you, so if you can't read it, you need to work on making it more readable. Doing that will make fixing it much easier.

Also, you should read/study this.
Was This Post Helpful? 0
  • +
  • -

#9 andrewsw  Icon User is online

  • say what now
  • member icon

Reputation: 6410
  • View blog
  • Posts: 25,909
  • Joined: 12-December 12

Re: Undefined Offset

Posted 16 August 2015 - 01:14 PM

Note that
//get count from placements
$countStm = $db->prepare('SELECT * FROM `ad_placements` WHERE `placement` = ? AND `Country` = ?');

you don't have to retrieve all the rows (and columns) and then count them, you can just use SELECT COUNT(*) FROM ...
Was This Post Helpful? 0
  • +
  • -

#10 JeremyBenson11  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 239
  • Joined: 10-January 14

Re: Undefined Offset

Posted 16 August 2015 - 01:36 PM

Readability isn't the issue here, I'll show you. You'll notice the only difference is the very last line.

This code alone alerts nothing in my js.

require('../../data/sqldata.php');
	
	$takenPlacements = array();
	$availablePlacements = array();
	
	$db = new PDO($dsn, $dbUserName, $dbPassword, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
	
	// get all the taken placements
	$getTakenStm = $db->prepare('SELECT * FROM `ad_placements` WHERE `country` = ?');

	try{
		
		$getTakenStm->execute(array($_POST['country']));
		$takenPlacements = $getTakenStm->fetchAll();
		
	}catch(\PDOException $e){}
	
	// get all possible placements
	
	$getPlacementsStm = $db->prepare('SELECT `ID`, `mainGenre`, `genre`, `subGenre` FROM `genres` WHERE `ID` < ?');
	
	try{
		
		$getPlacementsStm->execute(array(333));
		$availablePlacements = $getPlacementsStm->fetchAll();
		
	}catch(\PDOException $e){ }
	json_encode($availablePlacements);



This code alerts the dumped data

require('../../data/sqldata.php');
	
	$takenPlacements = array();
	$availablePlacements = array();
	
	$db = new PDO($dsn, $dbUserName, $dbPassword, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
	
	// get all the taken placements
	$getTakenStm = $db->prepare('SELECT * FROM `ad_placements` WHERE `country` = ?');

	try{
		
		$getTakenStm->execute(array($_POST['country']));
		$takenPlacements = $getTakenStm->fetchAll();
		
	}catch(\PDOException $e){}
	
	// get all possible placements
	
	$getPlacementsStm = $db->prepare('SELECT `ID`, `mainGenre`, `genre`, `subGenre` FROM `genres` WHERE `ID` < ?');
	
	try{
		
		$getPlacementsStm->execute(array(333));
		$availablePlacements = $getPlacementsStm->fetchAll();
		
	}catch(\PDOException $e){ }
	var_dump($availablePlacements);


Was This Post Helpful? 0
  • +
  • -

#11 andrewsw  Icon User is online

  • say what now
  • member icon

Reputation: 6410
  • View blog
  • Posts: 25,909
  • Joined: 12-December 12

Re: Undefined Offset

Posted 16 August 2015 - 01:46 PM

json_encode($availablePlacements);

This code does nothing. To output you would have to echo it (or otherwise print it). To retain the encoded data you would need to assign the result of json_encode to a variable.

Note that this is a very poor practice:
}catch(\PDOException $e){}

I trust that you won't be leaving these statements as they are.
Was This Post Helpful? 0
  • +
  • -

#12 JeremyBenson11  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 239
  • Joined: 10-January 14

Re: Undefined Offset

Posted 16 August 2015 - 02:08 PM

Ah, solved this one I think...

So the alert box not holds a longer version of this..

[{"ID":"1","0":"1","mainGenre":"Movies\/Television","1":"Movies\/Television","genre":"Movies\/Television","2":"Movies\/Television","subGenre":"Reality","3":"Reality"},{"ID":"2","0":"2","mainGenre":"Movies\/Television","1":"Movies\/Television","genre":"Movies\/Television","2":"Movies\/Television","subGenre":"Documentary","3":"Documentary"},{"ID":"3","0":"3","mainGenre":"Movies\/Television","1":"Movies\/Television","genre":"Movies\/Television","2":"Movies\/Television","subGenre":"Action","3":"Action"},


this data can be traversed in JS like an array, or with dot notation? Can I loop over it too, or do I have to run code on it to make it an array?

One thing. I got some extra slashes...

"mainGenre":"Movies\/Television"

that should be: "mainGenre":"Movies/Television"

Thanks gain guys, got me through more stupid bugs..

This post has been edited by andrewsw: 16 August 2015 - 02:12 PM
Reason for edit:: switched il to code tags

Was This Post Helpful? 0
  • +
  • -

#13 andrewsw  Icon User is online

  • say what now
  • member icon

Reputation: 6410
  • View blog
  • Posts: 25,909
  • Joined: 12-December 12

Re: Undefined Offset

Posted 16 August 2015 - 02:25 PM

json_encode escaped the forward slashes. Use JSON.parse in Javascript.

View Postandrewsw, on 16 August 2015 - 08:46 PM, said:

Note that this is a very poor practice:
}catch(\PDOException $e){}

I trust that you won't be leaving these statements as they are.

Was This Post Helpful? 0
  • +
  • -

#14 JeremyBenson11  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 239
  • Joined: 10-January 14

Re: Undefined Offset

Posted 16 August 2015 - 02:37 PM

Hm, when I do alert(JSON.parse(results)); I get:

[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]

Before that I couldn't access the data either. alert(results[1].mainGenre); would output 'undefined'..
Was This Post Helpful? 0
  • +
  • -

#15 andrewsw  Icon User is online

  • say what now
  • member icon

Reputation: 6410
  • View blog
  • Posts: 25,909
  • Joined: 12-December 12

Re: Undefined Offset

Posted 16 August 2015 - 02:51 PM

You haven't posted relevant code, but JSON.parse works with a string so you'll probably need to do:
var jResults = JSON.parse("'" + results + "'");

Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2