ホーム > 技術系 > php

phpのアーカイブ

PHPの無名関数(クロージャ)について

PHPの無名関数(クロージャ)についてのまとめです。

無名関数とは

無名関数とは、関数規則に沿って命名を必要とせず定義できる関数です。

function(引数) {
処理内容;
}

といった形で使用できます。

例えば

$func = function(引数) {
処理内容
}

といった形で定義した場合、この$funcは、ラムダ関数とも呼ばれます。

$a = $func(引数);

このような形式で、使用する場所で呼んで使用できます。

無名関数を使用するメリット

無名関数は概念的には関数と同じなので、無名関数にせず関数として定義して呼び出しても同じなのですが、
普通の関数を定義無名関数を使用することにより、その場限りで呼び出す処理の場合は、関数名を他の関数名と衝突しないで済む、プログラム全体が複雑にならないといったメリットがあります。

無名関数内の処理に外部の変数を使用したい場合

プログラムによっては、無名関数の中で使用するプログラムに、無名関数の外の変数を使用したい場合があります。

無名関数は関数なので、引数にしている変数以外の外部の変数は内部の処理には適用されません。

しかし、use文を使うことでその問題は解決できます。

$func = function(引数A) use(変数B) {
処理内容;
}

このように無名関数を使用することで、処理内容で引数Aだけでなく外部の変数Bも使用できます。

Laravelのファイル、フォルダのパーミッション設定

Laravelのファイルとフォルダのパーミッション設定についてです。

下記の記事が参考になりました。

Laravelのパーミッションを適切に設定 | Qiita

ディレクトリに対して権限を変更
sudo find laravel-root-directory -type d -exec chmod 750 {} \;

ディレクトリは750なので、所有者は全部可能、グループは読み実行可能、その他はできない設定

ファイルに対して権限を変更
sudo find laravel-root-directory -type f -exec chmod 640 {} \;

ファイルは640なので、所有者は読み、上書き可能、グループは読みのみ可能、その他はできない設定

最後にストレージとキャッシュの権限を変更
sudo chmod -R 770 laravel-root-directory/storage/ laravel-root-directory/bootstrap/cache/

ストレージ、キャッシュフォルダは所有者、グループは全部可能。その他はできない設定。

webサーバーのApacheをインストールすると作成されるwww-dataをグループに追加する
sudo chown -R myusername:www-data laravel-root-directory

これは、上記はwww-dataグループになっていますが、自分の環境(CentOS、nginx)では、httpdのグループがwwwだったので、以下の設定で上手くいきました。

sudo chown -R myusername:www laravel-root-directory

グループ「www」がphpを自分の環境の場合実行しているので、phpファイルは読み出しのみの設定で問題ありませんでした。
phpファイルの実行権限は、所有者、グループとも読みのみで問題ないんですね。
実行権限が必要なのかなとイメージ的には思っていたのですが。

例えばPerlなんかはCGIで755にするのが一般的でしたが、755ってのは所有者は全部できて、グループユーザが読み、実行権限があるということですもんね・・・。

使っているPHPはPHP-fpmなので、モジュール版ではなくてCGI版なのですが、同じCGIでもPerlとPHP-FPMではパーミッションが違うと、これはややこしい話です・・・。

php -vで表示されるphpバージョンと、phpinfo()で表示されるバージョンが違う対処

サーバはkusanagiを利用しているのですが、

phpinfo();

で表示されるphpのバージョンは7系なのに、

サーバにログインして、コマンドラインで

php -v

で表示されるのは、5系というよくわからない事象に遭遇して困ってしまいました。

これで何故困るかというと、Composerをアップデートしたときに、以下のようなエラーが出たからです

このComposerのアップデートには、phpの7系が必要だよ

みたいなエラーです。

しかし、phpinfo()で確認すると使っているPHPのバージョンは7系で、サーバにログインしてコマンドラインで実行している
Composerは5系のPHPを見ているようだという謎です。

