1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Undefined Offset? What does that mean?

Discussion in 'XenForo Development Discussions' started by Jaxel, Oct 8, 2010.

  1. Jaxel

    Jaxel Well-Known Member

    I built a wiki-like template system onto my CMS. The way it works is actually pretty simple... If I put the following code into a page, it will replace it with the appropriate pre-defined template:
    | name = Cassandra Alexandra
    | debut = Soulcalibur II
    | voiceE = Debra Jean Rogers
    | voiceJ = Reiko Takagi
    The way it works, is when it is building the page, it sends the content of the page to a model:
    class EWRporta_Model_Templates extends XenForo_Model
    	public function parseTemplates($text)
    		$templates = $this->fetchAllKeyed("
    			SELECT template_name AS name, template_content AS content
    				FROM EWRporta_templates
    		", 'name');
    		$codePattern = '/\[template=([\w]+)\](.*?)\[\/template\]/si';
    		$dataPattern = '/([\w\s]+)=(.+)/';
    		if (preg_match_all($codePattern, $text, $codeMatches))
    			foreach ($codeMatches AS $key => $codeMatch)
    				if (isset($templates[$codeMatches[1][$key]]))
    					$matches = explode("|", $codeMatches[2][$key]);
    					$replaceText = $templates[$codeMatches[1][$key]]['content'];
    					foreach ($matches AS $match)
    						if (preg_match($dataPattern, $match, $dataMatch))
    							$replaceText = str_replace("{{{".trim($dataMatch[1])."}}}", trim($dataMatch[2]), $replaceText);
    					echo $replaceText;
    					$text = str_replace($codeMatches[0][$key], $replaceText, $text);					
    		return $text;
    Allow me to try to explain how this code works:
    1. parseTemplate recieves original content as $text
    2. database fetches existing templates and stores them into $templates, keyed by the name
    3. defines regular expression matching patterns
    4. if regular expression match collects any results in $codeMatches, continue
    5. for each result stored in the match, continue as $codeMatch
    6. if template['name of match'] actually exists, continue, otherwise ignore
    7. the rest is parsing of the results and replacement text, which I dont need to get into for this discussion. needless to say, I know it all works because "echo $replaceText" actually works and displays the proper results
    This code works great, the replacement text is gathered correctly... and the system even echos the $replaceText out! However, the rest of XenForo then fails with the following error and trace stack:

    Server Error​
    Undefined offset: 2​
    1. XenForo_Application::handlePhpError() in EWRporta/Model/Templates.php at line 19
    2. EWRporta_Model_Templates->parseTemplates() in EWRporta/ControllerPublic/Index.php at line 104
    3. EWRporta_ControllerPublic_Index->actionPages() in XenForo/FrontController.php at line 303
    4. XenForo_FrontController->dispatch() in XenForo/FrontController.php at line 132
    5. XenForo_FrontController->run() in /home/eightway/public_xen1/index.php at line 15

    Line 19 is the following code:
    if (isset($templates[$codeMatches[1][$key]]));
    However, like I said, I know there is nothing wrong with my code, since the IF does process correctly and it does then go onto ECHO which is within the IF, and the results of the echo are correct.
  2. g0rn

    g0rn Well-Known Member

    You are referring to an array element that does not exist. You should use array_key_exists() function instead of checking isset($template[$index-of-non-existing-element]).
  3. Jaxel

    Jaxel Well-Known Member

    g0rn, thats not the issue... even using array_key_exists(), I get the same error...

    You can see that the function I wrote works by going here:

    The replacement text is a table which was automatically generated at the top (the result of "echo $replaceText;"). But then the forum itself stops working. The function I wrote works fine, but then XenForo's php error handler claims there was an error is brings everything to a halt... even though there was no error.

    On another note, in this case, isset() is preferred because its faster and there are no worries about NULL values.
  4. Jaxel

    Jaxel Well-Known Member

    Okay... I figured it out...
    foreach ($codeMatches AS $key => $codeMatch)
    Because each element in the $codeMatches array each had a sub array with 3 more elements... the foreach always assumed there were a total of 3 elements. For some reason foreach is iterating on itself down to the deepest nest, instead of the next. So I changed the code to:

    foreach ($codeMatches[1] AS $key => $codeMatch)

Share This Page