Am I on the right track with this random number array?
Just a little detail, to kick off: you're not declaring $products as an array anywhere. PHP will create a new variable, and assign it an empty array for you, true enough, but if you change your ini settings to E_STRICT | E_ALL, you'll notice that it doesn't do this without complaining about it.
It's always better to declare and initialize your variables beforehand. writing $products = array(); isn't hard, nor is it very costly. At any rate it's less costly than producing a notice.

Anyway, about your actual code: There is room to make your code more efficient way, so let's look at it piecce by piece:

function randomnumber(){
    $randomnumber = mt_rand(1, 10);
    return $randomnumber;
}


This function is just calling mt_rand, and returning the result. But only after the return value of mt_rand has been assigned to a local variable. That's just wasteful. Look at it from a machine's standpoint:

randomnumber();//call &lt;name:randomnumber&gt;
  \\
   \==&gt; lookup function in memory, goto, and start
   $randomnumber = mt_rand(1,10);
     \\                   \\
      \=&gt; allocate memory  \=&gt; lookup function, pass 2 arguments &amp; call
        ||     /\                                                 //
        ||     ||=======then, assign return valueof: =============/
        ||
        \== return COPY of assigned value
            then flag $randomnumber for GC (Garbage Collection)


That's just a hell of a lot of work, for a simple call to mt_rand. You can easily omit the allocation and garbage collection steps by changing the randomnumber function to this:

function randomnumber()
{
    return mt_rand(1,10);
}


This does exactly the same thing, without the overhead of an assignment. Still, a function call that just calls another function is a bit silly. If anything, it's an alias to an existing function, with default params. But you're still returning a copy of the return value of the core function (mt_rand). Just ditch the function, and in-line mt_rand(1,10);
If you insist, keep the alias, but define default arguments:

function randomnumber($from = 1, $to = 10)
{
    $from = (int) $from;//make sure we're dealing with ints
    $to = (int) $to;
    if ($from &gt; $to)
    {//check order of params
        $tmp = $from;
        $from = $to;
        $to = $tmp;
    }
    return mt_rand($from, $to);
}
randomnumber();//returns mt_rand(1,10)
randomnumber(10,20);//returns mt_rand(10,20)
randomnumber(200);//returns mt_rand(10, 200)
randomnumber(null, 5);//returns mt_rand(0,5)


But that's only of any use if you're going to use this alias function throughout, and don't want to bother passing those 2 arguments all the time, or (in case of passign variables) you're not sure what they might contain (null, 'a string', (float) '0.123',...).
But we're drifting off topic. Next, the array-constructing loop:

//Creates array.
//Checks to see if the random number is greater than 1
//Adds an 's' to the entry if greater than one
for ($i = 0; $i &lt; 10; $i++){
        $rannum = randomnumber();
        if ($rannum &gt; 1){
            $adds = "s";
        }else{
            $adds = "";
        }
        $products[$i] = $rannum." car".$adds;
}


This isn't too bad, really, just remove the function-call, and you're good, and perhaps shorten the if-else to a ternary or a single if-statement. you could argue that assigning the random number to a variable isn't really necessairy. You're using $i as an array-key, so you could assign the value to the array directly, and check the value there

for($i=0;$i&lt;10;$i++)
{
    $products[$i] = mt_rand(1,10);//$i is the key, so we don't need any other vars
    $products[$i] .= 'car '.($products[$i] &gt; 1 ? 's' : '');
}
//without ternary:
for($i=0;$i&lt;10;$i++)
{
    $products[$i] = mt_rand(1,10).' car';//just concat car already
    if ($products[$i] &gt; 1)
    {//comparing to int will cast $products[$i] to int
     //since the string starts with an int, it'll compare that int
     //'4 car' &gt; 1 ~~&gt; 4 &gt; 1 ~~&gt; true ==&gt; '4 car' .= s ===&gt; 4 cars
        $products[$i] .= 's';
    }
}


Then, the output loop:

//Outputs the final array.
foreach ($products as $current){
    echo $current."&lt;br /&gt;";
}


Ok, that's perfectly valid code, too, but wouldn't it be a lot shorter just writing this:

echo implode('&lt;br/&gt;', $products);


This turns an array into a string, and separates all values with a &lt;br/&gt;. To add another break at the end (and/or beginning) of this string:

echo '&lt;br/&gt;', implode('&lt;br/&gt;', $products), '&lt;br/&gt;';


I use this all the time if I want to dump a quick &lt;ul&gt; to the screen:

echo '&lt;ul&gt;&lt;li&gt;', implode('&lt;/li&gt;&lt;li&gt;', $array), '&lt;/li&gt;&lt;/ul&gt;';


So, your code ends up looking like:

for($i=0;$i&lt;10;$i++)
{
    $products[$i] = mt_rand(1,10);//$i is the key, so we don't need any other vars
    $products[$i] .= 'car '.($products[$i] &gt; 1 ? 's' : '')
}
echo implode('&lt;br/&gt;', $products);


Or, if regexes don't scare you and you like some unmaintainable code, you could even do this:

$arr = array();
$i=0;
while($i++&lt;10)
{
    $arr[] = mt_rand(1,10);
}
echo preg_replace('/(([2-9]+|10)\s+car)(?!s)/','$1s',implode(' car&lt;br/&gt;',$arr).' car');


But that's just terrible code to maintain... 

If the array you're echo-ing isn't of any use to you except for your printing it out, you could just as well drop the array:

for($i=0, $j=mt_rand(1,10);$i&lt;10;$i++, $j=mt_rand(1,10))
{
    echo $j, ' car', $j &gt; 1 ? 's' : '', '&lt;br/&gt;';
}


Which, if you're a massochist, you can turn into a one-liner quite easily:

for($i=0, $j=mt_rand(1,10);$i&lt;10;$i++, $j=mt_rand(1,10))  echo $j, ' car', $j &gt; 1 ? 's' : '', '&lt;br/&gt;';


As you can see, I'm using $i to count the number of iterations, while at the same time $j is (re-)assigned a new random value upon each iteration, too.
Using multiple variables in a for-loop construct is most commonly done to avoid calling count too much when for-looping a numerically indexed array:

for($i=0, $j = count($array); $i&lt;$j;$i++)
{
    var_dump($array[$i]);
}


instead of:

for($i=0;$i&lt;count($array);$i++)
{
    var_dump($array[$i]);
}


Both of the loops above behave in the same way (provided $array doesn't change inside the loop), but the first one is more performant, because, as you probably know, after each iteration the conditional expression (ie $i&lt;$j or $i&lt;count($array)) is evaluated. In the second case, this means the length of $array will be counted time and time again, whereas in the first case, this is only done once.