調べてみると、KusanagiのPHPは、Webサーバで実行しているのはPHP-fpmというCGI版のPHPで、コマンドラインで実行しているのは、apache経由でモジュール版のphp5系で実行しているとかとういったかんじの現象のようでした。

Kusanagiのサーバでは、rootでサーバにログインして

kuasanagi php7

を実行することでphp7の実行環境に切り替わるようですが、apacheのモジュール版はphp7になっていない??

というよく分からない感じです。

さらに調べると、Kusanagiではサーバにログインして

yum update

で、モジュール版もPHP7に切り替わるといったことが書いてあったので、試してみると、

yum updateでエラー

で、これはサーバのPythonのバージョンを3系に上げていたので、Python2系で書かれているyumがエラーを起こしている様子
これは、いろいろとぐぐることで対応方法が出てきたので、yumのソースで、Pythonのパスが書いてあるところを、
サーバに残っているPython2系へのパスに何箇所か変更します。

これで yum update が実行できました。

これで、満を持して

php -v

を実行。すると、またも

php 5.6〜〜〜

と。え、php7に変わってない・・・?

いったん諦めてから翌日サーバにログインして

php -v

をもう一度実行してみると

PHP 7.3.1 (cli)

と、無事アップデートしてました。

よく分からないですが、yum updateしてからサーバに反映されるのに
時間が必要だった?みたいで、apacheを再起動することで反映されたのか、
よく分かりませんが、何にせよ時間経過で反映されました。

よく分かりませんが、Composerで実行していたPHPは、モジュール版というよりも、CLI版
というPHPのようで、確かにphp -vをすると

PHP バージョン(cli)

と、cliを後についています。
ここのCLI版のバージョンが影響していたようですが、何にせよ今回のケースでは
yum update で無事解決したようです。

この後、

Composer update

を実行すると、無事エラーにならずアップデートを行うことができました。

Composerをrootユーザで実行してはいけない理由

Linux系のサーバにrootユーザでログインして、Composerを実行しようとすると、以下の警告メッセージが表示されます

Do not run Composer as root/super user! See https://getcomposer.org/root for details

https://getcomposer.org/root を見ろということなのでアクセスしてみると、説明がありました。

How do I install untrusted packages safely? Is it safe to run Composer as superuser or root?

どうやって信頼されてないパッケージを安全にインストールできますか?
Composerをスーパーユーザやルートユーザで安全に実行できますか?

Certain Composer commands, including exec, install, and update allow third party code to execute on your system. This is from its “plugins” and “scripts” features. Plugins and scripts have full access to the user account which runs Composer. For this reason, it is strongly advised to avoid running Composer as super-user/root.

Composerのコマンドには、実行、インストール、アップデートが含まれていて、システムに影響するコードを実行することをサードパーティに許可します。
これは、プラグインとスクリプトの特徴に由来しています。プラグインとスクリプトはComposerを実行するユーザアカウントに完全にアクセスします。
この理由により、Composerをrootユーザで実行しないことを強く推奨します。

You can disable plugins and scripts during package installation or updates with the following syntax so only Composer’s code, and no third party code, will execute:

あなたはプラグインとスクリプトを、パッケージをインストールかアップデート時に以下のコードを追加することで無効にすることができます。
サードパーティのコードは実行できなくなります。

composer install –no-plugins –no-scripts …
composer update –no-plugins –no-scripts …

The exec command will always run third party code as the user which runs composer.

In some cases, like in CI systems or such where you want to install untrusted dependencies, the safest way to do it is to run the above command.

execコマンドはサードパーティのコードをcomposerを実行するユーザと同じように実行します。

いくつかのケースで、CIシステムまたは信頼されていない依存関係をインストールするときに、最も安全なのは上記のようなコマンドで実行することです。

CentosでComposerがインストールされているかどうかの確認

