PHP色々メモ

PHP7のメモ書きです。

###includeする共通ファイルを絶対パス指定する

こんな感じで相対パスで指定すると色々と面倒なので、絶対パスで指定する。

```
include('../../common.php');
```

これだとダメ。

```
include('/common.php');
```

$_SERVER['DOCUMENT_ROOT']を使う。

```
include('$_SERVER['DOCUMENT_ROOT'] . /common.php');
```

ちなみに、Apache、Centos7環境だと、$_SERVER['DOCUMENT_ROOT']は、/var/www/htmlを返します。


参考サイト
[PHP で共通部を include する際に覚えておきたいドキュメントルートの取り方](https://h2ham.net/php-document-root/)

###require、require_once、include、include_onceの違い

require系で指定したファイルがないとFatal errorで処理を中断、include系で指定したファイルがないと警告（Warning）を出力して処理を継続。

参考サイト
[【PHP】外部ファイルを読み込む際のrequire、require_once、include、include_onceの使い分け](https://qiita.com/awesam86/items/3fa28e23c95ca74caddc)

[PHPのincludeとrequireの使い方と違いを比較](https://www.flatflag.nir87.com/include-598)

[include()とrequire()の違い](https://wp-p.info/tpl_rep.php?cat=php-biginner&fl=r14)
->具体的な使い分けについても書いてある。

###よく使うPHPのコマンドラインのオプション一覧

-h、ヘルプ表示

```
$ php -h
Usage: php [options] [-f] <file> [--] [args...]
   php [options] -r <code> [--] [args...]
   php [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]
   php [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]
   php [options] -S <addr>:<port> [-t docroot] [router]
   php [options] -- [args...]
   php [options] -a

  -a               Run as interactive shell
  -c <path>|<file> Look for php.ini file in this directory
```

-r、コマンドライン上でphpコードを実行する。

```
$ php -r "echo 'hello world'.PHP_EOL;"
hello world
$
$ php -r "phpinfo();" | grep php.ini
Configuration File (php.ini) Path => /etc 
```

-f、phpファイルを読み込んで実行する。これは特にオプションをつけないでも実行できました。

```
$ cat testphp.php 
<?php
echo 'hello php'.PHP_EOL;
?>
$ php -f testphp.php 
hello php
$ php testphp.php 
hello php
```

-i、phpの情報を取得。phpinfo()と同じかな。

```
$ php -i | less
```

--ini、設定ファイル関連の一覧表示かな。

```
$ php --ini
Configuration File (php.ini) Path: /etc
Loaded Configuration File:         /etc/php.ini
Scan for additional .ini files in: /etc/php.d
Additional .ini files parsed:      /etc/php.d/20-bz2.ini,
/etc/php.d/20-calendar.ini,
/etc/php.d/20-ctype.ini,
```

-m、コンパイルモジュールの一覧表示。

```
$ php -m
[PHP Modules]
bz2
calendar
Core
```

--ri、拡張モジュールの設定を表示。

```
$ php --ri sqlite3

sqlite3

SQLite3 support => enabled
SQLite Library => 3.7.17

Directive => Local Value => Master Value
sqlite3.extension_dir => no value => no value

$ #存在しない拡張モジュールを指定した場合
$ php --ri sqlite
Extension 'sqlite' not present.
```


-a、インタラクティブシェルモード（対話シェルモード）。コマンドライン上でちょっとphpのコードを試したいときに便利。Ctrl+Cで終了できる。

```

$ php -a
Interactive shell

php > echo 'aiueo';
aiueo
php > echo 3 + 3;
6
php > echo 3 * 3;
9
php > phpinfo();
phpinfo()
PHP Version => 7.4.3
```

###auto_prepend_fileで初期化処理の共通化、php.ini

php.iniにあるauto_prepend_fileは、実行するphpのメインファイルの前に実行するphpファイルを指定できる。
実際に使ってみるとこんな感じ。

```php.ini
; Automatically add files before PHP document.
; http://php.net/auto-prepend-file
;auto_prepend_file =
auto_prepend_file = /home/vagrant/test/testphp.php
```

```
$ cat /home/vagrant/test/testphp.php
<?php
echo 'hello php'.PHP_EOL;
?>

$ cat /home/vagrant/test/testphp2.php
<?php
echo 'hello php2'.PHP_EOL;
?>

$ php testphp2.php 
hello php
hello php2
```

testphp2.phpを実行したのに、testphp.phpが事前に実行されています。

で、これはウェブでphpを使う場合も適用されるのかと思って試してみたんだけど、この設定でApache上で適当なPHPのページを実行するとエラー(HTTP ERROR 500)が出ます。
（Apache2.4）

Apacheのエラーログ（/etc/httpd/logs/error_log）を見ると、下のエラーが出力される（タイムスタンプとかは省略）。

```/etc/httpd/logs/error_log
PHP Fatal error:  Unknown: Failed opening required '/home/vagrant/test/testphp.php' (include_path='.:/usr/share/pear:/usr/share/php') in Unknown on line 0
PHP Warning:  Unknown: failed to open stream: Permission denied in Unknown on line 0
```

ネットで少し調べてみたら、auto_prepend_fileの設定をphp.iniではなく.htaccessでやっている人が多かったので、以下を１行を.htaccessに追加して試してみたけど、それでもエラー(Internal Server Error)が出ました。

```.htaccess
php_value auto_prepend_file "/home/vagrant/test/testphp.php"
```

Apacheのエラーログ（/etc/httpd/logs/error_log）を見ると、下のエラーが出力される（タイムスタンプとかは省略）。

```
 /var/www/html/.htaccess: php_value not allowed here
```

php_valueはここでは（.htaccess）ダメだということで、httpd.confファイルの最後に同じ１行を追加してApacheを再起動してみたけど、またエラー(HTTP ERROR 500)が出ました。
エラーログ（/etc/httpd/logs/error_log）はこんな感じ。

```/etc/httpd/logs/error_log
PHP Fatal error:  Unknown: Failed opening required '/home/vagrant/test/testphp.php' (include_path='.:/usr/share/pear:/usr/share/php') in Unknown on line 0
PHP Warning:  Unknown: failed to open stream: Permission denied in Unknown on line 0
```

このエラー内容は、最初に試した時のエラーと同じ。で、エラーの内容が指定のファイルパスは読み込めない、includeパスは.:/usr/share/pear:/usr/share/phpだという事なので、今度は/usr/share/php/下にphpのテストファイルを追加して、httpd.confに追加する１行もそれに合わせて変更しました。

```httpd.conf
#最後に追加
php_value auto_prepend_file "/usr/share/php/testphp.php"
```
これでApacheを再起動したら、やりたいことができました。Apache上の適当なphpページを実行すると、最初に/usr/share/php/testphp.phpが実行されます。/usr/share/php下だけでなく、/etc/httpd/conf下のphpファイルでもできました。

これで、エントリポイントみたいなものができたので、ウェブ（Apache）上の全てのphpページの共通の初期化処理などを書くことができます。ただ、これは環境依存になりそうだし、その管理をするための手間がかかりそう。と言うより、ここまできたら普通はウェブのフレームワークとかを使うんだと思います。



参考サイト
 ・[auto_prepend_file ・ auto_append_file ディレクティブで自動的にファイルを読み込む](https://linuxserver.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0/php/auto_prepend_file%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%86%E3%82%A3%E3%83%96%E3%81%A8auto_append_file%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%86%E3%82%A3%E3%83%96/)
・[auto_prepend_file とauto_append_fileの設定をapacheの設定ファイルで記述する場合](https://sites.google.com/site/phpgongeben/home/autoprependfiletoautoappendfilenoshedingwoapachenoshedingfairudejishusuruchanghe)
・[auto_prepend_fileで役割分担](http://beatnik.jp/blog/archives/249)
・[PHPのエントリポイントの調べ方](https://qiita.com/nazonohito51/items/57c2af47550c95667c12)

#####PHPのエラー関連、PHP Notice:　PHP Warning:　HP Fatal error:

PHP Notice:　注意
PHP Warning:　警告
HP Fatal error:　エラー

・[PHPのエラー・警告・注意の違いとは](https://php1st.com/1833)

Warningやerrorが発生した場合、ブラウザにエラー内容を表示したい場合、php.iniファイルのdisplay_errorsをOffからOnにする。Offの場合、ログファイルに/var/log/httpd/error_logに表示されるだけになる。

```/etc/php.ini
display_errors = On
```

#####自分自身（PHPが稼働しているサーバ）のグローバルIPを取得する

PHPが稼働しているサーバのグローバルIPですが、$_SERVER変数で取得できると思っていましたが、自分の環境だとありませんでした。プライベートIPなら、`$_SERVER['SERVER_ADDR']`で取得できるのですが。
（ただ、ドメインをDNSで割り当ててない場合、$_SERVER['HTTP_HOST']と$_SERVER['SERVER_NAME']はグローバルIPになります。）

で、phpでグローバルIPを取得する方法ですが、下のサイトを参考にしました。gethostbyname()関数かcurlで自身のグローバルIPを問い合わせる感じですね。

・[PHP でクライアントとサーバのグローバル IP アドレスを取得する](https://yopinoji.com/get-ip-address-with-php)

あと、下のサイトを見る限り、さくらのサーバだと$_SERVER[‘HTTP_LISTEN_IPADDR’]でグローバルIPが取得できるみたいですね。

・[さくらのレンタルサーバーで$_SERVER[‘SERVER_ADDR’]の値が変わった](https://zakkiweb.net/a/71/)
・[さくら、レンタルサーバの仕様変更について（2018年3月）](https://help.sakura.ad.jp/notification/360000027581/)