Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 821
  • Last Modified:

Cannot redeclare startsWith()

Hey Experts!!

I have a few functions in my php page and my server keeps throwing the following error:


PHP Fatal error:  Cannot redeclare startsWith() (previously declared in /wp-content/themes/mountain-dawn/page.php:9) in /wp-content/themes/mountain-dawn/page.php on line 15

I have the page below, but don't understand what's going on.

<?php 
   get_header();
   	/* Code to handle including appropriate templates for GS Events, Artists and Releases */

	$giantStepArtistId = null;
	$giantStepReleaseId = null;
	$giantStepEventId = null;

	function startsWith($str, $searchStr, $case=true)
	{
	   if ($case)
		  return strpos($str, $searchStr, 0) === 0;
	
	   return stripos($str, $searchStr, 0) === 0;
	}
	
	function getValueFromEndOfArraySafely($urlParts, $indexOffsetFromEndOfArray)
	{
	   $index = sizeof($urlParts) - $indexOffsetFromEndOfArray;
	   if ($index >= 0)
		  return $urlParts[$index];
	   return null;
	}

/*########################################
######## START ARTIST SECTION ############
########################################*/	
	function handleArtistPage($url)
	{
		global $giantStepArtistId;

		//echo "The url is ".$url; 
		
		// we're only dealing with artists here
		if (!startsWith($url,"/index.php/artists"))
		{
			// echo "url doesn't start with artists...";
			return;
		}
		
		$parts = end(array_filter(explode('/',$url)));
		$lastPartOfUrl = $parts;
		
		//echo "<h3>the last part of url is ".$lastPartOfUrl."</h3>";
		
		if ($lastPartOfUrl == "bio")
		{
			$giantStepArtistId  = getValueFromEndOfArraySafely($parts,0);
			if ($giantStepArtistId != null)
			{
				//echo "In the bio and the artist id is ".$giantStepArtistId;
				get_template_part( "page", "artist-bio");
			}
		}
		elseif ($lastPartOfUrl == null || $lastPartOfUrl == "" )
		{
		    $giantStepArtistId = getValueFromEndOfArraySafely($parts,0);
		    if ($giantStepArtistId != null && $giantStepArtistId != "artists")
		    {
				//echo "In the null area, the artId is ".$lastPartOfUrl;
				get_template_part( "page", "artist");
		    }
		    else
		    {
				//echo "In the null area, no artist id "; 
				get_template_part( "page", "artist-listing");
		    }
		}
		else
		{
			$giantStepArtistId = getValueFromEndOfArraySafely($parts,0);
			if ($giantStepArtistId != null)
			{
				// echo "In the artist detail page, the $artId is ".$giantStepArtistId;
				// assume we have a detail page
				get_template_part( "page", "artist" );
			}
		}
	}
/*########################################
######## START RELEASE SECTION ##########
########################################*/

function handleReleasePage($url)
	{
		global $giantStepReleaseId;
				
		// we're only dealing with releases here
		if (strpos($url,"/index.php/releases")){
			return;
		}
		
		$parts = end(array_filter(explode('/',$url)));
		$lastPartOfUrl = $parts;
	
		/*
		echo "This is the url:".$url."<br>";
		echo "<br> <br> the last part of url is:".$lastPartOfUrl."<br>";
		echo "This is the parts:".$parts."<br>";
		echo "<pre> This is the parts variable ";
			echo print_r($parts);
		echo "</pre>";
		*/
		
		if ($lastPartOfUrl == null || $lastPartOfUrl == "" || $parts ){
		   $giantStepReleaseId = $parts;
		   if ($giantStepReleaseId != null && $giantStepReleaseId != "releases"){
				//echo "<br> <br><h1>In the null area, the releaseId is </h1>".$giantStepReleaseId;
				get_template_part("page", "releases-detail");
			}else{
				//echo "<br> <br><h1>In the null area, no releases id</h1> "; 
				get_template_part("page", "releases1");
			}
		}else{
			$giantStepReleaseId = getValueFromEndOfArraySafely($parts,0);
			if ($giantStepReleaseId != null){
				//echo "In the releases detail page, the $artId is ".$giantStepReleaseId;
				// assume we have a detail page
				get_template_part( "page", "releases-detail" );
			}
		}
	}