ComposerはPHPのパッケージ管理ツールですが、Composerを使用する前に、まず環境にComposerがインストールされているかの確認が必要になります。

CentOSでの確認方法についてですが、導入が完了されている状況であれば、コマンドラインで

composer

と打てば、下記のようなコマンドが表示されます。
インストールされている場合は、現在の入っているComposerのバージョンも確認できます。

composerの初期画面

Composerのインストールは、公式サイトからインストーラーをダウンロードしてセットアップ後、作成されたcomposer.pharを、

/usr/local/bin/composer

へ移動させることで実行可能になるので、ここまでができていれば上記の様な画面が表示されます。

なければcomposerコマンドが実行できないはずです。

インストールの手順は以下の通りです。

php -r “copy(‘https://getcomposer.org/installer’, ‘composer-setup.php’);”

php composer-setup.php

php -r “unlink(‘composer-setup.php’);”

mv composer.phar /usr/local/bin/composer

PHPの勉強メモ

PHPについての勉強メモです。

namespace(名前空間)

php5系の途中から利用可能になった仕様。

namespace ◯◯;

で名前空間を定義することで、同名のクラスや関数も定義して同時に読み込むことができる。

例えば異なる名前空間で同名のクラスが定義されている複数のライブラリを読み込んでから使用する場合は、

new 名前空間名\クラス名;

のようにして使うことができる。

use文での省略

名前空間は、

namespace ◯◯\◯◯\◯◯;

のように、サブディレクトリのような形式で使用することができる。

これが長くなると、

new ◯◯\◯◯\◯◯\クラス名;

のようなかんじで、記述が冗長になる。
記述が複数箇所になればなお冗長になる。

このため、use文を使うことで

use ◯◯\◯◯\◯◯ as A

のような形で宣言すれば

new A\クラス名;

のような形式で利用でき、記述が簡潔になる。

また、この宣言はいろいろな記述が可能で

use ◯◯\◯◯\◯◯\クラス名;

のような形式で宣言すれば

new クラス名のようなかんじでいきなり使用できる他、

use AB\CD\EF;

のような形式で、asを省略した場合

use EF\クラス名;

のような形式で記述が可能となる。

また、

use AB\CD;

のようなかんじで途中まで定義して

new CD\EF\クラス名;

のような使い方もできる。

また、これは、クラス名だけでなくメソッドを呼び出す場合も同様の手順で行うことができる。

::(スコープ定義演算子)

スコープ定義演算子は、クラスの静的プロパティやメソッドにアクセスする場合に使用する。

一般的な方法では、

クラス名->メソッド;
クラス名->プロパティ;

といった書き方がしますが、意味はこれと同じで

クラス名::メソッド;
クラス名::プロパティ;

といった書き方ができますが、前者は対象が動的な場合で、後者は静的であることを表しています。

どちらも実行結果は同じですが、プログラムの読み手が、アクセス先が静的で動的かが見ると分かるということです。

file_get_contentsがNULLを返すようになった原因の調査

PHPで、あるプログラムを作成していて、file_get_contents関数で特定のURLからJSONファイルを取得するという処理を行っていたのですが、以前は動作していたプログラムが、サーバ移行後に file_get_contents関数で取得できなくなってしまった現象に遭遇してしまったので調査と対応について記しておきます。

状況

・ 特定のURLから file_get_contents関数でJSONファイルを取得し、後に処理

・ 以前は動作していたが、サーバ移転後に動作しなくなった

・ レスポンスヘッダもNULLを返すようになっていて、原因が不明

調査

まず、エラーログを見て file_get_contents 関数がエラーになっていないかどうかを調べてみたのですが、エラーにはなっていませんでした。

結果からいうと、エラーになっていたわけではなく、取得がNULLになっているという謎の結果。

解決

ファイルを取得するのに、file_get_contents関数ではなく、cURL関数を使うことで解決できました。

以下の記事が参考になりました。

file_get_contents関数が動かなかった場合の方法 | Tips Note by TAM

cURL関数を使うことで、file_get_contentsとほぼ同じ動作をする関数を定義して、使用しました。

$result = curl_get_contents( $url, 120 );  //file_get_contentsの代用関数。120はタイムアウト(秒)
 
function curl_get_contents( $url, $timeout ){
    $ch = curl_init();
    curl_setopt( $ch, CURLOPT_URL, $url );
    curl_setopt( $ch, CURLOPT_HEADER, false );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
    curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout );
    $result = curl_exec( $ch );
    curl_close( $ch );
    return $result;
}

