20190820のPHPに関する記事は7件です。

php-master-changes 2019-08-19

今日は arginfo を PHP スタブへ移行する修正があった!

2019-08-19

iNem0o: Add md5 arginfo stubs

iNem0o: Add metaphone arginfo stubs

iNem0o: Add pageinfo arginfo stubs

iNem0o: Add sha1 arginfo stubs

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LaravelのEloquentで最初のn件とn件目以降のデータを取得する

Eloquentで最初の5件を取得

最初の5件を取得するには take メソッドが便利。

$datas = Model::where('hoge', 0)->get();

// 最初の5件
$datas->take(5)

Eloquentで最後の5件を取得

最後の5件を取得するなら splice が便利だ

$datas = Model::where('hoge', 0)->get();

// 最初の5件を削除した残り
$datas->splice(5)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VCCW3.x で、PHPのバージョンを5.6にする

結論

// in the client
$ sudo add-apt-repository ppa:ondrej/php   ### PPAのインストール
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt install php5.6   ### php5.6のインストール
$ sudo a2enmod php5.6   ### apacheにphp5.6モジュールを組み込む(有効化)
$ sudo a2dismod php7.0   ### apacheからphp7.0モジュールを除去(無効化) これを書いてない記事が多い
$ sudo apt-get install php5.6-mysql   ### 'Your PHP installation appears to be missing the MySQL extension which is required by WordPress.' エラーへの対処
$ sudo apt-get install php5.6-mbstring   ### WP Multibyte Patchあたりが必要としてるっぽい
$ sudo service apache2 restart

経緯

普段WordPressの開発に、Virtualbox + Vagrant + VCCW3 を使っているのだけど、未だWordPressの本番環境ではPHP5.x上で動かしてるものも少なくなくなくなくなくなくて、できるだけ本番環境に近い開発環境を用意したいものの、VCCW3はUbuntu16.04がベースにあるため、PHPの標準バージョンが7な上に、PHP5.6を標準でサポートしてないという状況のため、もどかしい気持ちになっていた。

手順

PPAを入れる

ペンパイナッポーアッポーではなく、パーソナル・パッケージ・アーカイブのことらしい。Ubuntu公式ではなく、そのユーザーが保守しているパッケージ集で、公式ではサポートしなくなったアプリケーションなどをaptでインストールできるようにしてくれる。
PHP5.6のインストールには、Ondřej Surý氏によるPPAを用いる。
PPAをインストールしたら、リストの更新のためにも、 apt-get updateをしておこう。

$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt-get update
$ sudo apt-get upgrade # ついで

PHP5.6 を入れる

Linux系の環境で、導入されている設定を切り替えるには、いろんな手続きが必要だったりするものだけど、今回はひとまずいきなりPHP5.6を入れても大丈夫のようだ。
PPAを入れることで、PHP5.6のインストールは可能になったのだから、早速入れてしまおう。

$ sudo apt-get install php5.6

PHP5.6 を apache で使えるようにする。

PHP5.6をインストールしただけではまだ使える状態にはなっていない。というか、apacheが「PHP5.6を使うべき」という認識をしてくれていないのだ。このままでは依然PHP7.0を使い続けてしまう(なぜPHP7.3じゃないんだろう…)

そこで、apacheのモジュールに、PHP5.6モジュールを組み込んで、使えるようにする。ただ、有効にしてapacheをrestartしてみると、実はセグフォるだけで、起動してくれない。理由は「PHP7.0モジュールも組み込まれているから」である。($ ls /etc/apache2/mods-enabled/を見てみると、php5.6.loadphp7.0.loadの2つが設置されいていることに気づくはずだ)。なので、これの除去もちゃんと行なっておく。

$ sudo a2enmod php5.6   ### apacheにphp5.6モジュールを組み込む(有効化)
$ sudo a2dismod php7.0   ### apacheからphp7.0モジュールを除去(無効化) これを書いてない記事が多い

余談1

調べた限りでは、この$ sudo a2dismod php7.0について書かれているサイトがほぼ無くて、結構迷った。実際、a2dismod php7.0をキーワードに検索して初めて見つけたくらいだ。

余談2

本来ならここで、CUIのPHPバージョンも5.6にしておくべきなんだろうが、wp-cliの何かプラグインがPHP5.xでは動かなかった気がするので、一旦保留。ただ、wp-cli経由でWordPress動かしたときに、PHP7.x上でWordPressを処理するのであれば、CUIの方もPHP5.6に変えないといけない気がするなぁ…