/*########################################
######## START EVENTS SECTION ##########
########################################*/
function handleEventsPage($url)
	{
		global $giantStepReleaseId;
				
		// we're only dealing with releases here
		if (strpos($url,"/index.php/events")){
			return;
		}
		
		$parts = end(array_filter(explode('/',$url)));
		$lastPartOfUrl = $parts;
	
		/*
		echo "This is the url:".$url."<br>";
		echo "<br> <br> the last part of url is:".$lastPartOfUrl."<br>";
		echo "This is the parts:".$parts."<br>";
		echo "<pre> This is the parts variable ";
			echo print_r($parts);
		echo "</pre>";
		*/
		
		if ($lastPartOfUrl == null || $lastPartOfUrl == "" || $parts ){
		   $giantStepEventsId = $parts;
		   if ($giantStepEventsId != null && $giantStepEventsId != "events"){
				//echo "<br> <br><h1>In the null area, the releaseId is </h1>".$giantStepReleaseId;
				get_template_part("page", "events-detail");
			}else{
				//echo "<br> <br><h1>In the null area, no releases id</h1> "; 
				get_template_part("page", "events");
			}
		}else{
			$giantStepReleaseId = getValueFromEndOfArraySafely($parts,0);
			if ($giantStepReleaseId != null){
				//echo "In the releases detail page, the $artId is ".$giantStepReleaseId;
				// assume we have a detail page
				get_template_part( "page", "events-detail" );
			}
		}
	}
?>

	<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
	
		<h2 id="post-<?php the_ID(); ?>"><?php the_title(); ?></h2>
		
			<div class="entrytext">

				<?php
				
					// Code to handle Giant Step Artists, Events and Releases
			
					$url = $_SERVER["REQUEST_URI"];
					handleArtistPage($url);
					handleReleasePage($url);
					handleEventsPage($url);
                     //uncomment this to determine if page.php is being called (look at the end of the page)
					 //echo "<h1>getting ready to die...</h1>";
					 //,die();
				
				?>
				
				<?php the_content('<p class="serif">Read more &raquo;</p>'); ?>
	
				<?php wp_link_pages(); ?>
				<hr>

				<?php endwhile; endif; ?>
        		</div>

<?php get_footer(); ?>

Open in new window

0
LZ1
Asked:
LZ1
  • 12
  • 10
  • 3
  • +1
1 Solution
 
Julian HansenCommented:
No problems here - what if you change the function name to xstartsWith()
0
 
LZ1Author Commented:
Same thing.

I should probably point out this is a Wordpress site and the file in question is page.php. Not sure if that makes a difference. I'm guessing my code is being gone over several times before anything is loaded.
0
 
Derek JensenCommented:
I'm with Julian; have you tried something like this?
function startsWith($str, $searchStr, $case=true)
{
    if ($case) {
        return (strpos($str, $searchStr, 0) === 0);
    }
    return (stripos($str, $searchStr, 0) === 0);
}

Open in new window


It's amazing what a few curlys can do! ;-)

...If that doesn't get the job done, have you considered using a more...OOP-friendly approach??

class Find
{
    static function yescase ($str, $needle, $offset) { return strpos($str, $needle, $offset); }
    static function nocase ($str, $needle, $offset) { return stripos($str, $needle, $offset); }
}

// meanwhile, somewhere in PHP-land...
$caps = ($case) ? 'yescase' : 'nocase';
// ...elsewhere in PHP-land...or not...
$isCapital = Find::$caps($str, $otherStr);

Open in new window

It may seem like overkill for this particular problem(and it is!), but it is infinitely more expandable(and faster!) than your original function. :)
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LZ1Author Commented:
Thanks for the input bigdogdman. However, I'm confused.  I replaced my current function with what you had in your first code block.  Same thing.

Now I want to try your second solution, but am uncertain as to where it goes?  Do I just paste it over the old function?
0
 
LZ1Author Commented:
Ok, so here's the thing I just discovered. If I move the last function to be the first function, then go to that page, I only have 1 error in my log.

However, if I have that same function as the last function, I get 2 errors in my log.

It seems like it's reiterating over the code multiple times depending on what function is being called.

Thoughts?
0
 
Julian HansenCommented:
is page.php part of an include or require statement in another file - if so if you change that to require_once - does the problem go away?
0
 
Derek JensenCommented:
Try what Julian said, and if that doesn't work...then let me ask you this:

Is there a particular reason you're making it so convoluted? You're only calling startsWith once, and you're passing it a static string. There's no variances or other variables that it's dealing with, so...if you're *just* looking for 'artists' in the URI(or *any* variable or static string), case is not going to matter 99% of the time. And the other 1%...is easy to fix when/If it's encountered. :) Just use strstr or preg_match or one of a dozen other PHP funcs that accomplish the same thing and be done with it. ;-)
0
 
Ovid BurkeCreative DirectorCommented:
PHP Fatal error:  Cannot redeclare startsWith() (previously declared in /wp-content/themes/mountain-dawn/page.php:9) in /wp-content/themes/mountain-dawn/page.php on line 15

That kind of error would seem to suggest that you have somehow defined the same function twice, or it might be two functions with the same name. I would suggest you check your functions.php file to see if a function by that name exists there, or maybe in one of your plugins if you have those installed.