何故 file_get_contents 関数が新しいサーバで動作しなかったのかについては不明ですが、代用の関数でなんとかなりました。

Nginx+php7へのWordPress移行で苦労した点まとめ

PHP7+Nginx

サイト運営に利用していたサーバを、サーバの運営に利用していたPleskの値上がりを受けて別のサーバへ移行しました。

サーバの環境もけっこう代わりました。

移行前の環境
php5+Apache

移行後の環境
php7+Nginx

すんなりサーバが移行できたわけでなくて、いろいろとトラブルも発生したので発生した問題点と、解決方法について備忘録として書いておきます。

1.サーバを移行しようと思った理由

これまで使用していたサーバの月額費用が、Pleskのライセンス費用で値上がりしたと、いってみればそれだけの理由です。
試算してみると、Plesk抜きのサーバへ移行すると月額2000円〜最大で3000円ほど(年額換算で3万円ほど)節約できる試算になったのでこのタイミングで移行することにしました。

2,移行したサーバ会社

ConohaのVPSに移行しました。

Conohaを決めた理由としては

  • サーバに最新技術が導入されていてサイトの動作速度向上が期待できる
  • Pleskは使えないが、Kusanagiコマンドで簡単にサイト設定を行うことができる
  • 費用面でサーバのメモリを少なくすれば月額費用はかなり少なくてすむ

という点になります。

2.移行プロセス

カスタムパーマリンクが機能しない

まず、サーバ管理のソフトウェアをApacheからNginxに変更しました。

理由としては、速いから? よく分かりませんがそうしました。

そしてPHPのバージョンを7にしてみたのですが、これはうまく行かず、理由としては、WordPressのカスタムパーマリンクが上手く機能しなかったから。

URL/〜〜〜/〜〜〜/

上記のようなWordPress上で設定していたURL設定が機能せず、Not Foundとなる。
この解決方法がわからなかったので、別の方法を考えました。
(理由としてはNginxの設定だったのですが、最初は分かりませんでした)

Apache + HHVMを試してみる

結局サーバのNginxではだめだったので、HHVMでサーバを変更してみることにしました。

HHVMというのはPHPのバージョンの1つのようなものなのですが、NginxではなくApacheで動作します。
kusanagiだとワンボタンでサービスを変更できるので、変更してみたところ、問題なくサイトが機能した・・・ように見えました。

訪れる謎の高負荷と、サーバダウン

HHVM+Apacheは、HHVMのキャッシュに機能で動作が非常に高速で、サーバ移行前と比べると動作が高速化してめでたしめだたし・・・・かと思いました

が、数時間おきにサーバに謎の高負荷がかかりサーバダウンするという現象が起きました。

とりあえず応急処置としてこまめにHHVMの再起動設定

調べてみたところ、ConohaのKusanagiのHHVMは不安定でときどきダウンすることがあるということでした。

応急処置として、cron設定で1分ごとにHHVMを再起動するように設定しました。
これにより、仮にサーバがダウンしても長時間そのままダウンし続けるという自体は避けることができます。

原因はよく分からないのですが、とりあえず同様の現象の方はいたようで、またあくまで応急処置で、数時間に一度、数分程度サーバがダウンしてしまうということ自体が解消されたわけではなく、さすがにその状況でサーバを運営し続けることは品質面で問題といえます。

