3

I'm writing a script that will select a random word from among words in an input file, multiple times. Now calling file() multiple times seems inefficient, so I'm thinking of having a global array for the words from the file and a function that will load the file into the array (called before selecting random words). Why doesn't it work?

global $words;

function init_words($file)
{
    $words = file($file);
    $count = count($words);
    echo "$count words<br>\n"; // "3 words"
}

init_words("/foo/bar");
$count = count($words);
echo "$count words<br>\n"; // "0 words" 
Chico
  • 45
  • 1
  • 3
  • The semantics in PHP are a bit different. Global variables aren't what they are in C for example. They need to be invited into the function scope. – mario Mar 30 '11 at 22:05
  • *(related)* [PHP Global in Functions](http://stackoverflow.com/questions/5166087/php-global-in-functions) – Gordon Mar 30 '11 at 22:22

5 Answers5

5

You need to declare $words global within the function itself. See:

$words = '';

function init_words($file)
{
    global $words;
    $words = file($file);
    $count = count($words);
    echo "$count words<br>\n"; // "3 words"
}

I suggest you review the variable scope chapter in the PHP manual.

As an aside I would never write this code in this way. Avoid globals unless they are absolutely necessary.

I would write your code this way to avoid this problem:

function init_words($file)
{
    $words = file($file);
    $count = count($words);
    echo "$count words<br>\n"; // "3 words"
    return $words;
}

$words = init_words("/foo/bar");
$count = count($words);
echo "$count words<br>\n"; // "3 words" 

Please see the returning values chapter in the PHP manual for more information on this.

Treffynnon
  • 21,365
  • 6
  • 65
  • 98
  • 1
    This. `global` works differently then what most people expect in PHP. It doesn't define a variable as global scope, instead it says that "for the following scope, I want to use the global version of [var], not a local one." – Mr. Llama Mar 30 '11 at 22:02
2
$words = null;

function init_words($file)
{
    global $words;
    $words = file($file);
    $count = count($words);
    echo "$count words<br>\n"; // "3 words"
}

init_words("/foo/bar");
$count = count($words);
echo "$count words<br>\n"; // "0 words" 

The global part should go inside your function

side note: it is not always the best to use global operators

Naftali
  • 144,921
  • 39
  • 244
  • 303
2

You want global $words; inside the function. Better yet, use the superglobal $GLOBALS.

phihag
  • 278,196
  • 72
  • 453
  • 469
  • [Variable scope](http://php.net/manual/en/language.variables.scope.php): Note: Using global keyword outside a function is not an error. It can be used if the file is included from inside a function. – Jared Farrish Mar 30 '11 at 22:01
  • @Jared Oh, of course, bad choice of words by me. Updated. – phihag Mar 30 '11 at 22:02
  • @phihag $GLOBALS has got to be the best way of using a global variable inside a function. mitigates spagetti code. something tells me php wants to enforce OO programming. :) – dewd Jan 13 '14 at 15:42
0

first you need to store the words in a serialised formant so that means

$file_location = "/foo/bar/words.txt";
$words = array("game", "cool", "why");
$words = serilize($words);
write_words_file($words, $filelocation); //Create the function so it can write to a file

then you will need to edit your init_words

function init_words($file)
{
    global $words;
    $data = file_get_contents($file);
    $words = unserialize($data);
    $count = count($words);
    echo "$count words<br>\n"; // "3 words"
}

init_words("/foo/bar/words.txt");
$count = count($words);
echo "$count words<br>\n"; // "0 words" 
Vish
  • 4,508
  • 10
  • 42
  • 74
  • Why do they need to be serialized? The `file()` method the OP is using turns each new line in a file into a item in an array. There is no need for serialisation. – Treffynnon Mar 30 '11 at 22:06
  • then you dont need to serialize it. – Vish Mar 30 '11 at 22:12
0

Alternately, you could use the following and avoid usage of global altogether:

function init_words($fname)
{
    $w = file($fname, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);  // We don't want the trailing spaces or empty lines.
    $c = count($w);

    return array($w, $c);
}

list($words, $count) = init_words("Some_File.txt");

In such a situation if you ever had to do any manipulation of the list of words, you can handle it all within init_words() as opposed to elsewhere in the script.

Mr. Llama
  • 20,202
  • 2
  • 62
  • 115