PHPからmysqlが

ここでapacheをrestartしてみると、起動はするもののページがちゃんと表示されてくれない、という問題が起こる。画面にはそっけなく

Your PHP installation appears to be missing the MySQL extension which is required by WordPress.

というテキストが表示されるのみだ。
これは、今のPHPモジュールからMySQL拡張が利用できないが故に表示されるようで、実際調べてみると、$ php -m | grep mysqlの結果にmysqlという行がないことに気づく。
一般に、こういうときは $ sudo apt-get install php-mysqlと打って、PHPのmysqlモジュールを入れるべきなのだが、言ってみればこのデフォルトのライブラリは、Ubuntu16.04標準のPHP7.x用のmysqlモジュールを指しているので、これでは解決しない。ちゃんと php5.6用のモジュールを入れてあげよう。

$ sudo apt-get install php5.6-mysql

mbstringも大事

普段はあまり有効性を感じないんだけど、まぁ大体の日本語環境では有効化されているプラグインWP Multibyte Patch。別になくても普通に使えるものの、もし自身の環境でこれが有効化されているなら、その内部で mbstring を使っているようなので、これも使えるようにしておく。
上記同様、普通ならphp-mbstringを入れるので良いのだけど、今回はPHP5.6向けのものが必要なので、php5.6-mbstringで対応する。

$ sudo apt-get install php5.6-mbstring

apache2をリロード!

最後に、今まで入れたり変更したりした設定を有効にするため、apache2をリロードする。
リロード方法はいくつかあるが、$ sudo a2enmod php5.6を実行したときに表示された方法でリロードすることにする。

$ sudo service apache2 restart

おわりに

いままでずっと「本番はPHP5.xだけど、まぁPHP7.xで動けばだいたい動くでしょ、WordPressは」みたいな雑な考えで逃げ続けていたのだが、WordPressも5.2になって、推奨環境がPHP7.3以上になり、さらに

年末に PHP 7 以降を最低必須バージョンにすることも視野に入れつつ
日本語 « PHP 最低必須バージョンの変更 — WordPress

とか公式にかかれていたりするので、そのうちPHP5.6で動くものが減ってくる可能性も考えると、今の構成(WordPressはもちろん、各種プラグインも)がちゃんとPHP5.6で動くかどうか検証しないといけないなーって状況になってきて、ここ数年ちゃんとLinux触ってないながらにいろいろ調べることになったわけなんですが、案外VCCW3でWordPressを開発してる人が少ないのか、これ系の情報があまり見つからないんですよね。いや、WordPressを使う人が、Linuxの環境いじれることの方が珍しいだけなんでしょうけど。

参考サイト/記事

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

すぐに忘れる phpcs を設定する際に使うコマンド

※phpcsにpathが通っている前提です。

現在使用可能な規約

$ phpcs -i
The installed coding standards are PEAR, Zend, PSR2, MySource, Squiz, PSR1 and PSR12

自作ルールの格納ディレクトリを確認

$ phpcs --config-show
Using config file: /Users/hoge/.composer/vendor/squizlabs/php_codesniffer/CodeSniffer.conf

installed_paths: /Users/hoge/.phpcs
# installed_paths: 〜 が自作ルールを入れるフォルダ。

自作ルールの格納ディレクトリを指定

# installed_pathsは上書きされるので注意。(この場合 /Users/hoge/.phpcs の指定が消える。)
$ phpcs --config-set intalled_paths path/to/standarts/dir
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel 5.8 -> 6.0 LTS Upgrade Guide が更新されました!

こちらのツイートの通り、 Laravel 6.0 は LTS サポートになる予定とのことです。

そして、 Laravel 5.8 から 6.0 へのアップグレードガイドも更新されました(リリースまでもう少し更新が入るかもしれません)。

以下、要約。

Upgrade dependencies

composer.jsonlaravel/framework の依存を ^6.0 にして composer update をかけます。

6.0 から SemVer を採用するので、 7.0 になるまで破壊的変更は含まれない予定となっています。そのため、バージョン指定は 6.0.0~6.x.x となる ^6.0 を指定する形になります。

もちろん、このアップグレードがほかの dependencies で対応しているかしっかりと確認する必要があります。これは以前からのアップグレードと同様です。

