What would be the simplest way to do this in php?

14 replies
Setup a webpage so that it...

Redirects to one URL 50% of the time
Redirects to another URL the other 50% of the time

Can php recognize successive visits to a webpage and split up the redirects based on that, or would it have to be done based on absolute times? (ie redirect to URL "A" one minute, then redirect to URL "B" the next minute, etc etc).
#php #simplest
  • Profile picture of the author POWERCENTER
    Code:
    %URL1 = 'hXXp://xxw.site1.com';
    %URL2 = 'hXXp://xxw.site2.com';
    
    %INT_RAND = MT_RAND(1,2);
    
    IF (%INT_RAND == 1){
        
        header("Location: %URL1");
        
    } ELSEIF (%INT_RAND == 2){
        
        header("Location: %URL2");
        
    }
    Obviously, so that I could post here i replaced the $ with % and part of the URLs with xx's. I am just picking a random number (1 or 2), then redirecting based on whichever number is picked.

    Thats the easier way to do it, but it won't be exactly 50% because it's random. If you need a perfect 50/50 split, you'll need to make a counter (store that info in a database).
    {{ DiscussionBoard.errors[252640].message }}
    • Profile picture of the author Brandon Tanner
      Hi POWERCENTER,

      Thanks for the reply. I was wondering what hxxp meant, lol.

      I know of the random function, but it will need to be a fairly even 50/50 split, so I don't think that would be the best option.

      I'm fairly new to php, so I'm not sure how I would go about doing the counter/database thing.

      I'm wondering if it might be better to just do it based on absolute time? For example, any visitors that came to the page during the 1st 30 minutes of each hour would get redirected to link "A", while any visitors that came to the page during the last 30 minutes of each hour would get redirected to link "B". I think that would work out to be pretty even over the course of a day.

      Again I'm pretty new at this, so I'm not sure if the code below would even work. But maybe you can see what I'm aiming for here and let me know if there's any mistakes...

      ///////////////////////////////////

      $URL1 = 'http://www.site1.com';
      $URL2 = 'http://www.site2.com';

      $TIME = date(i);

      IF ($TIME == <31){

      header("Location: $URL1");

      } ELSEIF ($TIME == >30){

      header("Location: $URL2");

      }

      /////////////////////////////////

      Thanks!
      Signature

      {{ DiscussionBoard.errors[252763].message }}
  • Profile picture of the author xanol
    rand(1,2) will work fine...
    Over time it will it will average out very close to 50/50.

    You could also keep track of a counter in a file. Read the number, and if ($num mod 2 == 0) goto offer 1, otherwise to offer 2. Before you redirect, increment $num and write it back out to the file. If you have more than two offers, this logic needs to be adjusted though... Good luck.
    {{ DiscussionBoard.errors[253244].message }}
  • Profile picture of the author -Nick-
    Just use 1 flag in a file.

    Read the file contents......

    If 1 then redirect to site one and write 2 to the file.
    If 2 then redirect to site two and write 1 to the file.

    Tick tock tick tock..... see saw
    Signature

    For Tips and Tricks Webmaster Blog | For Latest Check Software Downloads

    {{ DiscussionBoard.errors[253900].message }}
    • Profile picture of the author Brandon Tanner
      xanol and Nick...

      I appreciate the help, but I have no idea how to implement what you're suggesting. Could you maybe give me some example code?

      Thanks
      Signature

      {{ DiscussionBoard.errors[254731].message }}
  • Profile picture of the author Plinko
    Hi Brandon,

    Using the random functions aren't great. I generate test data for applications and I recently did one where I had the system enter 5000 people into a database with ages between 16 and 50. You would be surprised how many times the number 43 came up. Sometimes back to back.

    But Nick has it down pat. This can be solved with a simple flag (or sentinel). File is the way to go. Database connects are long and expensive and if the database goes down you show neither page.

    Here's a solution which I learned about many years ago from the book "Web Application Development with PHP 4.0." It uses a technique called polymorphism, or self modifying code. This isn't strictly necessary as you could use a separate file, but I present it here because I find it interesting.

    <?php
    $counter = 0;
    /* Don't modify above this line */

    $URL_ARRAY = array(
    0 => 'http://someurl1',
    1 => 'http://someurl2'
    );

    // if counter is 0 above, then set it to 1 for next time
    // otherwise if any other number, set back to 0
    if ($counter == 0)
    {
    $new_counter = 1;
    }
    else
    {
    $new_counter = 0;
    }

    // write the new value of $counter to this file
    $file = fopen(basename($PHP_SELF), "r+");
    fputs($file, "<?php\n\$counter = $new_counter;");

    // perform your redirect using orig value of $counter
    header('Location: ' . $URL_ARRAY[$counter]);

    ?>

    There you go. Untested but give it a try. It also gives you the ability to add more urls or change the logic if you like. In short this script does:

    - sets the counter for this session (0 or 1)
    - assigns your URLs to an array
    - sets the new counter for next session (1 or 0)
    - writes the new counter back to the same file for next time
    - performs the redirect using the original value of counter

    Hope this helps.
    {{ DiscussionBoard.errors[256130].message }}
    • Profile picture of the author Brandon Tanner
      Originally Posted by Plinko View Post

      Hi Brandon,

      Using the random functions aren't great. I generate test data for applications and I recently did one where I had the system enter 5000 people into a database with ages between 16 and 50. You would be surprised how many times the number 43 came up. Sometimes back to back.

      But Nick has it down pat. This can be solved with a simple flag (or sentinel). File is the way to go. Database connects are long and expensive and if the database goes down you show neither page.

      Here's a solution which I learned about many years ago from the book "Web Application Development with PHP 4.0." It uses a technique called polymorphism, or self modifying code. This isn't strictly necessary as you could use a separate file, but I present it here because I find it interesting.

      <?php
      = 0;
      /* Don't modify above this line */

      = array(
      0 => 'http://someurl1',
      1 => 'http://someurl2'
      );

      // if counter is 0 above, then set it to 1 for next time
      // otherwise if any other number, set back to 0
      if ( == 0)
      {
      = 1;
      }
      else
      {
      = 0;
      }

      // write the new value of to this file
      = fopen(basename(), "r+");
      fputs(, "<?phpn = ;");

      // perform your redirect using orig value of
      header('Location: ' . );

      ?>

      There you go. Untested but give it a try. It also gives you the ability to add more urls or change the logic if you like. In short this script does:

      - sets the counter for this session (0 or 1)
      - assigns your URLs to an array
      - sets the new counter for next session (1 or 0)
      - writes the new counter back to the same file for next time
      - performs the redirect using the original value of counter

      Hope this helps.

      Hi Plinko,

      I appreciate the help, but I plugged in that code and got 3 error messages...

      Warning: fopen(redirect.php) [function.fopen]: failed to open stream: Permission denied in /home/svrsvr/public_html/redirect.php on line 22

      Warning: fputs(): supplied argument is not a valid stream resource in /home/svrsvr/public_html/redirect.php on line 23

      Warning: Cannot modify header information - headers already sent by (output started at /home/svrsvr/public_html/redirect.php:22) in /home/svrsvr/public_html/redirect.php on line 26

      Any ideas? I didn't change anything in the code, except the 'someurls' to real URL's. Was I suppose to change something else too?

      Thanks
      Signature

      {{ DiscussionBoard.errors[257123].message }}
  • Profile picture of the author Plinko
    Hi Brandon,

    The file you are trying to write cannot be written by your webserver because it doesn't have permission. You created it as your shell account user (you) but the webserver runs under a different account and is prevented from changing your file.

    If you are using Linux, change the permissions like this:

    chmod 0666 filename.php

    And replace filename with the actual name of your script. Hope that helps.
    {{ DiscussionBoard.errors[257139].message }}
    • Profile picture of the author Brandon Tanner
      Originally Posted by Plinko View Post

      Hi Brandon,

      The file you are trying to write cannot be written by your webserver because it doesn't have permission. You created it as your shell account user (you) but the webserver runs under a different account and is prevented from changing your file.

      If you are using Linux, change the permissions like this:

      chmod 0666 filename.php

      And replace filename with the actual name of your script. Hope that helps.
      Hey Plinko,

      Just changed permissions. Down to just 1 error message now...

      Parse error: syntax error, unexpected '=' in /home/svrsvr/public_html/redirect.php on line 2

      I'm a php noob, but shouldn't there be a string or something before some of the 'equals' operators?
      Signature

      {{ DiscussionBoard.errors[257350].message }}
  • Profile picture of the author Plinko
    Take a look at post #7.

    In line 2 there is a variable assignament that reads:

    $counter = 0;

    But in your replay to me it looks like most of the variable names are gone. Take a look at your reply in post #8 and you'll see they are ALL missing for some reason. Line 2 there just reads:

    =0;

    Odd. Try copying from post #7 again.
    {{ DiscussionBoard.errors[257469].message }}
    • Profile picture of the author Brandon Tanner
      Originally Posted by Plinko View Post

      Take a look at post #7.

      In line 2 there is a variable assignament that reads:

      = 0;

      But in your replay to me it looks like most of the variable names are gone. Take a look at your reply in post #8 and you'll see they are ALL missing for some reason. Line 2 there just reads:

      =0;

      Odd. Try copying from post #7 again.
      Hey Plinko,

      That was it! Works perfectly now.

      It appears that the strings got stripped out somehow in my reply, and that's the code I was trying to use. Don't know how that happened.

      Anyways, it's all good now. Thanks so much for your help!

      BTW- do you do any custom developing? Shoot me a PM if you do. I've got a small php project that I'll need to hire someone for soon.
      Signature

      {{ DiscussionBoard.errors[257516].message }}
  • Profile picture of the author Plinko
    Great! Glad it works as prescribed, and glad I could help.

    Enjoy!
    {{ DiscussionBoard.errors[257590].message }}
  • Profile picture of the author faverr
    A word of caution when using a file. If two visitors hit your site at nearly the same time, two processes can end up writing to the file at the same time, and you might get unexpected results. This is actually a harder problem to solve using a file than appears at first blush.
    {{ DiscussionBoard.errors[258800].message }}
  • Profile picture of the author Plinko
    Yes, file locking can be an issue. But given the circumstances it is probably better than the other options. A database connect is too expensive and must be performed on each page load. rand() functions have no way of splitting results evenly, especially with only two values. SQLlite is an option if installed with PHP.

    You can put in logic to see if the file is available for writing and so forth. flock() would make sure the file is locked, but it doesn't work on an NFS system like most hosts use. Anyone trying to refresh a file edited over NFS may have run into the kinds of problems this presents.

    Ultimately if I knew the shared memory functions were available on a system I would write a single bit flag into memory and use that. But the solution above would suffice most situations unless you were getting multiple connections per microsecond regularly.
    {{ DiscussionBoard.errors[259379].message }}

Trending Topics