そこで、別の方法を検討することにしました。

すると、Nginxに切り替えると安定するということでした。

Nginx+PHP7に再度挑戦

最初にいったんやろうとしてあきらめたNginx+PHP7への移行に再度挑戦してみることにしました。

Conohaのサービスでは、サーバをイメージ保存しておいて、そのコピーのサーバを簡単に作成できるので、HHVMのサーバは残した状態で、コピーしたサーバを作成し、Nginxの設定に変更してテストを行いました。

こういうことがコントロールパネルから簡単にできるのも、Conohaの優れている点です。

カスタムパーマリンクの対応

まず、カスタムパーマリンクが動作しない点については、Nginxは.htaccessが使えないのでNginxの設定ファイルに記述しないといけないということでした。

Nginxの設定ファイルは、nginx.confというファイルに設定されているのですが、このファイルに正規表現を使って様々な記述がされていたので、この設定をサイトごとに設定しました。

この作業は少し手間がかかる作業でしたが、完了することで、無事パーマリンクが機能するようになりました。

PHP7で動作しないファイルの修正

次に、以前のサーバがPHP5で動かしていたので、PHP7になることで動作しないファイルが大量に出現したので、これらのエラーファイルを順に修正していきました。

エラー箇所の特定は、Nginxのエラーログファイルを見ながらエラー箇所を特定し、修正してきました。

これらは運営しているサイトの数が多かったのでかなりの作業量が必要になり、なかなか大変な作業だったのですが、HHVMにしたときに数時間おきに少しの間サーバがダウンするのはサービス品質に対して影響が大きいだろうということでやむをえず行いました。

PHP5の記述とPHP7では、特にデータベース回りの記述が変更になっている箇所が多かったので、修正箇所は多岐に渡りました。

また、WordPressのプラグインも、PHP7に対応していないプラグインは削除したり、ファイルの修正で対応できるものは対応するということが必要になりました。

サーバの移行完了

これらの作業を終えることで、無事Apache+PHP5からNginx+PHP7への移行が完了しました。

つまづいた点としては、

  • .htaccessが使えないのでパーマリンク設定をnginx.confに記述しなければならない
  • PHP5の記述が一部動作しないのでエラーが起こる点はPHP7で動作するように修正しなければならない

という主に2点になります。

思った以上に移行作業は時間はかかりましたが、結果的にサーバのランニングコストを下げることができ、サイトもNginx+PHP7になったことで高速化したように見えるのは良い点ではないかと思います。

まだサーバが移行したばかりなので予期せぬトラブルはあるかもしれませんが、しばらく様子見したいと思います。

phpでファイルをinclude時に謎の空白行が入る問題を解決

  • 2018年5月10日 6:46 PM
  • php

phpのファイルで、特定のファイルをincludeして読み込んだ場合に、謎の空白行が上に1行入る問題がありました。

発生した問題

phpファイルのヘッダの上に謎の空白行が1行表示される

原因の究明方法

まずはchromeのデベロッパーツールでソースコードを調べたが、ソースコード上には何の問題も見られない。
phpファイルのプログラムの行を削除して調べていたところ、特定のphpファイルをincludeした際に改行が入っていた。
該当のphpファイルを調査したが、問題ないソースコードであるように見受けられ、不要な出力や改行、全角文字なども見当たらなかった。

解決策

該当の問題となっていたphpファイルを新規作成して作り直し、同様のコードをコピーペーストして同様の内容とした。
作り直したファイルをアップロードしたところ問題は解消した。

つまり、もともとのファイルを作成した際に、文字コードや改行コードの微妙な違いがあったようである。

詳しい原因は分からないが、作成した時に使っていたエディタや環境と、現在使っている環境(phpstorm)が異なっていたために、微妙な差があって発生していた問題かもしれない。

ホーム > 技術系 > php

フィード

ページの上部に戻る