特に今回は 5.8 から 6.0 へのアップグレードのため、多くのライブラリは laravel/framework: ^5.6 といった形で依存していて、しっかりとした更新対応が入るまでアップグレード出来ないのではないでしょうか。

認可処理

Authorized Resources

$this->authorizeResource(Post::class, 'post'); のような形でリソースコントローラに対してコンストラクタでポリシーを設定している場合、 index メソッドは元々認可をスルーしていましたが、 viewAny メソッドをポリシークラス側に定義しない限り認可で拒否されるように変更になりました。

RegisterController

RegisterController の register registered メソッドを上書きしている場合は、親メソッドを呼ぶ必要が出てきました。イベントの発行場所なども変わっているので注意が必要です。

Authorization Responses

Illuminate\Auth\Access\Response クラスが変更になりました。

Database

プライマリキー型定義

パフォーマンス最適化のため、 protected $keyType = 'string'; のように、 string 系の型をプライマリキーとして保持している場合は、このプロパティを指定する必要が出ました。

Email 確認

email/resend ルーティングが GET から POST に変わりました。そのため、 view 側で CSRF を追加するなどの修正が必要です。

ヘルパー

str_plugarray_get などのヘルパー関数が今まで src/Illuminate/Support/helpers.php に実装されていましたが、 Illuminate\Support\Str または Illuminate\Support\Arr の静的メソッドを使うことが推奨されるようになりました。

また、 composer require laravel/helpers として別パッケージ化されたそれらのメソッドを要求することも可能です。

Localization

Lang::transLang::get に、 Lang::transChoiceLang::choice にメソッド名が変更になりました。

Lang::getLang::getFromJson は同じ扱いになったので、 Lang::getFromJson ではなく Lang::get を呼ぶことが推奨されるようになりました。

__('foo')@lang('foo') を使っている場合は特に変更は不要ですね。

キュー

php artisan queue:work を今まで呼んだ場合、失敗したジョブを無限に繰り返すようになっていました。今後は 1 度のみ再実行されます。無限に再実行したい場合は --tries=0 を指定します。

Input Facade

Input Facade は削除されました。 Input::get を使っていた場合は Request::input を使ってください。 Input はそのまま Request Facade に置き換え可能です。


他にも規模の小さい破壊的変更がありますが、ごらんのとおり今までと同じレベルの変更度合いですね。安心しました。

今後は 6.0.0 も 6.9.10 も同じコードで利用出来るようになるはずです(セキュリティリリースなど致命的なものは除く)。

また、大体半年置きにメジャーアップデートが行われていましたが、それは継続するようなので、恐らく来年の2月くらいに Laravel 7.0 が出るのではないかと思います。

※上記のリリースノートはまだ途中のものなので、今後他にも破壊的変更が含まれる可能性があることに注意してください。
※上記は要約で省略している部分もあります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP For Beginnersチュートリアル その14 基本的な検索フォームの実装

このシリーズの目的

体系的なwebコーディングの訓練ができるようになるためにPHPの初学のきっかけかつ、PHPでログインフォームやフォームを実装することができるようになるために

PHP For Beginners

上記のチュートリアルを進めているのでその備忘録。

前回

内容

今回のチュートリアル

PHP Multi Language Website Tutorial: Create Dynamic Website In 20 Minutes

このチュートリアルでやること

Webサイトの言語切り替えを行えるようになる

成果物

index.php
<?php 

    require_once "config.php";

?>

<!DOCTYPE html>
<html>
<head>
    <title><?php echo $lang['title'] ?></title>
    <link rel="stylesheet" type="text/css" href="css/index.css" media="all">
    <link rel="stylesheet" type="text/css" href="css/reset.css" media="all">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js">
    </script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" type="text/javascript">
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js">
    </script>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js">
    </script>


</head>
<body>
    <nav class="nav navbar navbar-expand-sm bg-dark navbar-dark ">
        <ul class="navbar-nav">
            <li class="nav-item"><a class="nav-link" href="#"><?php echo $lang['home'] ?></a></li>
            <li class="nav-item"><a class="nav-link" href="#"><?php echo $lang['pricing'] ?></a></li>
            <li class="nav-item"><a class="nav-link" href="#"><?php echo $lang['contact'] ?></a></li>
        </ul>
    </nav>
    <div class="container">
        <div class="row justify-content-center">
            <div class="main col-md-6">
                <h1><?php echo $lang['title'] ?></h1>
                <p><?php echo $lang['description'] ?></p>
            </div>
        </div>
    </div>

    <div class="footer bg-dark">
        <a class="footer-link" href="index.php?lang=en"><?php echo $lang['lang_en'] ?> </a>| <a class="footer-link" href="index.php?lang=ja"><?php echo $lang['lang_ja'] ?></a>
    </div>