As a test... wrap your function in a conditional statement like follows, and see if it works as intended.
if( ! function_exists( 'startsWith' ) )
{
	function startsWith($str, $searchStr, $case = true)
	{
	   if($case) {
		  return strpos($str, $searchStr, 0) === 0;
	   }
	   return stripos($str, $searchStr, 0) === 0;
	}	
}

Open in new window

0
 
Julian HansenCommented:
@madaboutasp,
That kind of error would seem to suggest that you have somehow defined the same function twice, or it might be two functions with the same name. I would suggest you check your functions.php file to see if a function by that name exists there
I believe that has already been dealt with - by adding an 'x' to the function name as suggested above problem persists - refer first two comments.
0
 
Derek JensenCommented:
...so, to reiterate what I've already suggested--beating a dead horse, I know--but have you tried eliminating that function entirely and just using strstr or preg_match(my personal favorite) instead? I'm certain this will fix the problem--or at least get us past this annoying redeclare error...
0
 
LZ1Author Commented:
@bigdogman:
Can you show me how to use strstr and preg_match? I'm still kind of learning PHP and haven't gotten to learn those functions yet.
0
 
LZ1Author Commented:
@madaboutasp: I did try your solution too. All it's doing is redeclaring all my other functions on the same page.

For some reason, it seems like it's reiterating over the page multiple times. Do I have to completely refactor my code?
0
 
Derek JensenCommented:
Absitively posolutely! :-)

Okay so you can go to php.net and look up strstr--better make it stristr(case-insensitive)--and preg_match to learn the syntax & what they return(feel free to peruse all the other tasty functions PHP has to offer :)), but they're both fairly similar to stripos:
stristr($haystack, $needle);
    stristr($url, "index.php/artists");

Open in new window

preg_match($needle, $haystack);
    preg_match("/index\.php\/artists/i", $url);

Open in new window


...you see, the reason I recommend against using strpos & stripos is because 1. they're slower(than strstr & stristr) and 2. they can return a value that equates to false(if you don't use ===). preg_match is the same way, but...usually you're not specifically looking for an error(preg_match()===false means an error occurred).

Now, how preg_match works is like this: (skip to the end if you know regexes already)
The reason it looks all funky is because preg_match accepts a regular expression, or regex.
Now, I specifically used "/" for a reason: it is the universal boundary marker, or "delimiter" for regexes, but it can be anything, like so:
preg_match("#index\.php/artists#i", $url);

Open in new window

The "i" at the end just means ignore case.
The "\" is called the "escape character." It tells the regex to treat the character immediately following it as a literal, instead of performing the reserved/special function it would otherwise serve without it. A period in a regex(not preceded by a backslash) matches any character, e.g. preg_match("/index.php/",$url); would return true if $url contained in it the string "indexgphp" or "index!php", etc...
That's why the "\/" in the very first preg_match, so as to not trigger the end of the regex prematurely(causing an error). :) If you had a # in your regex, and were using # as your delimiter, you'd have to escape that as well.
Confusing, I know...just roll with it. :)

