Please send questions to st10@humboldt.edu .

PHP and Files...

*   how? well, PHP is server-side -- it can read/write files on
    the server side (with some limitations/issues, as we'll discuss)

*   Two sources/references:

    W3Schools PHP tutorial has a bit on file commands
    (www.w3schools.com/php/php_file.asp)

    Sklar's "Learning PHP 5", Chapter 10: Working with Files

*   FIRST: how do you OPEN a file in PHP?

    with a function, fopen

    *   fopen takes 2 arguments: 

        *   a string representing the name of the file to be opened

        *   a string representing the mode -- WHAT action you plan
            to do to the opened file

    *   fopen returns a "thing" --- in some languages you'd call
        it a file, in some languages you'd call it a stream, in
	some languages you'd call it a file handle ---

	but you then USE this "thing" to be able to act on the
        opened file.

	(I'll use the term "file handle" for the rest of tonight)

        *   what if fopen FAILS? it happens to return 0 (which can
            be interpreted by PHP as false in an if, or a while,
	    or a for, or an "x or exit" or "x or die" construct)

    *   AND: as you use this file handle, it maintains a pointer/
        cursor/something keeping track of WHERE you currently are
	within the file...

	(and this pointer/cursor is moved by file functions, as we'll
	see)

*   What are some of the available modes for fopen?

    "r"	 - reading - and starts with the pointer/cursor pointing
           at the beginning of the file

    "r+" - reading/writing [yes, both?!] - and starts with the pointer
           /cursor pointing at the beginning of the file

    "w"  - write only. Opens and CLEARS CONTENTS of file (yes, the
           current contents are NUKED and GONE!) - and if the file
	   doesn't exist, a new file is created (and pointer/cursor
           is ready to write at the beginning)

    "w+" - reading/writing [yes, both?!] - BUT opens AND CLEARS CONTENTS
           of file, and if the file doesn't exist, a new file is
	   created (and pointer/cursor is ready to write/read at the 
           beginning)

    "a"  - appending. Opens the file, sets pointer/cursor to the
           end of the current contents, ready to write at the end;
	   and if the file doesn't exist, a new file is created
           (and pointer/cursor is ready to write at the beginning) 

    "x"  - writing, BUT it creates a new file, and returns false
           AND an error if the file happens to exist

    "x+" - reading/writing, BUT it creates a new file, and returns false
           AND an error if the file happens to exist

*   and what thou OPENS, thou should CLOSE ---

    fclose should be used to close a file handle you have opened with
    fopen ---

    it takes the file handle as argument;

    $fileHandle = fopen("myFile.txt", "r") or exit("Oh no! couldn't open!");

    ...

    fclose( $fileHandle );

*   a first (very simple) example:   files1.php

*   now that it is OPENED for reading (or whatever) --- what are some
    of my options for doing things with it?

    fgets - lets you grab a single line from a file

    *   its argument: the file handle that allows reading

    *   it returns the current line as a string,
        and it moves the pointer/cursor to the next line

    *   but --- how do you know when to stop?

    feof - lets you know if the pointer/cursor is at the end-of-file

    *   its argument: the file handle

    *   returns true if you're at the end of file for that file handle

*   SO: note that these can be used in a classic "loopy" way to walk
    through the lines of a file:

    $fileHandle = fopen("myFile.html", "r")
        or exit("Cannot open myFile.html");

    while (! feof( $fileHandle ) )
    {
        $nextline = fgets( $fileHandle );
        print "<h1> $nextline </h1>\n";
    }

    fclose($fileHandle);

    *   see example files2.php

    *   NOTE: it is the PHP interpreter running your script, not "you" ---
        it runs with its permissions, not yours.

	moral: the file to be read needs to be world-readable for
	the PHP interpreter to read it, even using "your" script
	for "your" file

        (had to:

	redwood> chmod 644 lines_to_show.txt

	...for it to be read by files2.php)

*   aside:

    trim($str) returns a new string version of $str with leading
       and trailing blanks removed

    strlen($str) returns the length of $str

*   fgetc( ) - returns the next character, moves the pointer-cursor to
    the next character

    (isn't that really a string of length 1 in PHP? I'm not sure)

    *   could use for a filtering operation, for example

    *   files3.php seeks to print out ONLY the alphabetic characters
        in lines_to_show.txt, 80 characters a line

    *   aside:
        ctype_alpha - returns true if the passed string is all
        alphabetic characters

*   INTERESTING NOTE: fopen can take a URL, and request that page
    and your code can simply treat what's opened as just another
    file handle!!

    (even though it is essentially acting like a browser request
    of a page, right?)

    but you can fopen it, then read it, filter it, display all
    or part of it, your choice! (using fgetc, fgetc)

    *   for this feature to work, the configuration directive
        allow_url_fopen must be ENABLED

	(it IS for redwood --- check using phpinfo( ),
	as you can see in redwood.humboldt.edu/~st10/phpinfo.php )

    *   see example files4.php

*   SO - a few words about writing...

    ...for a PHP script to WRITE to a file --- that file would
    have to world-writable;

    (to create a file --- would the directory have to be world-writable?)

    *   NOTE that sometimes system administrators will make special
        directories for such writing and creation, for a bit
        more protection...

    *   I'll note:

        fwrite($fileHandle, $text) will write $text to the file handle
	$fileHandle

    *   files5.php?

        aside:   file_get_contents($filestring) will open the $filestring
                 file, and return a string with that file's contents
		 in one fell swoop!!

        *   note that I had to create logFile.txt and make it world-writable
            for this script to work...

        *   this works, but I've now made logFile.txt NOT world-writable
            for the sake of my redwood file quota... 8-)

*   screen scraping: a term Sklar uses for reading from a remote URL
    and slicing out what you want from it;

    *   can be fragile - can you count on the format of the page you're
        grabbing from?

        (regular expressions can make this more robust...)

    *   is it legal/ethical? depends on the page you're grabbing from!

        if ISN'T in public domain, you probably need permission
        to incorporate another site's content into your own...
        be careful/ethical, and check!

*   a few additional comments, for your consideration/future personal
    investigation:

    *   there are some PHP tools for dealing specifically with CSV files...
    
    *   file_exists($str) lets you see if a file named $str exists
    
    *   file_put_contents("$filename", "$str") lets you write "$str" to a
        a file $filename
    
    *   is_readable($str) lets you see if a file named $str is readable
    *   is_writable($str) lets you see if a file named $str is writable

    *   sometimes a global variable $php_errormsg will contain
        additional info when a PHP error has occurred (including file-related
        errors

    *   AND there are tools/techniques for "sanitizing" externally-provided
        filenames a USER provides --- use such techniques in those
        situations!