</body>
</html>

config.php
<?php 

session_start();

if (!isset($_SESSION['lang'])) 
    $_SESSION['lang'] = "en";

    else if(isset($_GET['lang']) && $_SESSION['lang'] != $_GET['lang'] && !empty($_GET['lang'])) {
        if ($_GET['lang'] == "en") 
            $_SESSION['lang'] = "en";

        else if ($_GET['lang'] == "ja")
            $_SESSION['lang'] = "ja";
}

    require_once 'languages/'. $_SESSION['lang'] . ".php";

 ?>

ja.php
<?php 

     $lang = array(

        "title" => "ダイナミック・ウェブサイト",
        "home" => "トップ",
        "pricing" => "料金プラン",
        "contact" => "ご連絡先",
        "description" => "ようこそ、ダイナミック社のウェブサイトへ",
        "lang_en" => "英語",
        "lang_ja" => "日本語"
     );

 ?>

en.php
<?php 

     $lang = array(

        "title" => "Dynamic Website",
        "home" => "Home",
        "pricing" => "Pricing",
        "contact" => "Contact",
        "description" => "This is explanation about my amazing website!",
        "lang_en" => "English",
        "lang_ja" => "Japanese"
     );

 ?>

手順

1.サーバーにlanguageフォルダを作りそこに言語設定が記載されたPHPファイルを作る。
(ja.php、en.php)
コード見ればわかるように連想配列にキー値の形で記載していく。
今回はen.phpを基準として、それの互換としてja.phpを作るという流れで見てもらえればわかりやすい。

2.Session変数を用いて条件分岐させる。
今回はページが読み込まれた時にはWebサイトを英語表記し、あとはGETで切り替えられるようにする。

3.HTML要素の切り替えさせたい部分をPHPタグで用いて変数とキーをechoで出力する形に置き換える、詳しくは後述。

今回のコードの注釈

・言語ファイルの作り方

ja.php
<?php 

     $lang = array(

        "title" => "ダイナミック・ウェブサイト",
        "home" => "トップ",
        "pricing" => "料金プラン",
        "contact" => "ご連絡先",
        "description" => "ようこそ、ダイナミック社のウェブサイトへ",
        "lang_en" => "英語",
        "lang_ja" => "日本語"
     );

en.php
<?php 

     $lang = array(

        "title" => "Dynamic Website",
        "home" => "Home",
        "pricing" => "Pricing",
        "contact" => "Contact",
        "description" => "This is explanation about my amazing website!",
        "lang_en" => "English",
        "lang_ja" => "Japanese"
     );

 ?>

 ?>

言語切替させる箇所にそれぞれキーを設定して、そのキーを各言語共通にし、値をそれぞれの言語に合わせる形で書いていく。
そして、HTML要素の該当する部分をecho $lang['キー']の形でPHPタグを用いて置き換えていく。
こうすることで、キーさえ設定してまえばあとは実装したい言語に応じて基準となる言語と対照させてしまえば簡単に多言語に対応させることができるし、例えばページタイトルとメインタイトルには共通してtitleキーを設定することで一括して切り替えを行ったりすることもできる。

require_once
require_once 'languages/'. $_SESSION['lang'] . ".php";

require関数は指定されたパスのファイルを読み込む関数であるが、その派生のrequire_onceはファイルが既に読み込まれていた場合、そのファイルは読み込まないという処理が付随する。
今回はSessionにおいて最初に読み込まれるのはen.phpだということはコード見ればわかるが、ここで例えば英語orEngilishリンクをクリックしたとしても英語表示はそのままだがen.phpは読み込み直されることはない。
つまり、不必要な読み込みが行われないのでそれだけ処理は軽くなるということになる。
パスの指定方法は様々であるが同じ階層にあれば、そのままファイル名を、階層が違う場合は今回のようにパスを指定してファイル名を書く。
翻訳するとlanguageフォルダにある$_SESSION['lang']に代入された文字列.phpファイルを読み込むということになる。
ちなみに、PHPMaillerを使う際にも用いている関数なので、ここまでのチュートリアルを見直してみてほしい。

このチュートリアルを終えたら

