PHPには、（サーバー側にある）ファイルを読書きする機能があります。
[https://paiza.io/projects/AmzIAGAuiJdPMHsiMV7rdw?language=php 例]:
 $line";
}
fclose($fp);
実行結果（/etc/motdが開けた場合）:
resource(5) of type (stream)
> System Maintenance Notice
> 
> This weekend, we will shut down at 3:00 p.m. on Saturday for system updates.
実行結果（/etc/motdが開けなかった場合）:
PHP Warning:  fopen(/etc/motd): Failed to open stream: No such file or directory in /workspace/Main.php on line 5
Fail: fopen("/etc/motd", "r");
/etc/motd:
System Maintenance Notice
This weekend, we will shut down at 3:00 p.m. on Saturday for system updates.
fopen()関数は、Cと同じ名前ですが大きく機能が拡張されており、ネットワーク上のリソースも開くことができます。
ここではローカルファイルシステムの /etc/motd を読出し、内容を表示しようとしています。
/etc/motd は、UNIXにログインした時に表示するメッセージが保存されているファイルです。
fopen() に限らず、関数は戻値で成功/失敗を表しています。
ここで失敗を無視すると、それ以後の $fp を使った処理はことごとくエラーとなり、開けなかったハンドルで fclose() するという醜態に至ります。
var_dump()の結果から、fopen() が返す値は、リソース型だとわかります。
[https://paiza.io/projects/IvgsHfa2T7RFyeQ4HvgOVg?language=php 例]:
 $readString";
    }
    fclose($fp);
} catch (Exception $e) {
    echo sprintf("%s(%d): %s", $e->getFile(), $e->getLine(), $e->getMessage()), PHP_EOL;
}
PHPをウェブサーバー上で動かしている場合のファイル書込みは、セキュリティ上の脅威に直結するので慎重になるべきです。
ここでは、ごく小さな永続オブジェクトが必要な、アクセスカウンターを例に取ります。
例:
実行結果(1):
COUNT: 1
実行結果(2):
COUNT: 2
実行結果(3):
COUNT: 3
fopen()のモード "c+" はR/Wで開き、ファイルがなければ新規に作ります。
flock()は、ファイルへのアクセスをアトミックにする関数です。
ロックを掴んだあと、ファイルから１行読み出し、整数に変換しインクリメントしたあと先頭まで seek() しインクリメントした値を書込みます。
login.php:
シンプルでダーティーなログインフォーム
ユーザー名:
パスワード:
ログイン成功
ユーザー名 または パスワード が違います。
スーパーグローバル変数 $_POST が（間違っていないかではなく）あるのかをテストして、なければGETメソッドと判断しています。
ユーザー名:
パスワード:
を生成します。
ログイン成功
を生成します。
ユーザー名 または パスワード が違います。
を生成します。
ファームのレンダリング例
       ユーザー名:    
パスワード:    
登録
このコードには以下のような欠点があり、アジャイルにはともかく実務には使えません。
スクリプトに認証情報がハードコードされている
サーバーに侵入されなければ、JavaScript のように丸見えにはなりませんが「サーバーに侵入されない」前提で認証関係のコードを書いてはいけません。
メソッドを拠り所にフォームと認証を切り替えている
細工したユーザーエージェントからならば、メソッドを自由に切替えてチャレンジできます。
チャレンジ回数に限界がない
ブルートフォース攻撃に遭った時に、回数制限がないのは致命的な欠点です。
PHPでダウンロードをブラウザに問いかけるには、下記のように header 関数というのを使って、ブラウザに問い掛けできます。
コード例
書式は
です。
実験のさいには、あらかじめ画像データを作成しておいてください。
そして、ブラウザから、上記のPHPを実行します。（コマンドラインから実行しても、意味不明の文字列が表示されるだけです。）
成功すれば、ページ起動時に
と出て、「キャンセル」または「OK」のボタンが出てきます。
Content-Type: application/octet-stream の 「octet-stream 」は、種類を特定しないバイナリデータであることを宣言しています。画像データなどをダウンロードさせたい場合は画像ならバイナリ形式ですので、この 「octet-stream」を指定してもダウンロード可能です。
ダウンロードしたいファイルのファイル形式によっては、Content-Type で具体的に指定することもできます。
画像の場合、
PNG画像なら image/png をつかって   Content-Type: image/png  と指定しても、かまいません。
もしGIF画像なら image/gif で   Content-Type: image/gif  とも書けます。
JPEG画像なら    Content-Type: image/jpeg  とも書けます。
画像以外でも、
もしPDFをダウンロードさせるなら application/pdf のようになり、  Content-Type: application/pdf  とも書けます。
あるいは、もしテキストファイルなら text/plain で、  Content-Type: text/plain  とも書けます。
さて、
    header('Content-Disposition: attachment; filename="' . $fname . '"');
は、ダウンロードしたときのファイル名を上記コードでは $fname で指定しています。なので、ほかの名称でも構いません。たとえば
    header('Content-Disposition: attachment; filename="' . "test" . '"');
とすれば、ダウンロードされたファイル名は「test」になります。
ダウンロード開始は readfile関数でなくても、 file_get_contents 関数でもダウンロード問い掛けを出来ます。
環境や、アップロードするファイルの種類によっては
 ob_end_clean(); 
が必要です。
これがないと、ファイルにバッファ内の余計なデータがついたままブラウザに送信されてしまい、ダウンロード自体はできても、読込みエラーになってしまい、さっかくダウンロードした価値が無くなってしまいます。
上記のコードだと、ページが表示される前にダウンロードが始まってしまう。そのため、とても見づらくなります。
上記のPHPコードにprintなどの命令を書いても、うまく動作しないです。（基本的に、ダウンロード用のリンクでは、画像表示や文字表示は、あまり機能しないです。）
実務的な方法としては、別のHTMLファイルで上記PHPコードにアクセスするリンクを配置し、
コード例
ダウンロード
のようにして、このHTMLファイルに先にリンクしてもらうようにするのが良い。
すると、先にこのHTMLだけが表示されます。
そして、「ダウンロード」リンクをクリックすると、ページはそのままで（このHTMLが表示されたままで）、ダウンロードのポップアップが出るので、あとはブラウザ側でユーザーにダウンロードしてもらえば済む。