So, long story short, your code might look like this:
		if (!preg_match("/index\.php\/artists/i",$url))
		{
			// uri doesn't start with artists...

Open in new window

0
 
LZ1Author Commented:
I think I'm getting it now bigdogdman.  However, I'm probably still quite a ways off.
If I want to match on a number inside the URL then what?  Our URLs are formed like this:

http://mydomain.com/index.php/artists - This will return all the artists
http://mydomain.com/index.php/artists/2108 - This will return artist number 2108
http://mydomain.com/index.php/artists/2108/bio - This will return artist 2108 bio

Could you show me a little more of the code? Maybe for the "Releases" section?
0
 
LZ1Author Commented:
This is what I have started for artists:

						$url = $_SERVER["REQUEST_URI"];
						$parts = explode('/',$url);
						$lastPartOfUrl = end($parts);
					
						if (preg_match("/index\.php\/releases/i",$url)){
							// uri does start with artists...
							get_template_part( "page", "releases1");
						}elseif (preg_match("/index\.php\/releases/".$parts[3]."i",$url)){
							get_template_part( "page", "releases-detail");
						}

Open in new window


EDIT: I meant releases. It works for the releases1 page, but not the detail page
0
 
Derek JensenCommented:
Yeah, it's nearly there; you're just ending the regex prematurely. Put the last forward slash right before the 'i' & put a backslash in front of the slash after releases...see this is why they'll often use a different regex delimiter when searching URLs so they don't have to worry about escaping everything properly.

And sorry for the lack of example code; I'm on my mobile & it doesn't show the code *and* the text at the same time. :-P
0
 
Derek JensenCommented:
Also, capturing groups is a big part of regexes; say you wanted to capture the number and use it directly. All you'd have to do is something like this:
preg_match("/(\d+)/",$url,$matches);
$number = $matches[1];
0
 
LZ1Author Commented:
Still kind of confused...........

Put the last forward slash right before the 'i' & put a backslash in front of the slash after releases

There's no 'i' there near a slash?
0
 
Derek JensenCommented:
Sorry about that; this should be clearer:

elseif (preg_match("/index\.php\/releases/".$parts[3]."i",$url)){
here's where the regex was terminated--^                        ^-and it should be terminated here

elseif (preg_match("/index\.php\/releases\/".$parts[3]."/i",$url)){

Open in new window


You also should have it escape slashes within $parts[3], but you don't have to, unless you run into problems down the road. :)
0
 
LZ1Author Commented:
$parts[3] doesn't contain any slashes though so hopefully I'm safe with that.

So that worked for the first part.  But the elseif isn't working correctly........Any idea why?
0
 
LZ1Author Commented:
So this is my final code I'd like to use.  

Let me know about this.  It seems that the $parts[3] isn't getting called or at least it's not getting into that part.

Plus I may have one more question, which I can open another question here about the /bio section for artist.

						##############START ARTISTS##############
						if (preg_match("/index\.php\/artists/i",$url)){
							get_template_part( "page", "artist-listing");
						}elseif (preg_match("/index\.php\/artist\/".$parts[3]."/i",$url)){
							get_template_part( "page", "artists");
						}elseif (preg_match("/index\.php\/artist\/".$parts[3]."/i",$url)){
							get_template_part( "page", "artists-bio");
						##############START RELEASES##############
						}elseif (preg_match("/index\.php\/releases/i",$url)){
							get_template_part( "page", "releases1");
						}elseif (preg_match("/index\.php\/releases\/".$parts[3]."/i",$url)){
							get_template_part( "page", "releases-detail");
						##############START EVENTS##############
						}elseif (preg_match("/index\.php\/events/i",$url)){
							get_template_part( "page", "events-listing");
						}elseif (preg_match("/index\.php\/events\/".$parts[3]."/i",$url)){
							get_template_part( "page", "events-detail");
						}

Open in new window

0
 
Derek JensenCommented:
Which elseif? What is the contents of $parts?
0
 
LZ1Author Commented:
Sorry about that.

$parts[3] = number in text form

The first part for "artists".

http://mydomain.com/index.php/artists - This will return all the artists
http://mydomain.com/index.php/artists/2108 - This will return artist number 2108
http://mydomain.com/index.php/artists/2108/bio - <<<<<This part isn't working.
0
 
Derek JensenCommented:
Well, right off the bat I see a couple problems(and I'm fairly certain $parts[3] does not contain the number).

First of all, there's no need for $parts[3] in the preg_match. You're exploding $url by slash, and then searching for part of it. Do you see the problem?
Secondly, there's no need for all these ifs/elseifs. Simply modify your get_template_part function to accept part of $parts as a parameter, and do your checking inside there(probably in a switch statement or something).

However, I don't mean to make it more confusing, so let's just get working what's already there.
The first problem I see is, you have it all backwards. It's never getting to the last elseif(and thus why it's not working). It should look more like this:

Now, I know this is confusing, but let's just try it. Trust me, it'll make it a lot less confusing in the long run:
if (preg_match("@/artist/\d+/bio@i",$url)){    // There's no need to test for index.php if it's always going to be there
	get_template_part( "page", "artists-bio");
}elseif (preg_match("@/artist/\d+/?$@i",$url)){
	get_template_part( "page", "artists");
}elseif (preg_match("@/artists@i",$url)){
	get_template_part( "page", "artist-listing");
}

Open in new window

And that goes for the releases and events tests as well.
Start with your most specific test; otherwise, it'll never get that far. :)

There may be no need for $parts[3] in the preg_match, but that doesn't mean we have to do away with it entirely. Instead, let's try doing away with the preg_matches entirely! You could restructure your if test to look something like this:
$partsSize = sizeof($parts);
switch ($parts[3]) {    // $parts[3] *should* contain the "artists/releases/events" part...
    case "artists":
        if ($partsSize > 5) {
            // This means we *might* have something after the number(like maybe a slash at the end w/nothing after it...?)
        }elseif ($partsSize > 4) {
            // This means we *might* have a number, so check for it! :)
        }else{
            // do whatever here...
        }
    break;
    case "releases":
        // Same thing as above...
    break;
    case "events":
        // Same thing as above...
    break;
}

Open in new window


...As much as I Love regexes and any excuse to use preg_match, I'm also a realist. preg_match is computationally expensive. So I first look for any excuse not to use it. :-)
0
 
LZ1Author Commented:
I think I learned more in this one question than I have in the past 2 years using PHP.

Thanks so much for your help.
0
 
Derek JensenCommented:
Wow, what a compliment! I'm glad I could help! :-)
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 12
  • 10
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now