Sessionについては過去のチュートリアルでも出てきたがここで一旦基本に立ち返って最低でも以下の2つの記事はしっかり理解しておきたい。

PHP $_SESSION(セッション変数)のすべて!【初心者向け基本】

【PHP超入門】Cookieとセッションについて

私もそうだがそろそろコードを見れば何が行われているかが、新しい関数などが出てこない時などを除けばおおよそ苦もなく理解できるようになった頃なので、そろそろアルゴリズムを考える上で、コードを書くだけではなく概念の勉強もしていかないといけないと感じる。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP For Beginnersチュートリアル その13 コンタクトフォームの練習

このシリーズの目的

体系的なwebコーディングの訓練ができるようになるためにPHPの初学のきっかけかつ、PHPでログインフォームやフォームを実装することができるようになるために

PHP For Beginners

上記のチュートリアルを進めているのでその備忘録。

前回

内容

今回のチュートリアル

PHP Tutorial: Create Contact Form & Send an Email With Attachment Using PHPMailer v6

このチュートリアルでやること

その7 の復習

成果物

sendemail.php
<?php   

        $msg = "";
        use PHPMailer\PHPMailer\PHPMailer;
        use PHPMailer\PHPMailer\Except;
        use PHPMailer\PHPMailer\SMPT;


        if (isset($_POST['submit'])) {
                $subject = $_POST['subject'];
                $email = $_POST['email'];
                $message = $_POST['message'];

        if (isset($_FILES['attachment']['name']) && $_FILES['attachment']['name'] != "") {
            $file = "attachment/". basename($_FILES['attachment']['name']);
            move_uploaded_file($_FILES['attachment']['tmp_name'],$file);

        } else
            $file = "";

            mb_language("japanese");
            mb_internal_encoding("UTF-8");
            require 'vendor/autoload.php';
            require 'Mailtrap-config.php';


                $mail = new PHPMailer();

                // Server

                $mail->isSMTP();
                $mail->SMTPAuth = true;
                $mail->Host = MAIL_HOST;
                $mail->Username = MAIL_USERNAME;
                $mail->Password = MAIL_PASSWORD;
                $mail->SMTPSecure = MAIL_ENCRPT;
                $mail->Port = SMTP_PORT;

                // Recipients
                $mail->setFrom($email);
                // $toname = mb_encode_mimeheader("$name", 'ISO-2022-JP', 'B', "\n");
                $mail->addAddress(TO);
                // $mail->addAttachment($attachment);

                // Content
                $mail->Subject = mb_encode_mimeheader("$subject", "ISO-2022-JP", "UTF-8");
                $mail->Body = mb_convert_encoding("$message","ISO-2022-JP", "UTF-8");
                $mail->CharSet = 'ISO-2022-JP';
                $mail->Encoding = "7bit";
                $mail->addAttachment($file);

                // Select HTML or NOT

                $mail->isHTML(true);

               if ($mail->send()) {
                    $msg = "Your Email has been sent, thank you!";
                } else {
                    $msg = "Something wrong happend! Please try again!";

                    unlink($file);//サーバーに毎回添付したファイルが保存されないようにする。送信先には問題なく添付される。
                }



        }

 ?>


<!DOCTYPE html>
<html>
<head>
    <title>PHP Mail Contact Form </title>
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
    <link rel="stylesheet" type="text/css" href="css/index.css">
</head>
<body>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-6 mail">

                <?php if ($msg != "") {
                    echo "$msg <br> <br>";
                }
                ?>

                <form action="sendmail.php" method="post" enctype="multipart/form-data">
                    <input class="form-control" type="text" name="subject" placeholder="Subject......"><br> 
                    <input class="form-control" type="text" name="email" placeholder="Email......"><br> 
                    <textarea class="form-control" name="message"  placeholder="What`up?"></textarea><br>   
                    <input class="form-control" type="file" name="attachment"><br>  
                    <input class="btn btn-primary" type="submit" name="submit" value="Send Email">
                </form>
            </div>

        </div>

    </div>


</body>
</html>

変更点

unlink関数を使い、サーバーにユーザー側がアップロードした添付ファイルが残らないようにする。
メールには問題なくて添付されて送られるので問題ない。
また。Bootstrapを用いたフォームなのでテキスト要素にはform-controlクラスを付随。

今回のコードの注釈

unlink
unlink($file);

指定した引数を削除する。
この場合は$fileには添付ファイルのパスが代入されているので、それを削除するということはそのファイルを削除することになる。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む