tag:crieit.net,2005:https://crieit.net/tags/PHP7/feed 「PHP7」の記事 - Crieit Crieitでタグ「PHP7」に投稿された最近の記事 2022-05-19T23:55:46+09:00 https://crieit.net/tags/PHP7/feed tag:crieit.net,2005:PublicArticle/18194 2022-05-19T23:55:46+09:00 2022-05-19T23:55:46+09:00 https://crieit.net/posts/php-phoenix-migrate-db-depend-other-db-20220521 (PHP) Phoenix でデータ関係が依存しているDBをマイグレーションする <p><a target="_blank" rel="nofollow noopener" href="https://github.com/lulco/phoenix">lulco/phoenix</a> でデータ関係が依存しているDBをマイグレーションする方法をメモ。</p> <p>ドキュメントが全然ないので地道にやっていきます……。</p> <h2 id="コード"><a href="#%E3%82%B3%E3%83%BC%E3%83%89">コード</a></h2> <p>早速コードを。</p> <h3 id="phoenix.php"><a href="#phoenix.php">phoenix.php</a></h3> <pre><code class="php">return [ 'migration_dirs' => [ 'first' => __DIR__ . '/migrations/first', 'second' => __DIR__ . '/migrations/second', ], 'environments' => [ 'local' => [ 'adapter' => 'mysql', 'host' => $_ENV['MYSQL_HOST'], 'port' => (int)$_ENV['MYSQL_PORT'], // optional 'username' => $_ENV['MYSQL_USER'], 'password' => $_ENV['MYSQL_PASSWORD'], 'db_name' => $_ENV['MYSQL_DBNAME'], 'charset' => 'utf8mb4', ], 'production' => [ 'adapter' => 'mysql', 'host' => $_ENV['MYSQL_HOST'], 'port' => (int)$_ENV['MYSQL_PORT'], // optional 'username' => $_ENV['MYSQL_USER'], 'password' => $_ENV['MYSQL_PASSWORD'], 'db_name' => $_ENV['MYSQL_DBNAME'], 'charset' => 'utf8mb4', ], ], 'default_environment' => 'local', 'log_table_name' => 'phoenix_log', ]; </code></pre> <p>肝は <code>migration_dirs</code> で <code>first</code> と <code>second</code> でそれぞれ対応するディレクトリを指定しているところ。</p> <h3 id="/migrations/first/hoge.php"><a href="#%2Fmigrations%2Ffirst%2Fhoge.php">/migrations/first/hoge.php</a></h3> <pre><code class="php"><?php namespace migrations; use Phoenix\Database\Element\Index; use Phoenix\Migration\AbstractMigration; class HogeMigration extends AbstractMigration { protected function up(): void { $this->table('hoge') ->addColumn('create_date', 'datetime') ->addColumn('name', 'string') ->create(); // insert $hogeData = [ [ 'name' => 'foo' ], [ 'name' => 'bar' ], [ 'name' => 'buz' ], // 略 ]; $rows = []; foreach ($hogeData as $key => $val) { $rows[] = [ 'create_date' => date('Y-m-d H:i:s'), 'name' => $val['name'], ]; } $this->insert('hoge', $rows); } protected function down(): void { $this->table('hoge') ->drop(); } } </code></pre> <p>まずは最初に <code>hoge</code> というDBを作成し、そこにデータを流し込みます。</p> <h3 id="/migrations/second/fuga.php"><a href="#%2Fmigrations%2Fsecond%2Ffuga.php">/migrations/second/fuga.php</a></h3> <pre><code class="php"><?php namespace migrations; use Phoenix\Database\Element\Index; use Phoenix\Migration\AbstractMigration; class FugaMigration extends AbstractMigration { protected function up(): void { $this->table('fuga') ->addColumn('create_date', 'datetime') ->addColumn('name', 'string') ->addColumn('hoge_id', 'integer') ->create(); // select hoge data $hogeRows = $this->select('SELECT id, name FROM hoge'); // insert $fugaData = [ [ 'name' => 'un' ], [ 'name' => 'deux' ], [ 'name' => 'trois' ], // 略 ]; $rows = []; foreach ($fugaData as $key => $val) { $id = 0; // hoge の name と fuga の name が一致する要素を array_filter() で抽出し、 array_values() で番号を詰める $hogeArray = array_values( array_filter( $hogeRows, function($hogeRow) use ($val) { $needle = mb_strlen(mb_strtolower($val[0])) > 0 ? mb_strtolower($val[0]) : 'NOTHING'; return mb_strpos(mb_strtolower($hogeRow['name']), $needle) !== false; } ) ); // $hogeArray の要素が1つ (一意に定まる) 場合はその値を、そうでない場合はデフォルト値をセット $id = count($hogeArray) === 1 ? (int)$hogeArray[0]['id'] : 0; $rows[] = [ 'create_date' => date('Y-m-d H:i:s'), 'name' => $val[0], 'hoge_id' => $id, // 上述でセットした id を使用 ]; } $this->insert('fuga', $rows); } protected function down(): void { $this->table('fuga') ->drop(); } } </code></pre> <p>次に <code>fuga</code> を作成し、そこに徐に <code>$this->select()</code> で SQL文 を発行、先程流し込んだデータを抽出します。</p> <p>その抽出したデータと <code>fuga</code> に流し込みたいデータを突き合わせて初期データを生成し、それを <code>fuga</code> に流し込む……という算段。</p> <p>これで意図したデータをマイグレーションすることができました。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/lulco/phoenix">GitHub - lulco\/phoenix: Framework agnostic database migrations for PHP.</a> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/lulco/phoenix/blob/master/src/Database/Adapter/PdoAdapter.php">phoenix\/PdoAdapter.php at master · lulco\/phoenix · GitHub</a></li> </ul></li> </ul> <p>ドキュメントがないのでコードを読んで普通に <code>select</code> とか使えそう、と思って試したりしていました。</p> arm-band tag:crieit.net,2005:PublicArticle/18193 2022-05-19T23:50:29+09:00 2022-05-19T23:50:29+09:00 https://crieit.net/posts/eloquent-connect-multiple-db-20220520 Eloquent で複数DBに接続する <p>単独の Eloquent を利用して異なるデータソースにアクセスしてみたのでメモしておきます。</p> <h2 id="コード"><a href="#%E3%82%B3%E3%83%BC%E3%83%89">コード</a></h2> <pre><code class="php"><?php declare(strict_types=1); use Illuminate\Database\Capsule\Manager; class DBConnection { private $db; public function __construct() { $this->db = new Manager; // default $this->db->addConnection([ 'driver' => 'mysql', 'host' => $_ENV['MYSQL1_HOST'], 'database' => $_ENV['MYSQL1_DBNAME'], 'username' => $_ENV['MYSQL1_USER'], 'password' => $_ENV['MYSQL1_PASSWORD'], 'charset' => 'utf8', ]); // second $this->db->addConnection([ 'driver' => 'mysql', 'host' => $_ENV['MYSQL2_HOST'], 'database' => $_ENV['MYSQL2_DBNAME'], 'username' => $_ENV['MYSQL2_USER'], 'password' => $_ENV['MYSQL2_PASSWORD'], 'charset' => 'utf8', ], 'second'); // addConnection() メソッドの第二引数に接続名を指定する (1つ目はなしだと default になる) $this->db->setAsGlobal(); $this->db->bootEloquent(); } // 略 } </code></pre> <p>肝はコメントにも記した通り <code>Manager</code>クラス の <code>addConnection()</code>メソッド について、第二引数に接続名を指定することです (1つ目はなしだと <code>default</code> になり、後で使用する分にも指定は不要) 。</p> <p>あ、しれっと書いていますが <code>dotenv</code> を使用した想定です。</p> <pre><code class="php"><br />$db = new DBConnection(); $secondDBrows = $db->connection('second')->table('hoge_db') ->where( /* 略 */ ) ->select( /* 略 */ ) ->get(); </code></pre> <p>こちらもしれっと書いていますがイメージとしては先程のDB接続用クラス <code>DBConnection</code> をインスタンス化して、その中から <code>connection()</code>メソッド で引数に先程指定した接続名を記述することで二つ目の接続を利用してDBにアクセスできる、ということです。</p> <p>これで意図したことを実装することができました。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://blog.bagooon.com/?p=1492">Laravelを使わず、直接PHPからEloquentを使用し、かつ複数のDBに接続する方法。</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://technoledge.net/composer-eloquent-illuminate-database/">LaravelのORM「Eloquent」を単体で使ってスクラッチ開発する | テクナレジ</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/18191 2022-05-18T00:03:50+09:00 2022-05-18T00:03:50+09:00 https://crieit.net/posts/eloquent-multiple-where-condition-closure-20220518 Eloquent で複合条件の抽出をする <p>Eloquent を実践的に使い始めたばかりなので初歩的なところですが、複合条件を組み立てるところについてメモ。</p> <h2 id="コード"><a href="#%E3%82%B3%E3%83%BC%E3%83%89">コード</a></h2> <p>やりたいこととしては、 <code>WHERE A AND B AND (C OR D)</code> という条件。</p> <pre><code class="php">$departName = [ '総務部', '営業部', ]; $dataRows = $dbConnect->table('hoge_db') ->where( [ ['user_id', '>', 23], ['age', '<', 42], ] ) ->where(function($query) use ($departName) { $query->orWhere('depart_name', '=', $departName[0]) ->orWhere('depart_name', '=', $departName[1]); }) ->select( 'fuga_db.name', 'fuga_db.attribute', 'fuga_db.parameter' ) ->join('fuga_db', 'hoge_db.user_id', '=', 'fuga_db.employee_id') ->get(); </code></pre> <p><code>$dbConnect</code> にDB接続情報が入ったインスタンスがあるという前提ですが、イメージとしてこのようなコードです。</p> <p>肝は以下。</p> <ul> <li><code>OR</code> 条件の括弧の中身を <code>where()</code>メソッド の中にクロージャとして無名関数で記述する。</li> <li>関数の引数はクエリ。そこに <code>orWhere()</code>メソッド を足していく。</li> <li>クロージャの外部の変数はスコープの関係で Undefined Variable になってしまうので <code>use</code>句 でクロージャ内に持ち込む</li> </ul> <p>これで意図した挙動になることを確認しました。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/Hwoa/items/542456b63e51895f9a55">Laravel5で「.. or ...) and (..」みたいな複雑な条件を書く - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/mitashun/items/7b1a6c4bb44acd08472e">【Laravel】EloquentでOR検索する方法 - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://umebius.com/laravel/querybuilder%E3%81%AB%E3%82%88%E3%82%8Band%E6%A4%9C%E7%B4%A2%E3%81%A8or%E6%A4%9C%E7%B4%A2%E3%81%AE%E8%A4%87%E5%90%88/">Eloquent\/QueryBuilderによるAnd検索とOr検索の複合 - Laravel5開発</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/17898 2021-12-29T00:16:11+09:00 2021-12-29T00:17:49+09:00 https://crieit.net/posts/test-centos8-lamp-for-almalinux-in-docker-20211229 (Docker) Almalinux を見据えて CentOS8 での環境構築を試験してみる <p>手前味噌で恐縮ですが、自作の LAMP環境 を検証する Docker Compose について。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/arm-band/docker_compose_ambergrease">GitHub - arm-band/docker_compose_ambergrease</a></li> </ul> <p>イメージを CentOS7 ベースで構築しているので、いずれは AlmaLinux なり Rocky Linux なりに移行しなければならないことは分かっていました。</p> <p>そこで、その以降を見据えて残り数日の命の CentOS8 で試験してみることにしました。なぜ AlmaLinux や Rocky Linux ではなくわざわざ CentOS8 かというと、いきなりそれらのOSに飛びついて何らかの不具合が発生したときに原因の切り分けで苦労するならば、まだ同じシリーズで差分が少ない (と想定される) CentOS8 で試験して、問題なければ次に進もう、という段階的な試験を想定したためです。</p> <h2 id="検証"><a href="#%E6%A4%9C%E8%A8%BC">検証</a></h2> <pre><code class="bash">docker run --name php7_cent8 -it centos:centos8 /bin/bash </code></pre> <p>まずはイメージを取得し、 bash に入ります。</p> <h3 id="Apache + PHP"><a href="#Apache+%2B+PHP">Apache + PHP</a></h3> <p>最初は Apache + PHP 。こちらについては、以前 <a target="_blank" rel="nofollow noopener" href="https://labor.ewigleere.net/2020/02/23/centos8-lamp-install-note/">CentOS8 をインストールして遊んだとき</a>にremiリポジトリの入り方が CentOS7 とは異なることが分かっていたので、多少手を加える必要があるだろう、と踏んでいました。</p> <pre><code class="bash"># \cp -pf /usr/share/zoneinfo/Japan /etc/localtime # </code></pre> <p>これは問題なし。</p> <pre><code class="bash"># dnf -y update && yum -y install epel-release sudo less iproute httpd-devel zip unzip openssl mod_ssl ## 略 Installed: apr-1.6.3-12.el8.x86_64 apr-devel-1.6.3-12.el8.x86_64 apr-util-1.6.1-6.el8.x86_64 apr-util-bdb-1.6.1-6.el8.x86_64 apr-util-devel-1.6.1-6.el8.x86_64 apr-util-openssl-1.6.1-6.el8.x86_64 brotli-1.0.6-3.el8.x86_64 centos-logos-httpd-85.8-2.el8.noarch cyrus-sasl-2.1.27-5.el8.x86_64 cyrus-sasl-devel-2.1.27-5.el8.x86_64 epel-release-8-11.el8.noarch expat-devel-2.2.5-4.el8.x86_64 groff-base-1.22.3-18.el8.x86_64 httpd-2.4.37-43.module_el8.5.0+1022+b541f3b1.x86_64 httpd-devel-2.4.37-43.module_el8.5.0+1022+b541f3b1.x86_64 httpd-filesystem-2.4.37-43.module_el8.5.0+1022+b541f3b1.noarch httpd-tools-2.4.37-43.module_el8.5.0+1022+b541f3b1.x86_64 libdb-devel-5.3.28-42.el8_4.x86_64 libpath_utils-0.2.1-39.el8.x86_64 libpkgconf-1.4.2-1.el8.x86_64 libtalloc-2.3.2-1.el8.x86_64 mailcap-2.1.48-3.el8.noarch mod_http2-1.15.7-3.module_el8.4.0+778+c970deab.x86_64 mod_ssl-1:2.4.37-43.module_el8.5.0+1022+b541f3b1.x86_64 ncurses-6.1-9.20180224.el8.x86_64 openldap-devel-2.4.46-18.el8.x86_64 perl-Carp-1.42-396.el8.noarch perl-Data-Dumper-2.167-399.el8.x86_64 perl-Digest-1.17-395.el8.noarch perl-Digest-MD5-2.55-396.el8.x86_64 perl-Encode-4:2.97-3.el8.x86_64 perl-Errno-1.28-420.el8.x86_64 perl-Exporter-5.72-396.el8.noarch perl-File-Path-2.15-2.el8.noarch perl-File-Temp-0.230.600-1.el8.noarch perl-Getopt-Long-1:2.50-4.el8.noarch perl-HTTP-Tiny-0.074-1.el8.noarch perl-IO-1.38-420.el8.x86_64 perl-IO-Socket-IP-0.39-5.el8.noarch perl-IO-Socket-SSL-2.066-4.module_el8.3.0+410+ff426aa3.noarch perl-MIME-Base64-3.15-396.el8.x86_64 perl-Mozilla-CA-20160104-7.module_el8.3.0+416+dee7bcef.noarch perl-Net-SSLeay-1.88-1.module_el8.3.0+410+ff426aa3.x86_64 perl-PathTools-3.74-1.el8.x86_64 perl-Pod-Escapes-1:1.07-395.el8.noarch perl-Pod-Perldoc-3.28-396.el8.noarch perl-Pod-Simple-1:3.35-395.el8.noarch perl-Pod-Usage-4:1.69-395.el8.noarch perl-Scalar-List-Utils-3:1.49-2.el8.x86_64 perl-Socket-4:2.027-3.el8.x86_64 perl-Storable-1:3.11-3.el8.x86_64 perl-Term-ANSIColor-4.06-396.el8.noarch perl-Term-Cap-1.17-395.el8.noarch perl-Text-ParseWords-3.30-395.el8.noarch perl-Text-Tabs+Wrap-2013.0523-395.el8.noarch perl-Time-Local-1:1.280-1.el8.noarch perl-URI-1.73-3.el8.noarch perl-Unicode-Normalize-1.25-396.el8.x86_64 perl-constant-1.33-396.el8.noarch perl-interpreter-4:5.26.3-420.el8.x86_64 perl-libnet-3.11-3.el8.noarch perl-libs-4:5.26.3-420.el8.x86_64 perl-macros-4:5.26.3-420.el8.x86_64 perl-parent-1:0.237-1.el8.noarch perl-podlators-4.11-1.el8.noarch perl-threads-1:2.21-2.el8.x86_64 perl-threads-shared-1.58-2.el8.x86_64 pkgconf-1.4.2-1.el8.x86_64 pkgconf-m4-1.4.2-1.el8.noarch pkgconf-pkg-config-1.4.2-1.el8.x86_64 sscg-2.3.3-14.el8.x86_64 sudo-1.8.29-7.el8_4.1.x86_64 unzip-6.0-45.el8_4.x86_64 zip-3.0-23.el8.x86_64 Complete! </code></pre> <p>OK。</p> <pre><code class="bash"># dnf -y upgrade ## 略 Upgraded: epel-release-8-13.el8.noarch Complete! </code></pre> <p>特に大きな差分もなさそうです。OK。</p> <h3 id="remiリポジトリ"><a href="#remi%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA">remiリポジトリ</a></h3> <pre><code class="bash"># rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-8.rpm Retrieving http://rpms.famillecollet.com/enterprise/remi-release-8.rpm warning: /var/tmp/rpm-tmp.hlvLxe: Header V4 RSA/SHA256 Signature, key ID 5f11735a: NOKEY Verifying... ################################# [100%] Preparing... ################################# [100%] Updating / installing... 1:remi-release-8.5-2.el8.remi ################################# [100%] # rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi2021 # </code></pre> <p>OK。 CentOS8 用のリポジトリに切り替えました。鍵についてはすぐ <code>RPM-GPG-KEY-remi2022</code> にしなければならないでしょうけど。</p> <h4 id="dnf"><a href="#dnf">dnf</a></h4> <pre><code class="bash"># dnf config-manager --enable remi && dnf config-manager --enable remi-php74 No such command: config-manager. Please use /usr/bin/dnf --help It could be a DNF plugin command, try: "dnf install 'dnf-command(config-manager)'" </code></pre> <p><code>remi-php74</code> に指定で躓くかと思いきや、そもそも <code>config-manager</code> がない、と?</p> <p>元々は <code>yum-config-manager</code> だったのですが、 CentOS8 であれば <code>dnf</code> ベースの方が良いだろう、ということで置き換えてはみましたが、ダメですか……。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://blog.trippyboy.com/2021/terraform/almalinux%E3%81%ABterraform%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92yum%E3%81%A7%E5%B0%8E%E5%85%A5%E3%81%99%E3%82%8B%E3%81%AE%E5%B7%BB/">Almalinuxにterraformコマンドをyumで導入するの巻 - TrippyBoyの愉快な日々</a></li> </ul> <p>こちらより <code>dnf install -y dnf-plugins-core</code> してみます。</p> <pre><code class="bash"># dnf install dnf-plugins-core ## 略 Installed: dbus-glib-0.110-2.el8.x86_64 dnf-plugins-core-4.0.21-3.el8.noarch python3-dateutil-1:2.6.1-6.el8.noarch python3-dbus-1.2.4-15.el8.x86_64 python3-dnf-plugins-core-4.0.21-3.el8.noarch python3-six-1.11.0-8.el8.noarch Complete! </code></pre> <p>OK。</p> <h4 id="remi + PHP"><a href="#remi+%2B+PHP">remi + PHP</a></h4> <pre><code class="bash"># dnf config-manager --enable remi && dnf config-manager --enable remi-php74 Error: No matching repo to modify: remi-php74. </code></pre> <p>……やはり <code>remi-php74</code> で引っかかりましたか。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://mebee.info/2020/03/12/post-7365/">CentOs8 php7.4をインストールする | mebee</a></li> </ul> <p>……想定していたものとは少し違うやり方ですが、試してみましょう。</p> <pre><code class="bash"># dnf module reset php ## 略 Remi's RPM repository for Enterprise Linux 8 - x86_64 598 kB/s | 3.9 MB 00:06 Last metadata expiration check: 0:00:03 ago on DDD dd mmm yyyy hh:ii:ss AM UTC. Dependencies resolved. Nothing to do. Complete! </code></pre> <p>OK。</p> <pre><code class="bash"># dnf module install -y php:remi-7.4 ## 略 Installed: libedit-3.1-23.20170329cvs.el8.x86_64 libxslt-1.1.32-6.el8.x86_64 nginx-filesystem-1:1.14.1-9.module_el8.0.0+184+e34fea82.noarch oniguruma5php-6.9.7.1-1.el8.remi.x86_64 php-cli-7.4.27-1.el8.remi.x86_64 php-common-7.4.27-1.el8.remi.x86_64 php-fpm-7.4.27-1.el8.remi.x86_64 php-json-7.4.27-1.el8.remi.x86_64 php-mbstring-7.4.27-1.el8.remi.x86_64 php-xml-7.4.27-1.el8.remi.x86_64 Complete! # php --version PHP 7.4.27 (cli) (built: Dec 14 2021 17:17:06) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies </code></pre> <p>OK。入りましたね。これに従い該当箇所を書き換えます。</p> <pre><code class="dockerfile"># enable repository remi & remi-php74 #RUN dnf config-manager --enable remi && dnf config-manager --enable remi-php74 # disable default module RUN dnf module reset -y php RUN dnf module install -y php:remi-7.4 ## 略 # disable repository remi & remi-php74 #RUN dnf config-manager --disable remi && dnf config-manager --disable remi-php74 </code></pre> <p><code>config-manager</code> によるリポジトリ使用のオン・オフの切り替えを削除しました。</p> <pre><code class="bash"># dnf -y install php php-devel php-pdo php-mysqlnd php-mbstring php-gd php-pear php-pecl-apc-devel zlib-devel php-xml php-mcrypt php-pecl-xdebug ## 略 Installed: autoconf-2.69-29.el8.noarch automake-1.16.1-7.el8.noarch cmake-filesystem-3.20.2-4.el8.x86_64 cpp-8.5.0-4.el8_5.x86_64 dejavu-fonts-common-2.35-7.el8.noarch dejavu-sans-fonts-2.35-7.el8.noarch emacs-filesystem-1:26.1-7.el8.noarch fontconfig-2.13.1-4.el8.x86_64 fontpackages-filesystem-1.44-22.el8.noarch freetype-2.9.1-4.el8_3.1.x86_64 fribidi-1.0.4-8.el8.x86_64 gcc-8.5.0-4.el8_5.x86_64 gcc-c++-8.5.0-4.el8_5.x86_64 gd3php-2.3.3-4.el8.remi.x86_64 glibc-devel-2.28-164.el8.x86_64 glibc-headers-2.28-164.el8.x86_64 graphite2-1.3.10-10.el8.x86_64 harfbuzz-1.7.5-3.el8.x86_64 isl-0.16.1-6.el8.x86_64 jbigkit-libs-2.1-14.el8.x86_64 kernel-headers-4.18.0-348.2.1.el8_5.x86_64 keyutils-libs-devel-1.5.10-9.el8.x86_64 krb5-devel-1.18.2-14.el8.x86_64 libX11-1.6.8-5.el8.x86_64 libX11-common-1.6.8-5.el8.noarch libXau-1.0.9-3.el8.x86_64 libXpm-3.5.12-8.el8.x86_64 libcom_err-devel-1.45.6-2.el8.x86_64 libimagequant-2.12.5-1.el8.x86_64 libjpeg-turbo-1.5.3-12.el8.x86_64 libkadm5-1.18.2-14.el8.x86_64 libmcrypt-2.5.8-26.el8.x86_64 libmpc-1.1.0-9.1.el8.x86_64 libpng-2:1.6.34-5.el8.x86_64 libraqm-0.7.0-4.el8.x86_64 libselinux-devel-2.9-5.el8.x86_64 libsepol-devel-2.9-3.el8.x86_64 libsodium-1.0.18-2.el8.x86_64 libstdc++-devel-8.5.0-4.el8_5.x86_64 libtiff-4.0.9-20.el8.x86_64 libtool-2.4.6-25.el8.x86_64 libverto-devel-0.3.0-5.el8.x86_64 libwebp-1.0.0-5.el8.x86_64 libxcb-1.13.1-1.el8.x86_64 libxcrypt-devel-4.1.1-6.el8.x86_64 libxml2-devel-2.9.7-9.el8_4.2.x86_64 m4-1.4.18-7.el8.x86_64 make-1:4.2.1-10.el8.x86_64 openssl-devel-1:1.1.1k-5.el8_5.x86_64 pcre2-devel-10.32-2.el8.x86_64 pcre2-utf16-10.32-2.el8.x86_64 pcre2-utf32-10.32-2.el8.x86_64 perl-Thread-Queue-3.13-1.el8.noarch php-7.4.27-1.el8.remi.x86_64 php-devel-7.4.27-1.el8.remi.x86_64 php-fedora-autoloader-1.0.1-2.el8.remi.noarch php-gd-7.4.27-1.el8.remi.x86_64 php-mysqlnd-7.4.27-1.el8.remi.x86_64 php-opcache-7.4.27-1.el8.remi.x86_64 php-pdo-7.4.27-1.el8.remi.x86_64 php-pear-1:1.10.13-1.el8.remi.noarch php-pecl-apcu-5.1.21-1.el8.remi.7.4.x86_64 php-pecl-apcu-devel-5.1.21-1.el8.remi.7.4.x86_64 php-pecl-mcrypt-1.0.4-1.el8.remi.7.4.x86_64 php-pecl-xdebug-2.9.8-1.el8.remi.7.4.x86_64 php-process-7.4.27-1.el8.remi.x86_64 php-sodium-7.4.27-1.el8.remi.x86_64 xz-devel-5.2.4-3.el8.x86_64 zlib-devel-1.2.11-17.el8.x86_64 Complete! </code></pre> <p>OK。</p> <pre><code class="bash"># php -r &quot;copy('https://getcomposer.org/installer', 'composer-setup.php');&quot; && php composer-setup.php && php -r &quot;unlink('composer-setup.php');&quot; && mv composer.phar /usr/local/bin/composer All settings correct for using Composer Downloading... Composer (version 2.2.1) successfully installed to: /etc/yum.repos.d/composer.phar Use it: php composer.phar # composer --version Composer version 2.2.1 2021-12-22 22:21:31 </code></pre> <p>Composer も入りました。</p> <pre><code class="bash"># mkdir /var/log/php # chown apache /var/log/php # chmod 755 /var/log/php # mkdir -p /etc/ssl/private </code></pre> <p>まあこの辺りは普通に。</p> <h3 id="SSL"><a href="#SSL">SSL</a></h3> <pre><code class="bash"># openssl req -new -newkey rsa:2048 -nodes -out /etc/ssl/private/server.csr -keyout /etc/ssl/private/server.key -subj &quot;/C=/ST=/L=/O=/OU=/CN=*.lvh.me&quot; ## 略 # openssl x509 -days 365 -req -signkey /etc/ssl/private/server.key -in /etc/ssl/private/server.csr -out /etc/ssl/private/server.crt Signature ok subject=CN = *.lvh.me Getting Private key </code></pre> <p>OK。</p> <h3 id="Apache の設定ファイル"><a href="#Apache+%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB">Apache の設定ファイル</a></h3> <h4 id="ssl.conf"><a href="#ssl.conf">ssl.conf</a></h4> <pre><code class="bash"># cat /etc/httpd/conf.d/ssl.conf ## 略 </code></pre> <p>表示させたSSL用の設定を現行のものと差し替えます。ただし、現行の設定をなるべく引き継ぐように。これは他の設定ファイルも同様です。</p> <pre><code class="conf">- SSLRandomSeed startup file:/dev/urandom 256 - SSLRandomSeed connect builtin - SSLCipherSuite HIGH:3DES:!aNULL:!MD5:!SEED:!IDEA </code></pre> <p>現行にあったこれらの行は削除。</p> <pre><code class="conf">+ SSLHonorCipherOrder on </code></pre> <p>これは新しく追加されていました。</p> <pre><code class="conf">SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 </code></pre> <p>プロトコルについては念のため現行の設定を引き継ぎ。流石にもう SSLv2 なんて存在しないでしょうけど……。</p> <pre><code class="conf">- <Files ~ "\.(cgi|shtml|phtml|php3?)$"> + <FilesMatch "\.(cgi|shtml|phtml|php)$"> SSLOptions +StdEnvVars - </Files> + </FilesMatch> </code></pre> <p>微妙にディレクティブの表現が変わっていますが、影響はなさそうなので変更を受け入れます。</p> <h4 id="php.conf"><a href="#php.conf">php.conf</a></h4> <pre><code class="bash"># cat /etc/httpd/conf.d/php.conf ## 略 # Redirect to local php-fpm if mod_php (5 or 7) is not available <IfModule !mod_php5.c> <IfModule !mod_php7.c> # Enable http authorization headers SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1 <FilesMatch \.(php|phar)$> SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost" </FilesMatch> </IfModule> </IfModule> </code></pre> <p>こちらは最後の部分に追記がありますね。これはそのまま受け入れ。</p> <h4 id="php.ini"><a href="#php.ini">php.ini</a></h4> <pre><code class="bash"># cat /etc/php.ini ## 略 </code></pre> <p>こちらも設定を引き継ぎ、といっても現行の設定と変更点はなく(自前の設定を引き継いだ) 差分としてはコメントの文字列くらい。</p> <h3 id="AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.0.2.1. Set the 'ServerName' directive globally to suppress this message"><a href="#AH00558%3A+httpd%3A+Could+not+reliably+determine+the+server%27s+fully+qualified+domain+name%2C+using+192.0.2.1.+Set+the+%27ServerName%27+directive+globally+to+suppress+this+message">AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.0.2.1. Set the 'ServerName' directive globally to suppress this message</a></h3> <p>Apache を起動しようとしたところ、</p> <blockquote> <p>AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.0.2.1. Set the 'ServerName' directive globally to suppress this message</p> </blockquote> <p>のエラーメッセージがログに記録されて起動してこない現象に遭遇。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/sachiko-kame/items/a6deebbad207d627b598">[Docker]AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using ***.***.*.*. Set the 'ServerName' directive globally to suppress this message - Qiita</a></li> </ul> <p>そういえば元々の Dockerfile には記述していましたが、 <code>httpd.conf</code> への追記をしていませんでした。</p> <pre><code class="bash">echo ServerName www.example.com:80 >> /etc/httpd/conf/httpd.conf </code></pre> <p>これでOK。</p> <pre><code class="bash"># httpd -v Server version: Apache/2.4.37 (centos) Server built: Nov 12 2021 04:57:27 </code></pre> <p>バージョンも拾えました。</p> <h3 id="(2)No such file or directory: AH02454: FCGI: attempt to connect to Unix domain socket /run/php-fpm/www.sock (*) failed"><a href="#%282%29No+such+file+or+directory%3A+AH02454%3A+FCGI%3A+attempt+to+connect+to+Unix+domain+socket+%2Frun%2Fphp-fpm%2Fwww.sock+%28%2A%29+failed">(2)No such file or directory: AH02454: FCGI: attempt to connect to Unix domain socket /run/php-fpm/www.sock (*) failed</a></h3> <p>これで Apache も起動してきたのでブラウザで表示確認、ということで <code>phpinfo()</code> でも表示させようかとファイルを用意して <code>curl</code> してみると……</p> <blockquote> <p>Service Unavailable</p> <p>The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.</p> </blockquote> <p>503エラーが出てしまいました。</p> <blockquote> <p>(2)No such file or directory: AH02454: FCGI: attempt to connect to Unix domain socket /run/php-fpm/www.sock (*) failed</p> </blockquote> <p>Apache のエラーログには上述のログが記録されていました。</p> <p>今までとは異なる方法で PHP をインストールしたら、どうやら php-fpm (CGIモード) で動作しようとしてしまっているようです。</p> <p>今回の環境ではCGI版かモジュール版かはあまり考慮しておらず、Webサーバも Apache のためモジュール版でも良いと判断。</p> <p>動作を切り替えます。</p> <pre><code class="bash"># less /etc/httpd/conf/httpd.conf ## 略 Include conf.modules.d/*.conf </code></pre> <p>念のためモジュール読み込みの記述があることを確認。</p> <pre><code class="bash"># ls /etc/httpd/conf.modules.d/ 00-base.conf 00-lua.conf 00-optional.conf 00-ssl.conf 01-cgi.conf 10-proxy_h2.conf README 00-dav.conf 00-mpm.conf 00-proxy.conf 00-systemd.conf 10-h2.conf 15-php.conf </code></pre> <p>関係しそうなのは <code>00-mpm.conf</code>, <code>01-cgi.conf</code>, <code>15-php.conf</code> 辺りでしょうか。</p> <pre><code class="bash"># less /etc/httpd/conf.modules.d/15-php.conf # Cannot load both php5 and php7 modules <IfModule !mod_php5.c> <IfModule prefork.c> LoadModule php7_module modules/libphp7.so </IfModule> </IfModule> </code></pre> <p>ここはそのまま。</p> <pre><code class="bash"># less /etc/httpd/conf.modules.d/01-cgi.conf # This configuration file loads a CGI module appropriate to the MPM # which has been configured in 00-mpm.conf. mod_cgid should be used # with a threaded MPM; mod_cgi with the prefork MPM. <IfModule mpm_worker_module> LoadModule cgid_module modules/mod_cgid.so </IfModule> <IfModule mpm_event_module> LoadModule cgid_module modules/mod_cgid.so </IfModule> <IfModule mpm_prefork_module> LoadModule cgi_module modules/mod_cgi.so </IfModule> </code></pre> <p>ここもそのまま。</p> <pre><code class="bash"># less /etc/httpd/conf.modules.d/00-mpm.conf # Select the MPM module which should be used by uncommenting exactly # one of the following LoadModule lines. See the httpd.conf(5) man # page for more information on changing the MPM. # prefork MPM: Implements a non-threaded, pre-forking web server # See: http://httpd.apache.org/docs/2.4/mod/prefork.html # # NOTE: If enabling prefork, the httpd_graceful_shutdown SELinux # boolean should be enabled, to allow graceful stop/shutdown. # #LoadModule mpm_prefork_module modules/mod_mpm_prefork.so # worker MPM: Multi-Processing Module implementing a hybrid # multi-threaded multi-process web server # See: http://httpd.apache.org/docs/2.4/mod/worker.html # #LoadModule mpm_worker_module modules/mod_mpm_worker.so # event MPM: A variant of the worker MPM with the goal of consuming # threads only for connections with active processing # See: http://httpd.apache.org/docs/2.4/mod/event.html # LoadModule mpm_event_module modules/mod_mpm_event.so </code></pre> <p>変更するのはここ。</p> <pre><code>- #LoadModule mpm_prefork_module modules/mod_mpm_prefork.so + LoadModule mpm_prefork_module modules/mod_mpm_prefork.so - LoadModule mpm_event_module modules/mod_mpm_event.so # LoadModule mpm_event_module modules/mod_mpm_event.so </code></pre> <p>上述のうち2ヶ所を反転させます。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.out48.com/archives/5636/">CentOSにApacheとPHP入れてPHPファイルを表示しようとしたら503エラー Output48</a></li> </ul> <p>これでOK。起動も確認できました。</p> <p>テンプレートとして上述を反転させた <code>00-mpm.conf</code> を用意し、エントリポイントでファイルコピーして設定を上書きすることで対処しました。</p> <p><a href="https://crieit.now.sh/upload_images/abe7eb81a2b7f6580feb784cb81cdf1361cb21ea49eef.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/abe7eb81a2b7f6580feb784cb81cdf1361cb21ea49eef.jpg?mw=700" alt="最終的に AlmaLinux の Docker Compose で起動、確認した phpinfo() の画面" /></a></p> <p>最終的に AlmaLinux の Docker Compose を作成して起動し、ブラウザで該当の PHPファイル にアクセスし、 <code>phpinfo()</code> の画面が表示されることを確認できました。OK。</p> <h3 id="SSLCertificateFile: file '/etc/pki/tls/certs/localhost.crt' does not exist or is empty"><a href="#SSLCertificateFile%3A+file+%27%2Fetc%2Fpki%2Ftls%2Fcerts%2Flocalhost.crt%27+does+not+exist+or+is+empty">SSLCertificateFile: file '/etc/pki/tls/certs/localhost.crt' does not exist or is empty</a></h3> <p>上述のエラーの他に</p> <blockquote> <p>SSLCertificateFile: file '/etc/pki/tls/certs/localhost.crt' does not exist or is empty</p> </blockquote> <p>localhost のSSL証明書がない、というエラーにも遭遇しました。</p> <p>なければ作れば良いだけ、上述で</p> <pre><code class="bash">echo ServerName www.example.com:80 >> /etc/httpd/conf/httpd.conf </code></pre> <p>としているので、このダミードメインを使います。</p> <pre><code class="bash"># openssl req -new -newkey rsa:2048 -nodes -out /etc/pki/tls/certs/localhost.csr -keyout /etc/pki/tls/private/localhost.key -subj &quot;/C=/ST=/L=/O=/OU=/CN=www.example.com&quot; ## 略 # openssl x509 -days 365 -req -signkey /etc/pki/tls/private/localhost.key -in /etc/pki/tls/certs/localhost.csr -out /etc/pki/tls/certs/localhost.crt Signature ok subject=CN = www.example.com Getting Private key </code></pre> <p>これでOK。 <code>ssl.conf</code> には記述はあるのですが……。</p> <h3 id="MySQL"><a href="#MySQL">MySQL</a></h3> <p>次に MySQL 側を。こちらはほぼ手を加える必要はないという想定です。</p> <pre><code class="bash"># dnf localinstall https://dev.mysql.com/get/mysql80-community-release-el8-2.noarch.rpm ## 略 Package mysql80-community-release-el8-2.noarch is already installed. Dependencies resolved. Nothing to do. Complete! </code></pre> <p>CentOS8 用ということでリポジトリの入れ方を少し変更。</p> <pre><code class="bash"># ls /etc/yum.repo.d/ CentOS-Linux-AppStream.repo CentOS-Linux-Media.repo epel-testing.repo CentOS-Linux-BaseOS.repo CentOS-Linux-Plus.repo mysql-community.repo CentOS-Linux-ContinuousRelease.repo CentOS-Linux-PowerTools.repo mysql-community-source.repo CentOS-Linux-Debuginfo.repo CentOS-Linux-Sources.repo remi-modular.repo CentOS-Linux-Devel.repo epel-modular.repo remi.repo CentOS-Linux-Extras.repo epel-playground.repo remi-safe.repo CentOS-Linux-FastTrack.repo epel.repo CentOS-Linux-HighAvailability.repo epel-testing-modular.repo </code></pre> <p><code>mysql-community.repo</code>, <code>mysql-community-source.repo</code> の2つが追加されたことを確認。</p> <pre><code class="bash"># dnf module disable mysql ## 略 Complete! </code></pre> <p>デフォルトの MySQL がいると邪魔になるので無効化して</p> <pre><code class="bash"># dnf -y install mysql-community-devel mysql-community-server ## 略 Installed: mysql-community-client-8.0.27-1.el8.x86_64 mysql-community-client-plugins-8.0.27-1.el8.x86_64 mysql-community-common-8.0.27-1.el8.x86_64 mysql-community-devel-8.0.27-1.el8.x86_64 mysql-community-libs-8.0.27-1.el8.x86_64 mysql-community-server-8.0.27-1.el8.x86_64 net-tools-2.0-0.52.20160912git.el8.x86_64 Complete! </code></pre> <p>インストール完了。</p> <pre><code class="bash"># mysqld --version /usr/sbin/mysqld Ver 8.0.27 for Linux on x86_64 (MySQL Community Server - GPL) </code></pre> <p>デフォルトでは <code>8.0.26</code> だったバージョンが地味に <code>8.0.27</code> に上がりました。</p> <pre><code class="bash"># grep 'temporary password' /var/log/mysqld.log yyyy-mm-ddThh:ii:ss.zzzzzzZ 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: XXXXXXXXXXXX </code></pre> <p>初期パスワードの出現位置が半角スペース区切りで13番目であることを確認。これはエントリポイントで <code>awk</code> を使って抽出、初期パスワードを環境変数の値で書き換える処理で使用するため個人的には重要ポイント。ここは変更しなくて良さそうです。</p> <pre><code class="bash"># cat /etc/my.cnf [mysqld] ## 略 datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid </code></pre> <p>デフォルトで4つパラメータが指定されています。うち3つはテンプレートの設定ファイルに記述がされているので不要、 <code>pid-file</code> だけ現時点では指定がないため、これだけ <code>base.cnf</code> に移植します。</p> <p><code>/etc/my.cnf</code> には上述4つを削除した代わりに <code>!includedir /etc/my.cnf.d</code> を末尾に追加したものを現行の <code>my.cnf</code> と差し替え。</p> <p>これで MySQL 側は良さそうです。</p> <p>なお、 phpMyAdmin は公式イメージをそのまま使っているので変更なし。</p> <p>以上で一通り動作検証できたので、これをベースに AlmaLinux 用に書き換えれば良さそうです。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <h3 id="Docker"><a href="#Docker">Docker</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://hub.docker.com/_/almalinux?tab=tags">almalinux Tags | Docker Hub</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://hub.docker.com/_/centos?tab=tags">centos Tags | Docker Hub</a></li> </ul> <h3 id="AlmaLinux"><a href="#AlmaLinux">AlmaLinux</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://blog.apar.jp/linux/15554/">AlmaLinux 8.4 LAMPサーバインストールメモ【Apache2.4+MySQL8.0+PHP7.4】 | あぱーブログ</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/yamada-hakase/items/17b41d33e30232b69fe2">AlmaLinuxを使ってみた(後編) - Qiita</a></li> </ul> <h3 id="dnf"><a href="#dnf">dnf</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://blog.trippyboy.com/2021/terraform/almalinux%E3%81%ABterraform%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92yum%E3%81%A7%E5%B0%8E%E5%85%A5%E3%81%99%E3%82%8B%E3%81%AE%E5%B7%BB/">Almalinuxにterraformコマンドをyumで導入するの巻 - TrippyBoyの愉快な日々</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/questions/40937056/dnf-missing-config-manager-command">linux - DNF missing config-manager command - Stack Overflow</a></li> </ul> <h3 id="remi"><a href="#remi">remi</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="http://rpms.remirepo.net/">Remi's RPM repository</a></li> </ul> <h3 id="AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.0.2.1. Set the 'ServerName' directive globally to suppress this message"><a href="#AH00558%3A+httpd%3A+Could+not+reliably+determine+the+server%27s+fully+qualified+domain+name%2C+using+192.0.2.1.+Set+the+%27ServerName%27+directive+globally+to+suppress+this+message">AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.0.2.1. Set the 'ServerName' directive globally to suppress this message</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/sachiko-kame/items/a6deebbad207d627b598">[Docker]AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using ***.***.*.*. Set the 'ServerName' directive globally to suppress this message - Qiita</a></li> </ul> <h3 id="PHP"><a href="#PHP">PHP</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://mebee.info/2020/03/12/post-7365/">CentOs8 php7.4をインストールする | mebee</a></li> </ul> <h3 id="(2)No such file or directory: AH02454: FCGI: attempt to connect to Unix domain socket /run/php-fpm/www.sock (*) failed"><a href="#%282%29No+such+file+or+directory%3A+AH02454%3A+FCGI%3A+attempt+to+connect+to+Unix+domain+socket+%2Frun%2Fphp-fpm%2Fwww.sock+%28%2A%29+failed">(2)No such file or directory: AH02454: FCGI: attempt to connect to Unix domain socket /run/php-fpm/www.sock (*) failed</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/questions/58365479/no-such-file-or-directory-ah02454-fcgi-attempt-to-connect-to-unix-domain-sock">apache - No such file or directory: AH02454: FCGI: attempt to connect to Unix domain socket /var/run/php/php5.6-fpm.sock (*) failed - Stack Overflow</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://www.out48.com/archives/5636/">CentOSにApacheとPHP入れてPHPファイルを表示しようとしたら503エラー Output48</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://ja.stackoverflow.com/questions/46727/amazon-linux2%E3%81%A7%E3%82%A8%E3%83%A9%E3%83%BCah02454%E3%82%84ah01079%E3%81%AA%E3%81%A9%E3%81%8C%E5%87%BA%E3%81%A6httpd%E3%81%8C%E3%81%86%E3%81%BE%E3%81%8F%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%BE%E3%81%9B%E3%82%93">php - amazon-linux2でエラーAH02454やAH01079などが出てhttpdがうまく起動しません - スタック・オーバーフロー</a></li> </ul> <h3 id="php-fpm"><a href="#php-fpm">php-fpm</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/kotarella1110/items/634f6fafeb33ae0f51dc">nginx と PHP-FPM の仕組みをちゃんと理解しながら PHP の実行環境を構築する - Qiita</a></li> </ul> <h3 id="SSLCertificateFile: file '/etc/pki/tls/certs/localhost.crt' does not exist or is empty"><a href="#SSLCertificateFile%3A+file+%27%2Fetc%2Fpki%2Ftls%2Fcerts%2Flocalhost.crt%27+does+not+exist+or+is+empty">SSLCertificateFile: file '/etc/pki/tls/certs/localhost.crt' does not exist or is empty</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://daredemose.com/linux/ssl/">SSL/TLS | 初心者向けプログラミング講座</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://hacknote.jp/archives/51779/">いつの間にか作られてる /etc/pki/tls/certs/localhost.crt と /etc/pki/tls/private/localhost.key の謎 | ハックノート</a></li> </ul> <h3 id="MySQL"><a href="#MySQL">MySQL</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/yasushi-jp/items/1579c301075d693a2a36">MySQL 8.0 を CentOS 8.1 にインストールする手順 - Qiita</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/17518 2021-07-15T22:35:47+09:00 2021-07-15T22:35:47+09:00 https://crieit.net/posts/guzzule-error-in-xampp-20210715 Guzzle Client で cURL error 60: SSL certificate problem: self signed certificate in certificate chain エラー <h2 id="現象"><a href="#%E7%8F%BE%E8%B1%A1">現象</a></h2> <p>XAMPP 上で <a target="_blank" rel="nofollow noopener" href="https://packagist.org/packages/guzzlehttp/guzzle">Guzzle Client</a> を利用しようとしたら以下のようなエラーが発生しました。</p> <blockquote> <p>GuzzleHttp\Exception\RequestException: cURL error 60: SSL certificate problem: self signed certificate in certificate chain (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://example.jp/</p> </blockquote> <h2 id="前提"><a href="#%E5%89%8D%E6%8F%90">前提</a></h2> <p>この XAMPP 環境は以前<a target="_blank" rel="nofollow noopener" href="https://labor.ewigleere.net/2020/02/24/xampp-php-update/">XAMPPのPHPのバージョンをアップグレードする ( 7.1.7 → 7.4.3 )</a>で PHP のバージョンを上げていました。</p> <h2 id="調査"><a href="#%E8%AA%BF%E6%9F%BB">調査</a></h2> <p>XAMPP の PHP について <code>php.ini</code> を確認。</p> <pre><code class="ini">extension=curl </code></pre> <p>まずここはOK。</p> <pre><code class="ini">[curl] ; A default value for the CURLOPT_CAINFO option. This is required to be an ; absolute path. ;curl.cainfo = </code></pre> <p>あ、SSL証明書の指定がないですね。</p> <p>ちなみに元々 XAMPP に入っていたバージョンの <code>php.ini</code> では</p> <pre><code class="ini">[curl] ; A default value for the CURLOPT_CAINFO option. This is required to be an ; absolute path. curl.cainfo="PATH:\TO\xampp\apache\bin\curl-ca-bundle.crt" </code></pre> <p>SSL証明書の指定がありました。</p> <p>パス先にSSL証明書が存在していることを確認の上、パスを現行の <code>php.ini</code> に貼り付けます。</p> <pre><code class="ini">[curl] ; A default value for the CURLOPT_CAINFO option. This is required to be an ; absolute path. ;curl.cainfo = curl.cainfo="PATH:\TO\xampp\apache\bin\curl-ca-bundle.crt" </code></pre> <p>これで XAMPP の Apache を再起動したところ、エラーは出なくなりました。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="http://nanoappli.com/blog/archives/7992">‘cURL error 60’エラーが出たときの対処法 ‘cURL error 60: SSL certificate problem: unable to get local issuer certificate’</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://linuxfan.info/curl-insecure">curlで「自己署名証明書」を受け入れるには【curl: (60) SSL certificate problem: self signed certificate】 | LFI</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://madadou.info/2018/05/08/curl-error-60/">cURL error 60: SSL certificate (GuzzleHttp v6) | まだどう?</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/17517 2021-07-14T20:39:52+09:00 2021-07-14T20:39:52+09:00 https://crieit.net/posts/composer-lcobucci-jwt-require-ext-sodium-20210714 lcobucci/jwt を Composer でインストールしようとしたら Your requirements could not be resolved to an installable set of packages. のエラーメッセージ <p><a target="_blank" rel="nofollow noopener" href="https://packagist.org/packages/lcobucci/jwt">lcobucci/jwt</a> を Composer でインストールしようとしたら以下のエラーメッセージが表示されました。</p> <pre><code class="bash">> composer require Search for a package: ./composer.json has been updated Running composer update Loading composer repositories with package information Updating dependencies Your requirements could not be resolved to an installable set of packages. Problem 1 - Root composer.json requires lcobucci/jwt 4.1.4 -> satisfiable by lcobucci/jwt[4.1.4]. - lcobucci/jwt 4.1.4 requires ext-sodium * -> it is missing from your system. Install or enable PHP's sodium extension. To enable extensions, verify that they are enabled in your .ini files: - PATH\TO\xampp\php\php.ini You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode. Installation failed, reverting ./composer.json to its original content. </code></pre> <p>XAMPP (PHP 7.4.3) に <code>ext-sodium</code> の拡張機能がない、と。 Docker を使っても良いのですが、今回はサクッと試したいだけなのでもう少し見てみます。試しに <code>php.ini</code> を確認すると</p> <pre><code class="ini">;extension=soap ;extension=sockets ;extension=sodium ;extension=sqlite3 ;extension=tidy ;extension=xmlrpc ;extension=xsl </code></pre> <p>何かそれらしきものがコメントアウトされているのを発見。</p> <pre><code class="ini">;extension=soap ;extension=sockets extension=sodium ;extension=sqlite3 ;extension=tidy ;extension=xmlrpc ;extension=xsl </code></pre> <p>コメントアウトを外し、 XAMPP のコントロールパネルから Apache を再起動。</p> <p>それから再度 Composer でインストールをかけると、正常に完了しました。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://packagist.org/packages/lcobucci/jwt">lcobucci/jwt - Packagist</a></li> <li>同種のエラーメッセージへの対処: <a target="_blank" rel="nofollow noopener" href="https://qiita.com/wallkickers/items/e895495172b5e7371f38">【PHP】「〜requires ext-gd * -> the requested PHP extension gd is missing from your system.」でパッケージがインストールできない時の解決法。 - Qiita</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/17047 2021-05-01T13:26:57+09:00 2021-05-01T13:28:14+09:00 https://crieit.net/posts/sqlite-docker-20210501 Docker で PHP + SQLite3 の開発環境を構築する <p>SQLite を試験したくなったので、環境を Docker で作ることにしました。</p> <p>ベースは <a target="_blank" rel="nofollow noopener" href="https://labor.ewigleere.net/2021/02/12/docker_centos7_apache_php_xdebug/">CentOS7 + Apache + PHP7 (Composer, Xdebug) の開発環境を Docker で作る</a> で。</p> <h2 id="構成"><a href="#%E6%A7%8B%E6%88%90">構成</a></h2> <h3 id="ディレクトリ構造"><a href="#%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E6%A7%8B%E9%80%A0">ディレクトリ構造</a></h3> <pre><code>PROJECT_ROOT/ │ # 略 │ ├ sqlite/ │ # 略 </code></pre> <p>SQLite 用のディレクトリを掘っただけで、後は同じです。</p> <h3 id="docker-compose.yml"><a href="#docker-compose.yml">docker-compose.yml</a></h3> <pre><code class="yaml">version: '3.8' services: web: build: context: ./apache/docker dockerfile: Dockerfile args: # 略 SQLITE_TABLENAME: $SQLITE_TABLENAME labels: lamp.sqlite.php: "SQLite PHP" volumes: # 略 # sqlite - ./sqlite:/var/sqlite/ # 略 entrypoint: bash -c "bash /workspace/entrypoint.sh $WEB_ROOT_DIRECTORY $WEB_DOMAIN $WEB_HOST_PORTNUM $WEB_CONTAINER_PORTNUM $WEB_HOST_PORTSSL $WEB_CONTAINER_PORTSSL $SQLITE_TABLENAME && /bin/bash" </code></pre> <p><code>docker-compose.yml</code> も大部分は同じです。変数(<code>SQLITE_TABLENAME</code>)とボリュームがそれぞれ1つ増えたのと、 entrypoint へ渡す引数が1つ増えたくらいです。</p> <h3 id=".env"><a href="#.env">.env</a></h3> <pre><code class="env">WEB_ROOT_DIRECTORY=sample_sqlite WEB_DOMAIN=lvh.me WEB_HOST_PORTNUM=8080 WEB_CONTAINER_PORTNUM=80 WEB_HOST_PORTSSL=4043 WEB_CONTAINER_PORTSSL=443 SQLITE_TABLENAME=maindb </code></pre> <p>上述の通り、 SQLite のファイル名を決める変数が増えました。</p> <h3 id="apache/docker/Dockerfile"><a href="#apache%2Fdocker%2FDockerfile">apache/docker/Dockerfile</a></h3> <pre><code class="dockerfile">FROM centos:centos7 # 略 # enable repository remi & remi-php74 RUN yum-config-manager --enable remi && yum-config-manager --enable remi-php74 # php RUN yum -y install php php-devel php-pdo php-mysqlnd php-mbstring php-gd php-pear php-pecl-apc-devel zlib-devel php-xml php-mcrypt php-pecl-xdebug # sqlite RUN yum -y install sqlite sqlite-devel # disable repository remi & remi-php74 RUN yum-config-manager --disable remi && yum-config-manager --disable remi-php74 # 略 # volume directory RUN mkdir /template RUN mkdir /var/www/${WEB_ROOT_DIRECTORY} RUN mkdir /var/www/${WEB_ROOT_DIRECTORY}/web RUN mkdir /workspace RUN mkdir /var/sqlite </code></pre> <p>こちらも概ね同じ。 PHP のインストール直後に <code>sqlite</code>, <code>sqlite-devel</code> をインストールしています。また、最後にボリュームとしてマウントするディレクトリを作成しています。</p> <h2 id="workspace/entrypoint.sh"><a href="#workspace%2Fentrypoint.sh">workspace/entrypoint.sh</a></h2> <pre><code class="sh"># 略 # make sqlite file & create dummy table if [[ ! -e /var/sqlite/${7}.sqlite3 ]]; then echo ".exit" | echo "create table testtable(one varchar(10), two smallint);" | sqlite3 /var/sqlite/${7}.sqlite3 fi # Apache start /usr/sbin/httpd -DFOREGROUND & </code></pre> <p>entrypoint も同様ほぼ同じですが、 Apache 起動前に「もし SQLite のデータファイルが該当ディレクトリにない場合は作成」の処理を追加しました。テーブルがないとファイルが生成されなかったので、ダミーテーブルも CREATE しています。</p> <h2 id="検証"><a href="#%E6%A4%9C%E8%A8%BC">検証</a></h2> <p>上述で構築された SQLite にダミーデータを流し込んでテストしてみます。</p> <pre><code class="bash"># sqlite3 /var/sqlite/maindb.sqlite3 sqlite> insert into testtable values('hello', 10); sqlite .exit # </code></pre> <p>まずはダミーテーブルにダミーデータを INSERT します。</p> <pre><code class="php"><?php try { $pdo = new PDO('sqlite:/var/sqlite/maindb.sqlite3'); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $stmt = $pdo->prepare("SELECT * FROM testtable WHERE two >= :two"); $stmt->execute([ 'two' => 5 ]); $result = $stmt->fetchAll(); var_dump($result); } catch (Exception $e) { echo $e->getMessage() . PHP_EOL; } </code></pre> <p>次に上述のような <code>index.php</code> を作成し、Webアクセスします。</p> <pre><code>/var/www/sample_sqlite/web/index.php:25: array (size=1) 0 => array (size=2) 'one' => string 'hello' (length=5) 'two' => string '10' (length=2) </code></pre> <p>結果。これで PHP から PDOオブジェクト 経由でダミーテーブルに接続できたので、ひとまず環境構築という点では完了です。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://it-afi.com/php/post-1253/">php 7.4をソースからインストール時にchecking for sqlite3 > 3.7.4… no configure: error: Package requirements (sqlite3 > 3.7.4) were not met:</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://www.agent-grow.com/self20percent/2018/08/06/linux-command-auto-yes/">コマンドの途中で聞いてくる yes を自動入力したい?それ yes で出来るよ – 自主的20%るぅる</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://linuxfan.info/post-1739">シェルスクリプトでファイルの存在を確認する方法 | LFI</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://laboradian.com/how-to-use-sqlite-from-php/">PHP から SQLite を使う手順 – ラボラジアン</a> <ul> <li>最終的には SQLite3オブジェクト からではなく PDOオブジェクト から接続してしまいましたが</li> </ul></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/39_isao/items/a5b4940138bced936de0">PHP + SQLite3 超入門したメモ - Qiita</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/16504 2021-01-04T23:43:49+09:00 2021-01-04T23:43:49+09:00 https://crieit.net/posts/phpunit-note-exclude-file-and-avoid-cannot-modify-header-20210104 PHPUnit のメモ(設定で特定のファイルを対象除外、 Cannot modify header information - headers already sent by ... のエラーの回避) <p>PHPUnit を使っていて少し躓いた部分のメモ。なお、 PHPUnit のバージョンは <code>9.5.0</code> で試しました。</p> <h2 id="設定で特定のファイルを対象除外"><a href="#%E8%A8%AD%E5%AE%9A%E3%81%A7%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%AF%BE%E8%B1%A1%E9%99%A4%E5%A4%96">設定で特定のファイルを対象除外</a></h2> <p>設定の値を返すだけの簡単な設定ファイルを作ってあり、それをテストから除外したい場合。</p> <pre><code class="xml"><phpunit bootstrap="./tests/bootstrap.php" addUncoveredFilesFromWhitelist="true" processUncoveredFilesFromWhitelist="true" stopOnFailure="false" colors="auto"> <testsuites> <testsuite> <directory suffix="Test.php">./tests</directory> </testsuite> </testsuites> <filter> <whitelist processUncoveredFilesFromWhitelist="true"> <directory suffix=".php">./src</directory> <exclude> <directory suffix=".php">./tests</directory> <directory>./template</directory> </exclude> </whitelist> </filter> </phpunit> </code></pre> <p>ディレクトリの除外ならば <code>phpunit.xml.dist</code> で上記の <code>whitelist</code> > <code>exclude</code> > <code>directory</code> で囲んだパスを除外できることは知っていました。</p> <pre><code class="php"><?php return [ 'base' => '/', 'appname' => 'Config Sample', ]; </code></pre> <p>今回のケースでは、例えばこんな <code>src/config.php</code> があったとします。また、 <code>src/</code> ディレクトリには他のコードもあるため、 <code>src/</code> 自体はテスト対象に含めたいとします。</p> <pre><code class="xml"><phpunit bootstrap="./tests/bootstrap.php" addUncoveredFilesFromWhitelist="true" processUncoveredFilesFromWhitelist="true" stopOnFailure="false" colors="auto"> <testsuites> <testsuite> <directory suffix="Test.php">./tests</directory> </testsuite> </testsuites> <filter> <whitelist processUncoveredFilesFromWhitelist="true"> <directory suffix=".php">./src</directory> <exclude> <directory suffix=".php">./tests</directory> <directory>./template</directory> <file>./src/config.php</file> </exclude> </whitelist> </filter> </phpunit> </code></pre> <p><code>whitelist</code> > <code>exclude</code> > <code>file</code> にすれば良し。</p> <h2 id="Cannot modify header information - headers already sent by ... のエラーの回避"><a href="#Cannot+modify+header+information+-+headers+already+sent+by+...+%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AE%E5%9B%9E%E9%81%BF">Cannot modify header information - headers already sent by ... のエラーの回避</a></h2> <p>とあるメソッドの中に <code>header()</code> 関数が記述されていると、テストの際に</p> <blockquote> <p>Cannot modify header information - headers already sent by (output started at PATH/TO/PROJECT/vendor/phpunit/phpunit/src/Util/Printer.php:104)</p> </blockquote> <p>のようなエラーが出てしまいました。</p> <p>これは PHPUnit はテスト中のメッセージを標準出力に吐き出すので、 <code>header()</code> の前に既に出力がされてしまっている状態になるため引っかかってしまうようです。</p> <p>対策としては、 PHPUnit の <code>@runInSeparateProcess</code> アノテーションを使用することで、そのテストケースを別プロセスとして動作させること。</p> <p>これにより <code>header()</code> 前に出力がない状態としてテストするため、引っかからなくなります。</p> <pre><code class="php"><?php class DullahanTest extends \PHPUnit\Framework\TestCase { /** * @test * @runInSeparateProcess */ public function testDullahan() { // some test code } } </code></pre> <p>こんなイメージです。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <h3 id="設定で特定のファイルを対象除外"><a href="#%E8%A8%AD%E5%AE%9A%E3%81%A7%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%AF%BE%E8%B1%A1%E9%99%A4%E5%A4%96">設定で特定のファイルを対象除外</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://phpunit.readthedocs.io/ja/latest/configuration.html">3. XML 設定ファイル — PHPUnit latest Manual</a></li> </ul> <h3 id="Cannot modify header information - headers already sent by ... のエラーの回避"><a href="#Cannot+modify+header+information+-+headers+already+sent+by+...+%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AE%E5%9B%9E%E9%81%BF">Cannot modify header information - headers already sent by ... のエラーの回避</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/1000k/items/65f64dd95c020639edbf">header() 関数を使ったメソッドを PHPUnit でテストする方法 - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://blog.shimabox.net/2016/12/13/test_methods_that_use_the_header_function_in_phpunit/">PHPUnitでheader関数を使うメソッドのテスト | Shimabox Blog</a></li> </ul> <h2 id="余談"><a href="#%E4%BD%99%E8%AB%87">余談</a></h2> <p>今回ほんの些細なプログラムを書いたのですが、あまりにも些細なものだったので「どうせなら PHPUnit の練習にしよう」と思って取り組みました。結果、 PHPUnit で今まであまり触ってこなかったケースに当たったので、良い勉強になったのかな、と思います。</p> <h3 id="サンプルプログラムを書く際に参考にしたサイト ( PHPUnit とは関係なし)"><a href="#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92%E6%9B%B8%E3%81%8F%E9%9A%9B%E3%81%AB%E5%8F%82%E8%80%83%E3%81%AB%E3%81%97%E3%81%9F%E3%82%B5%E3%82%A4%E3%83%88+%28+PHPUnit+%E3%81%A8%E3%81%AF%E9%96%A2%E4%BF%82%E3%81%AA%E3%81%97%29">サンプルプログラムを書く際に参考にしたサイト ( PHPUnit とは関係なし)</a></h3> <h4 id="password_hash"><a href="#password_hash">password_hash</a></h4> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.php.net/manual/ja/function.password-hash.php">PHP: password_hash - Manual</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/rana_kualu/items/3ef57485be1103362f56">2018年のパスワードハッシュ - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/yayoshM/items/8971e893c1bd95aa0284">PHPのPassword_hash関数をcrypt関数で再現する(メモ) - Qiita</a> <ul> <li><code>password_hash</code> の <code>salt</code> を指定するのは非推奨。仮に指定する場合、短すぎると警告が発せられる</li> </ul></li> </ul> <h4 id="call_user_func_array"><a href="#call_user_func_array">call_user_func_array</a></h4> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.php.net/manual/ja/function.call-user-func-array.php">PHP: call_user_func_array - Manual</a></li> </ul> <p>変数の渡し方が若干疑問。</p> <h4 id="call_user_func_array + FastRoute"><a href="#call_user_func_array+%2B+FastRoute">call_user_func_array + FastRoute</a></h4> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/masakielastic/items/0265ba85de113d06430c">FastRoute を試す - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://webty.jp/staffblog/production/post-2613/">Composerでオレオレフレームワークを作った話 │ Webty Staff Blog</a></li> </ul> <h4 id="str_pad"><a href="#str_pad">str_pad</a></h4> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.php.net/manual/ja/function.str-pad.php">PHP: str_pad - Manual</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/15625 2019-12-19T18:37:14+09:00 2019-12-21T22:57:10+09:00 https://crieit.net/posts/PHP-PHP-5dfb44ca45b7e PHPでメールフォームを自前でつくる。ゆるふわPHP第5回 <p><a href="https://crieit.now.sh/upload_images/6b33941a2e2feb9085362f3ed6e1458f5df771e992c2b.jpeg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/6b33941a2e2feb9085362f3ed6e1458f5df771e992c2b.jpeg?mw=700" alt="ゆるふわPHP第5回" /></a></p> <h2 id="第5章 条件式ってなんなんですか?"><a href="#%E7%AC%AC%EF%BC%95%E7%AB%A0%E3%80%80%E6%9D%A1%E4%BB%B6%E5%BC%8F%E3%81%A3%E3%81%A6%E3%81%AA%E3%82%93%E3%81%AA%E3%82%93%E3%81%A7%E3%81%99%E3%81%8B%EF%BC%9F">第5章 条件式ってなんなんですか?</a></h2> <p>条件式とは、「もし~ならば、~する」といったように、条件を満たしていればその後のプログラムを実行させる命令になり、書式は次の様になります。</p> <pre><code>// もし、変数$ageが20ならば「条件式」と表示させる。 if ($age == 20) { echo "条件式"; } </code></pre> <pre><code><html lang="ja"> <head> <meta charset="UTF-8"> <title>はじめてのPHP</title> </head> <body> <?php $age = 20; if ($age == 20) { echo "条件式"; } ?> </body> </html> </code></pre> <p>上記プログラムをcode05.phpとしてサーバにアップすると「条件式」と表示されます。</p> <p>8行目の変数$ageの値を20以外の値にすると、表示されなくなることを確認してください。</p> <p>また、等号をあらわす「==」の他に「>」「=」「</p> <pre><code>// もし、変数$ageが20より大きければ if ($age > 20) // もし、変数$ageが20より小さければ if ($age < 20) // もし、変数$ageが20以上ならば if ($age >= 20) // もし、変数$ageが20以下ならば if ($age <= 20) // もし、変数$ageが20でなければ if ($age != 20) </code></pre> <p>「<a href="https://crieit.net/posts/PHP-PHP-5dfc9b04e6b4e">第6章 メール送信できちゃうんです!!</a>」に続きます。</p> ケイジ tag:crieit.net,2005:PublicArticle/14776 2019-02-02T09:32:29+09:00 2019-02-02T09:34:19+09:00 https://crieit.net/posts/KUSANAGI-PHP7-nginx KUSANAGI で PHP7 + nginx を利用している際のタイムアウト時間設定 <h1 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h1> <p>デフォルトでファイルが複数あって迷うので、備忘録です。<br /> 以下はタイムアウト時間が1時間(3600秒)の場合の例です。</p> <p>必要な設定箇所は 3 (4) ファイルです。</p> <h1 id="PHP7"><a href="#PHP7">PHP7</a></h1> <h2 id="php.ini"><a href="#php.ini">php.ini</a></h2> <p>/etc/php7.d/php.ini</p> <pre><code>max_execution_time = 3600 </code></pre> <h2 id="PHP-FPM"><a href="#PHP-FPM">PHP-FPM</a></h2> <p>/etc/php7-fpm.d/www.conf</p> <pre><code>request_terminate_timeout = 3600 </code></pre> <h1 id="nginx"><a href="#nginx">nginx</a></h1> <h2 id="SSL"><a href="#SSL">SSL</a></h2> <p>location ディレクティブブロック <code>location ~ [^/]\.php(/|$) {}</code> 内に記載があります。</p> <p>/etc/nginx/conf.d/kusanagi_html_ssl.conf</p> <pre><code>fastcgi_read_timeout 3600s </code></pre> <h2 id="HTTP"><a href="#HTTP">HTTP</a></h2> <p>SSL を用いている場合は不要ですが念の為。</p> <p>/etc/nginx/conf.d/kusanagi_html_http.conf</p> <pre><code>fastcgi_read_timeout 3600s </code></pre> <h1 id="最後に"><a href="#%E6%9C%80%E5%BE%8C%E3%81%AB">最後に</a></h1> <p>PHP (PHP-FPM), nginx の再起動を忘れずに。<br /> KUSNAGAI の場合は、以下のコマンドで PHP (PHP-FPM), nginx の再起動を同時に行ってくれます。</p> <pre><code>sudo kusanagi restart </code></pre> sola tag:crieit.net,2005:PublicArticle/14469 2018-06-17T19:55:22+09:00 2018-10-25T17:29:30+09:00 https://crieit.net/posts/Wercker-Laravel5-6-PHP7-CI WerckerでLaravel5.6+PHP7のCI <p><a href="https://crieit.net/posts/BitBucket-Wercker-Laravel5-CI">BitBucket+WerckerでLaravel5のCI</a> でも書いたとおり、BitBucket+Werckerを利用することでLaravel5のCIを無料で簡単に行うことができます。</p> <p>ただ、上記の内容だと最新のLaravel5.6(PHP7)には対応していないため、対応したものでCIできるようにしてみました。</p> <p>下記が設定のためのwercker.ymlになります。</p> <pre><code class="yaml">box: dala00/laravel services: - id: mysql tag: 5.7 env: MYSQL_ALLOW_EMPTY_PASSWORD: "true" MYSQL_DATABASE: test build: steps: - script: name: Install dependencies code: | composer install - script: name: Fill mysql env. code: |- sudo sed -i -e "s/DB_HOST=mysql/DB_HOST=$MYSQL_PORT_3306_TCP_ADDR/g" .env.testing sudo sed -i -e "s/DB_PORT=3306/DB_PORT=$MYSQL_PORT_3306_TCP_PORT/g" .env.testing - script: name: Run phpunit code: |- vendor/bin/phpunit </code></pre> <h2 id="Werckerで使っている設定の解説"><a href="#Wercker%E3%81%A7%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E8%A8%AD%E5%AE%9A%E3%81%AE%E8%A7%A3%E8%AA%AC">Werckerで使っている設定の解説</a></h2> <pre><code class="yaml">box: dala00/laravel </code></pre> <p>僕が作ったイメージです(7.2。タグ付けは忘れているようです)。<code>/var/www/app</code>にプロジェクトが入っています。ちょっとしたものは大体動くのでこれで問題ない気がします(どうしてもちょうどいいイメージが見つからないため…)。</p> <pre><code class="yaml"> - id: mysql tag: 5.7 </code></pre> <p>mysql8が入るとパスワードのプラグインが違う関係でWerckerのCI時に接続ができません。仕方がないのでtagで5.7を指定しています。(恐らく今後イメージ側かWercker側で対処してくれるとは思うのですが…)</p> <pre><code class="yaml"> sudo sed -i -e "s/DB_HOST=mysql/DB_HOST=$MYSQL_PORT_3306_TCP_ADDR/g" .env.testing sudo sed -i -e "s/DB_PORT=3306/DB_PORT=$MYSQL_PORT_3306_TCP_PORT/g" .env.testing </code></pre> <p>Laravel5.6のテストの場合はphpunit.xmlで指定されている環境変数である<code>APP_ENV=testing</code>が使われるため、<code>.env.testing</code>が優先的に使用されます。また、WerckerはDBのIPがMYSQL_PORT_3306_TCP_ADDRで取得できるので、<code>.env.testing</code>をその内容に置換します。置換前の文字列は適宜自分のものに置き換えてください。</p> <p>こんな感じでWerckerにてLaravel5.6のCIが可能です。BitBucketを利用されている方は連携も非常に簡単ですので是非お試しください。</p> だら@Crieit開発者 tag:crieit.net,2005:PublicArticle/14466 2018-06-07T09:13:48+09:00 2019-02-28T14:24:27+09:00 https://crieit.net/posts/PHP5-3-PHP7-2 PHP5.3のプロジェクトをPHP7.2にした時の流れ <p>誰かが作っていたものを10年くらい前に引き継いで今も継続している案件がある。何度かサーバーは変わったが、とはいえかなり古いものなのでPHP5.3で動作していた。<br /> ただ、お客さんの依頼で使用したいパッケージで5.3では動かないものが出てきたので、サーバー移転ついでにPHP7.2にした話。</p> <h2 id="環境"><a href="#%E7%92%B0%E5%A2%83">環境</a></h2> <ul> <li>フレームワークなし</li> <li>composerあり</li> </ul> <h2 id="やり方"><a href="#%E3%82%84%E3%82%8A%E6%96%B9">やり方</a></h2> <p>基本的にはとりあえずPHP7.2の環境で動作させてひたすら修正していくだけ。ローカルでも一時的に借りたVPSとかでも何でも良い。自分の場合はDockerを使った。Dockerの詳細は興味ない人もいると思うので最後の方に書く。</p> <p>PHP5.3というのがわりと微妙なところで、結構面倒な部分が出てくる。大きな山となったのは下記2つだった。</p> <h3 id="register_globals"><a href="#register_globals">register_globals</a></h3> <p>古いプロジェクトなのでregister_globalsが有効化されており、しっかりとこの機能を利用して作られてしまっている。今の人は知らないかもしれないが、<code>$_GET</code>とか<code>$_POST</code>とかで受け取る値が自動的に変数となってしまう機能。例えば<code>$_GET['mode']</code>とかがあったら<code>$mode</code>変数として使える便利機能。</p> <p><a target="_blank" rel="nofollow noopener" href="http://php.net/manual/ja/security.globals.php">http://php.net/manual/ja/security.globals.php</a></p> <p>これはPHP5.4で削除されているので当然プロジェクト全体でエラーになる。(特にガッツリ時間をもらっているプロジェクトでもないので、新規機能追加とかは行っているがこの辺のリファクタリングは行われていない)</p> <h4 id="対処方法"><a href="#%E5%AF%BE%E5%87%A6%E6%96%B9%E6%B3%95">対処方法</a></h4> <pre><code class="php">extract($_POST, EXTR_SKIP); extract($_GET, EXTR_SKIP); </code></pre> <p>解決方法としては一番ひどい方法だと思うが、動かなくなるよりはまし。というか元々ひどすぎるのでそれほど変わらない。そもそも今後フレームワーク化してこういった処理は全部消したいので、とりあえず段階的な対応。</p> <h3 id="MySQL接続"><a href="#MySQL%E6%8E%A5%E7%B6%9A">MySQL接続</a></h3> <p>mysql_connectと関連関数が使われていた。これはPHP7では削除されるので、PDOに置き換える必要がある。</p> <p>しかし、前述したとおりフレームワークが使われていないのでmysql_queryをラップした関数が色々と作成されており、ほとんどのページでその関数群が使われている。基本的にはPHP7にするとほとんどのページが動かなくなる。徐々にEloquentに置き換えてはいたが、そんなに少ない量でもないため全部をすぐ置き換えるのには無理がある。</p> <p>そのため、消えたmysql_*関数を全部用意することにした。</p> <pre><code class="php">define('MYSQL_ASSOC', 'assoc'); $conn = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8", $user, $pass); function mysql_query($query) { global $conn; return $conn->query($query); } function mysql_fetch_assoc($statement) { return $statement->fetch(PDO::FETCH_ASSOC); } function mysql_fetch_array($statement, $mode) { return mysql_fetch_assoc($statement); } function mysql_numrows($statement) { return $statement->rowCount(); } function mysql_insert_id() { global $conn; return $conn->lastInsertId(); } function mysql_free_result($statement) { $statement->closeCursor(); } function mysql_error() { global $conn; $info = $conn->errorInfo(); if (isset($info[1])) { return $info[2]; } return null; } function mysql_errno() { global $conn; $info = $conn->errorInfo(); if (isset($info[1])) { return $info[1]; } return null; } function mysql_close($link = null) { } </code></pre> <p>解決方法としては一番ひどい方法だと思うが、動かなくなるよりはまし。というか元々ひどすぎるのでそれほど変わらない。そもそも今後フレームワーク化してこういった処理は全部消したいので、とりあえず段階的な対応。</p> <p>ちなみに今回は使っていないので詳しくは知らないが<br /> <a target="_blank" rel="nofollow noopener" href="https://github.com/dshafik/php7-mysql-shim">dshafik/php7-mysql-shim: A shim for ext/mysql in PHP 7+</a><br /> というのもあるらしい。</p> <h3 id="PEAR"><a href="#PEAR">PEAR</a></h3> <p>PEARは古いプログラムもあるので、下記の様な処理があると全部エラーになる。</p> <pre><code class="php">$var =& Foo::factory(); </code></pre> <p>上記の&がエラーになるので削除していく。</p> <h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2> <p>基本的な対応は上記だが、あとはバージョンの違いでちょっとしたエラーとかも出るので見つけ次第修正していく。本当はテストである程度網羅されている事が望ましいが、古いスクラッチプロジェクトなので当然テストもない。(最近はちょこちょこCI含め追加しているが全く足りない)</p> <p>一通り確認したので先日PHP7.2が走っているサーバーに移転を完了した。</p> <p>ただし、プロジェクトがひどすぎる関係でこれは完成でなくあくまでも分岐点なので、最終的にはLaravelを入れて全部そちらに移行などしたい。既に一部の完全に分離できるバッチ処理等はこのプロジェクトに組み込まずGoで書いていたりする。</p> <p>マイクロサービス化は色々とメリットデメリットがあげられているが、こういった古すぎるプロジェクトに関しては可能なところを分離していくと要らない部分を捨てやすくて良い。(もちろんやり過ぎはよくないと思う)</p> <h2 id="おまけでDocker"><a href="#%E3%81%8A%E3%81%BE%E3%81%91%E3%81%A7Docker">おまけでDocker</a></h2> <pre><code class="dockerfile:Dockerfile">FROM php:7.2-apache RUN apt-get update && apt-get install -y git zlib1g-dev RUN curl -sS https://getcomposer.org/installer | php RUN mv composer.phar /usr/local/bin/composer RUN a2enmod rewrite RUN docker-php-ext-install pdo_mysql mbstring zip </code></pre> <p>```yml:docker-compose.yml<br /> version: '2'<br /> volumes:<br /> mysql_data:<br /> driver: 'local'<br /> services:<br /> mysql:<br /> image: mysql:5.7.19<br /> volumes:<br /> - mysql_data:/var/lib/mysql<br /> - ./mysql:/etc/mysql/conf.d<br /> environment:<br /> - MYSQL_ALLOW_EMPTY_PASSWORD=true</p> <p>phpmyadmin:<br /> image: phpmyadmin/phpmyadmin<br /> environment:<br /> - PMA_ARBITRARY=1<br /> - PMA_HOST=mysql<br /> - PMA_USER=root<br /> - PMA_PASSWORD=<br /> ports:<br /> - 8201:80</p> <p>app:<br /> image: myapp/php:7.2<br /> depends_on:<br /> - mysql<br /> working_dir: /var/www/html<br /> volumes:<br /> - .:/var/www/html<br /> - ./php/php.ini:/usr/local/etc/php/conf.d/myphp.ini<br /> ports:<br /> - "8200:80"<br /> tty: true<br /> stdin_open: true</p> <pre><code><br />```ini:php.ini log_errors = On error_log = /dev/stderr date.timezone = "Asia/Tokyo" </code></pre> <p><code>conf:config.cnf [mysqld] sql_mode=''</code></p> だら@Crieit開発者