20200731のPHPに関する記事は17件です。

PHPだけで簡単なおみくじを作ってみた

概要

非常に簡単な機能です。

まず、初期画面に「おみくじを引く」ボタンがあり、
初期画面.png
ボタンを押すと、7つあるくじのうちの一つがランダムに引かれ、結果が表示されます。
結果画面.png
結果の詳細をクリックすると、くじに応じたコメントが表示されます。
詳細画面.png

実装

動作確認環境:PHP7.1.29

初期画面

まず初期画面を実装します。

start.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>おみくじ</title>
</head>
<body>
<h1>おみくじ</h1>
<h2>おみくじを引いて今日の運勢を占ってみよう!</h2>
<form action="fortune.php" method="POST">
<input type="submit" name="btn" value="おみくじを引く">
</form>
</body>
</html>

一つのフォームがあるだけの簡単なページです。
クリックすると、「fortune.php」へ飛ばされます。

結果画面

結果画面へアクセスされると、ランダムにくじが引かれ、その結果が表示されます。

fortune.php
<?php
$lots = [1, 2, 3, 4, 5, 6, 7];
if (isset($_POST['btn'])) {
    $lot = array_rand($lots);
    switch ($lot) {
        case 0:
            $res = '大吉';
            $num = 1;
            break;
        case 1:
            $res = '中吉';
            $num = 2;
            break;
        case 2:
            $res = '小吉';
            $num = 3;
            break;
        case 3:
            $res = '吉';
            $num = 4;
            break;
        case 4:
            $res = '半吉';
            $num = 5;
            break;
        case 5:
            $res = '末吉';
            $num = 6;
            break;
        case 6:
            $res = '凶';
            $num = 7;
    }
} else {
    header('Location:start.php');
    exit();
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>おみくじ</title>
</head>
<body>
<h1>結果</h1>
<h2><?php echo $res; ?></h2>
<p><a href="detail.php?num=<?php echo $num; ?>">結果の詳細</a></p>
<p><a href="start.php"><button type="button">もう一度おみくじを引く</button></a></p>
</body>
</html>

else文内の処理によって、「おみくじを引く」ボタンを押さずに(値をPOSTせずに)やって来たアクセスを、初期画面へと弾いています。

くじを引く処理は、1から7の値が入った配列を作り、その配列からarray_randによってランダムにキーを取り出し、その値によって結果を分岐させています。

注意点として、「array_rand」は値を取り出しているのではなくキーを取り出しています

array_rand — 配列から一つ以上のキーをランダムに取得する
引用元:PHPマニュアル array_rand

この為、続くswitch文のcase文では0から値が始まっています。

また、結果によって変数$numに数値を代入し、それをURLパラメータに加えたリンクを生成することで、詳細ページ内容を分岐させます。

詳細画面

URLパラメーターから値を取得し、それにより表示させるコメントを変化させています。

detail.php
<?php
if (isset($_GET['num']) && $_GET['num'] < 8 && $_GET['num'] > 0) {
    $num = $_GET['num'];
    switch ($num) {
        case 1:
            $res = '絶好調の運勢!';
            break;
        case 2:
            $res = '今日という日に期待大!';
            break;
        case 3:
            $res = 'ちょっといいことあるかも!';
            break;
        case 4:
            $res = 'ラッキー!';
            break;
        case 5:
            $res = '末吉よりはいいかも';
            break;
        case 6:
            $res = '一応吉だよ';
            break;
        case 7:
            $res = 'ダメだったらやり直せばええんやで';
    }
} else {
    header('Location:start.php');
    exit();
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>おみくじ</title>
</head>
<body>
<h1>結果の詳細</h1>
<h2><?php echo $res; ?></h2>
<p><a href="start.php"><button type="button">もう一度おみくじを引く</button></a></p>
</body>
</html>

このページでは、
「『num』をキーとしたGETパラメータがある」
かつ
「そのGETパラメータが1〜7の範囲内」
の場合のみ処理が走るようにしています。

...実は少々穴があり、GETパラメータに「2.2」など範囲内の整数以外の数値を入れるとアクセスできてしまいます...

これを防ぐのに良いアドバイスとかコメント頂けたら喜びます!

あとがき

現在プロサー12期生として、PHPを学習のタツロンです。
今回はプロサーで学んだ知識のアウトプットの一環として、0から処理を書いてみました。
何か不備などございましたら、コメント頂けると幸いです。

また、プロサーに関してお聞きしたいことがある方もDMとか歓迎です!

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

PHP 7.3からPHP 7.2へのダウングレード

はじめに

VPS上に構築しているシステムで以下のようなwarningが出た

"continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"?

sshでバージョン表示させるといつのまにかバージョンが上がっていた

$ php -v
PHP 7.3.19 (cli) (built: Jun  9 2020 08:06:30) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.19, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.19, Copyright (c) 1999-2018, by Zend Technologies

PHPドキュメントを見に行くとphp7.3ではcontinue文が非推奨との事
https://www.php.net/manual/ja/migration73.incompatible.php

どう対処したか?

インフラ担当に問い合わせると、テストとしてバージョンを上げたとの事なので今回はダウングレードで対応を行う。

php73リストアップ

$ yum list installed | grep php73
php.x86_64                                7.3.19-1.el7.remi          @remi-php73
php-bcmath.x86_64                         7.3.19-1.el7.remi          @remi-php73
php-cli.x86_64                            7.3.19-1.el7.remi          @remi-php73
php-common.x86_64                         7.3.19-1.el7.remi          @remi-php73
php-devel.x86_64                          7.3.19-1.el7.remi          @remi-php73
...

php73削除

$ sudo yum remove -y php.x86_64 php-bcmath.x86_64 php-cli.x86_64 php-common.x86_64 php-devel.x86_64 php-fpm.x86_64 ...

php73確認

$ php -v
-bash: /usr/bin/php: そのようなファイルやディレクトリはありません

php72インストール

$ sudo yum install -y --enablerepo=remi-php72 php.x86_64 php-bcmath.x86_64 php-cli.x86_64 php-common.x86_64 php-devel.x86_64 ... 

php72確認

$ php -v
PHP 7.2.32 (cli) (built: Jul  8 2020 07:33:50) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.32, Copyright (c) 1999-2018, by Zend Technologies

Apache再起動

$ sudo service httpd restart
Redirecting to /bin/systemctl restart httpd.service
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPでAWS CLIを用いてS3に画像をアップする

EC2環境上でPHPのexec関数とAWS CLIを用いてS3に画像をアップしようと思ったら、嵌ったので備忘録メモです。

まず、事前にEC2上で

$ aws configure 

を叩いて、アクセスキー ID、シークレットアクセスキー、AWSリージョン、出力形式を入力した後に、PHPファイルに

exec('aws s3 sync  ./upload  s3://{バケット名}/img --acl public-read --delete', $out);

を挿入し、実行してみましたが$outに結果が返らず、S3にもアップされませんでした。
そこで、PHPのファイル上に事前に次の形式でアクセスキー ID、シークレットアクセスキー、AWSリージョンを記述したあとにexec関数を記述すると動作しました。

$region = 'ap-northeast-1';
$key = '****';
$secret = '**********************';
putenv('AWS_DEFAULT_REGION=' . $region);
putenv('AWS_ACCESS_KEY_ID=' . $key);
putenv('AWS_SECRET_ACCESS_KEY=' . $secret);
exec('aws s3 sync  ./upload  s3://{バケット名}/img --acl public-read --delete', $out);

ただし、PHPファイルにキー情報を直接書いてしまうのはセキュリティ的に問題ありそうなので、APPACHと同じキーをユーザーに割り当てる方法もあるようです。

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

LaravelでRedisを操作する

前提条件

eclipseでLaravel開発環境を構築する。デバッグでブレークポイントをつけて止める。(WindowsもVagrantもdockerも)
本記事は上記が完了している前提で書かれています
プロジェクトの作成もapacheの設定も上記で行っています

LaravelでDIを使う
本記事は上記で作成したフォルダとファイルを使用します

PhpRedisのインストール

PhpRedisを介してRedisを操作します
下記リンクで環境構築した人はインストールされているはずです
LAMP+Redis環境を超短手数で構築する
インストールしていない人は下記リンクに従ってインストールしてください
phpredis インストール

設定

(1) /sample/.env修正
Redisへアクセスするための設定を書く

‥‥
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
‥‥

REDIS_HOST、REDIS_PASSWORD、REDIS_PORTを自分の環境に合ったものにしてください
vagrantのforwarded_port設定でポートを変えたりしている場合、自分の環境にあった値に変えてください

(2) /sample/config/database.php修正
.envに書いたRedis接続定義はdatabase.phpで使われています
database.phpに定義されている配列の'redis'=>'default'要素修正、'redis'=>'db2'要素追加

‥‥
'redis' => [
‥‥
        'default' => [
            'url' => env('REDIS_URL'),
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', '6379'),
            'database' => env('REDIS_DB', '0'),
        ],

        'db2' => [
            'url' => env('REDIS_URL'),
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', '6379'),
            'database' => '2',
        ],
‥‥

Redisへの接続定義を2つ作りました

(3) /sample/config/app.php修正
aliases要素内のRedisをコメントにする

‥‥
//'Redis' => Illuminate\Support\Facades\Redis::class,
‥‥

サービスクラス作成

(1) /sample/app/Services/InterfacesフォルダにRedisService.php作成

RedisService.php
<?php
namespace App\Services\Interfaces;

interface RedisService
{
    public function __construct();

    public function setKey1($value);
    public function getKey1();

}

(2) /sample/tests/Services/ImplフォルダにRedisServiceImpl.php作成

Tests\Services\Impl\RedisServiceImpl.php
<?php
namespace Tests\Services\Impl;

use App\Services\Interfaces\RedisService;

class RedisServiceImpl implements RedisService
{

    public function __construct()
    {
    }

    public function setKey1($value)
    {
    }

    public function getKey1()
    {
    }

}

(3) /sample/app/Services/ImplフォルダにRedisServiceImpl.php作成

App\Services\Impl\RedisServiceImpl.php
<?php
namespace App\Services\Impl;

use App\Services\Interfaces\RedisService;
use Illuminate\Support\Facades\Redis;

class RedisServiceImpl implements RedisService
{

    private $redis = null;

    public function __construct()
    {
        $this->redis = Redis::connection('db2');
    }

    public function setKey1($value)
    {
        Redis::set('key1', 'default_' . $value);
        $this->redis->set('key1', 'db2_' . $value);
    }

    public function getKey1()
    {
        $default = Redis::get('key1');
        $db2 = $this->redis->get('key1');

        return [$default, $db2];

    }

}

static関数としてRedis::setのように書くと、さきほどdatabase.phpに書いたdefault接続が使われます。
他の接続を使いたい場合は、Redis::connection('db2');のように明示的に接続を取ってください
Redisクラスのメソッド名はRedisコマンド名がそのまま使えます

DI登録

(1) /sample/app/Providers/DiServiceProvider.phpに下記を追記
use App\Services\Interfaces\RedisService;

(2) /sample/app/Providers/DiServiceProvider.phpのregisterメソッドに下記を追記
app()->singleton(RedisService::class, $prefix . 'RedisServiceImpl');

DiServiceProvider.phpはLaravelでDIを使うで作成したファイルです
LaravelでDIを使うでconfig/app.phpのprovidersに登録してあります

Controllerにメソッド追加

(1) /sample/app/Http/Controllers/SampleController.phpにuse文を追記
use App\Services\Interfaces\RedisService;

(2) /sample/app/Http/Controllers/SampleController.phpにredis1メソッド、redis2メソッドを追記

SampleController.php
    public function redis1(Request $request, RedisService $redisService)
    {
        $key1Value = $request->input('key1');

        if (!is_null($key1Value)) {
            $redisService->setKey1($key1Value);
        }

        return view('sample.redis1');

    }

    public function redis2(RedisService $redisService)
    {
        $key1Value = $redisService->getKey1();

        $data = ['key1Value' => var_export($key1Value, true)];

        return view('sample.redis2', $data);
    }

(3) /sample/routes/web.phpに下記を追記
Route::get('sample/redis1', 'SampleController@redis1');
Route::get('sample/redis2', 'SampleController@redis2');

viewの作成

(1) /sample/resources/views/sample/redis1.blade.phpファイル作成

redis1.blade.php
<html>
    <head>
        <title>sample</title>
    </head>
    <body>

        <form action="{{ url('sample/redis1') }}" method="get">
            <div>key1<input type="text" name="key1" value=""></div>
            <input type="submit" >
        </form>

    </body>
</html>

(2) /sample/resources/views/sample/redis2.blade.phpファイル作成

redis2.blade.php
<html>
    <head>
        <title>sample</title>
    </head>
    <body>

        <div>{{$key1Value}}</div>

    </body>
</html>

動作確認1

http://localhost/laravelSample/sample/redis1
a.png
何か値を入れて送信ボタンをクリック

http://localhost/laravelSample/sample/redis2
b.png
sample/redis1で入力した値が出てくる

redisを見てみる

127.0.0.1:6379> select 0
OK
127.0.0.1:6379> keys *
1) "laravel_database_key1"

laravel_database_という接頭辞が付いた形で保存されています
これはconfig/database.phpのredis=>options=>prefix要素で接頭辞を設定しているためです

127.0.0.1:6379[2]> select 0
OK
127.0.0.1:6379> get laravel_database_key1
"default_value1"
127.0.0.1:6379> select 2
OK
127.0.0.1:6379[2]> get laravel_database_key1
"db2_value1"
127.0.0.1:6379[2]>

redisにも値が入っていることがわかります

sessionの格納先をRedisにする

(1) /sample/.env修正
sessionの設定を書く

‥‥
#SESSION_DRIVER=file
SESSION_DRIVER=redis
SESSION_CONNECTION=db2
‥‥

SESSION_DRIVERをredisに変える。SESSION_CONNECTIONに格納先のRedis接続を指定する

動作確認2

Laravelでセッションを使う
上記記事で作成した
http://localhost/laravelSample/sample/session1
にアクセスする

redisを見てみる

127.0.0.1:6379[2]> select 2
OK
127.0.0.1:6379[2]> keys *
1) "laravel_database_laravel_cache:xxxxxxxxxxxxxxxxxxxxxx"

Redisに入っていることがわかります

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

【PHP】CSVを作成し、ZIPに圧縮してダウンロード

はじめに

前回の記事【PHP】Excelで文字化けしないCSVファイル作成の続き?というより最終的にやりたかったことを備忘録として記事にします。

非同期通信で、DBからテーブルごとのCSVを作成し、ZIPに圧縮してダウンロードさせる!!!

ZIPに圧縮まではすんなりできたのですが(前回記事は多少躓きましたが…)、ダウンロードしたZIPファイルが開けない/解凍できない現象に悩まされました。

非同期をjQueryでやっていたんですが上手くいかず、XMLHttpRequestに変えたら成功しました。
何がダメだったんだろう。。。

コード

ルーティングとかは省きます。

クライアント側 JS
var request = new XMLHttpRequest();
request.open('GET', '/getZip', true);
request.responseType = "blob";
request.onload = function (oEvent) {
    var blob = request.response;
    var objectURL = window.URL.createObjectURL(blob);
    // リンクを作成し、JavaScriptからクリック
    var link = document.createElement("a");
    document.body.appendChild(link);
    link.href = objectURL;
    link.download = 'ZIPファイル名';
    link.click();
    document.body.removeChild(link);
};
request.send(null);
サーバ側 PHP
// ZipArchiveクラス初期化
$zip = new ZipArchive();
// Zipファイルパス
$zipFileNm = 'ZIPファイル名(拡張子付)';
$zipFilepath = 'ZIPファイルパス'.$zipFileNm;
// Zipファイルオープン
$result = $zip->open($zipFilepath, ZIPARCHIVE::CREATE);
if($result !== true){
  //ZIPファイル作成失敗時の処理
}

// CSV作成 前回記事関数
$csvFilePath = createCSV('CSVファイル名', 'データカラム', 'データ本体');
// CSVファイルをZIPに追加
$zip->addFile($csvFilePath, 'CSVファイル名');
// Zipファイルクローズ
$zip->close();

// HTTPヘッダを設定
mb_http_output( "pass" );
header("Pragma: public");
header('Content-Type: application/force-download;');
header('Content-Length: '.filesize($zipFilepath));
header("Content-Disposition: attachment; filename=$zipFileNm");
ob_end_clean();

// ファイル出力(ダウンロードさせる)
readfile($zipFilepath);

// Zipファイル削除
if(!unlink($zipFilepath)){
  //ZIPファイル削除失敗時の処理
}

// CSVファイルの削除
$delFileName = "CSVファイル保存パス/*.csv";
foreach(glob($delFileName) as $val){
  if(!unlink($val)){
    // CSVファイル削除失敗時の処理
  }
}

最後に

だらだら長いコードだと思います。
あと、これで本当に良いのかな~と疑問。処理は動くけども。

こうした方が良い等ありましたら、アドバイスください!!!

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

[PHP]strtotime("- 1 month")はアカン[31日はテストが落ちる日]

これはなに?

PHPでstrtotime("- 1 month")とかstrtotime("+ 1 month")とか書いちゃだめだよって話です。

今日は何の日でしょう?

今日は、弊社の自動テストが落ちた日です。
昨日は落ちなかったのに、いったいなぜ今日落ちてしまったのでしょう。

なぜ落ちた?

それは今日が31日だからです。

テストコードに現在時刻を使ったコードがありました。
ただし、現在時刻から+1ヶ月したり-1ヶ月したりして、相対的な日付でテストをしているので、
普段は時刻が変わることによる問題は起こっていませんでした。

しかし、今日初めて問題が発覚しました。
現在時刻から前月の月を取得する計算が31日だけおかしかったのです。

前月の計算の仕方(NGケース)

strtotime("- 1 month")

一見良さそうです。今から マイナス1ヶ月後の日付が取れそうです。

7/1なら6/1

7/20なら6/20

7/31なら7/1

( ゚д゚) ・・・
 
(つд⊂)ゴシゴシ
 
(;゚д゚) ・・・
 
(つд⊂)ゴシゴシゴシ
  _, ._
(;゚ Д゚) …!?

0ヶ月前やん!

strtotime("+ 1 month")

の場合でも問題が起こります。

8/31の1ヶ月後は
10/1になってしまします。
2ヶ月後ですね。

正しい書き方

strtotime('first day of previous month');
strtotime('first day of next month');

参考コード

間違った例

date('Y-m-d H:i:s', strtotime('+ 1 Month', strtotime('2020/08/31 00:00:01')))
=> "2020-10-01 00:00:01"
>>> date('Y-m-d H:i:s', strtotime('- 1 Month', strtotime('2020/07/31 00:00:01')))
=> "2020-07-01 00:00:01"

正しい例

>>> date('Y-m-d H:i:s', strtotime('first day of previous month', strtotime('2020/07/31 00:00:01')))
=> "2020-06-01 00:00:01"
>>>  date('Y-m-d H:i:s', strtotime('first day of next month', strtotime('2020/08/31 00:00:01')))
=> "2020-09-01 00:00:01"

参考

https://bugs.php.net/bug.php?id=44073
https://stackoverflow.com/questions/19727274/strtotime-bug-when-using-1-month-from-january

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

【PHP Redis】Redisが動かない時

Redisの動作を確認しましょう

$ sudo chmod +x /etc/init.d/redis
$ sudo service redis status
$ sudo service redis restart
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP Laravel `?:`の正体を知ってすっきりした話

目的

  • 先輩方が開発に携わったLaravelアプリのソースコードをみていたら自分の知らない処理が出てきて驚いた話をまとめる

初見のコード

  • 自分が初めて見たコードを下記に記載する。

    変数 = 比較対象A === 比較対象B ?文字列1:文字列2;
    

簡単な解説

  • 処理内容を下記に簡単に記載する。
    1. 比較対象Aと比較対象Bを比較する。
    2. データ型も含めて比較し、一致しているのかしていないのかを確認する。
    3. 一致していた(true)の場合、文字列1が変数に格納される。
    4. 一致していない(false)の場合、文字列2が変数に格納される。
  • この?:を用いた記載(?:)は条件演算子と呼ばれる物である。
  • 下記に処理を記載する。

    条件式 ?式1:式2;
    
  • 上記の様な処理の場合、条件式が真(true)の時に式1を実行し、偽(false)の時に式2を実行する。

具体例

  • 下記の様なコードを実行した時の結果を考える。

    $a = 'staging';
    $b = 'dev';
    
    echo $a === $b ? 'OK' : 'NO';
    
  • 上記を実行すると「NO」と出力される。

  • 下記の様なコードを実行した時の結果を考える。

    $a = 'dev';
    $b = 'dev';
    
    echo $a === $b ? 'OK' : 'NO';
    
  • 上記を実行すると「OK」と出力される。

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

PHP `?:`の正体を知ってすっきりした話

目的

  • 先輩方が開発に携わったLaravelアプリのソースコードをみていたら自分の知らない処理が出てきて驚いた話をまとめる

初見のコード

  • 自分が初めて見たコードを下記に記載する。

    変数 = 比較対象A === 比較対象B ?文字列1:文字列2;
    

簡単な解説

  • 処理内容を下記に簡単に記載する。
    1. 比較対象Aと比較対象Bを比較する。
    2. データ型も含めて比較し、一致しているのかしていないのかを確認する。
    3. 一致していた(true)の場合、文字列1が変数に格納される。
    4. 一致していない(false)の場合、文字列2が変数に格納される。
  • この?:を用いた記載(?:)は条件演算子と呼ばれる物である。
  • 下記に処理を記載する。

    条件式 ?式1:式2;
    
  • 上記の様な処理の場合、条件式が真(true)の時に式1を実行し、偽(false)の時に式2を実行する。

具体例

  • 下記の様なコードを実行した時の結果を考える。

    $a = 'staging';
    $b = 'dev';
    
    echo $a === $b ? 'OK' : 'NO';
    
  • 上記を実行すると「NO」と出力される。

  • 下記の様なコードを実行した時の結果を考える。

    $a = 'dev';
    $b = 'dev';
    
    echo $a === $b ? 'OK' : 'NO';
    
  • 上記を実行すると「OK」と出力される。

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

PHP 「?:」 の正体を知ってすっきりした話

目的

  • 先輩方が開発に携わったLaravelアプリのソースコードをみていたら自分の知らない処理が出てきて驚いた話をまとめる

初見のコード

  • 自分が初めて見たコードを下記に記載する。

    変数 = 比較対象A === 比較対象B ?文字列1:文字列2;
    

簡単な解説

  • 処理内容を下記に簡単に記載する。
    1. 比較対象Aと比較対象Bを比較する。
    2. データ型も含めて比較し、一致しているのかしていないのかを確認する。
    3. 一致していた(true)の場合、文字列1が変数に格納される。
    4. 一致していない(false)の場合、文字列2が変数に格納される。
  • この?:を用いた記載(?:)は条件演算子と呼ばれる物である。
  • 下記に処理を記載する。

    条件式 ?式1:式2;
    
  • 上記の様な処理の場合、条件式が真(true)の時に式1を実行し、偽(false)の時に式2を実行する。

具体例

  • 下記の様なコードを実行した時の結果を考える。

    $a = 'staging';
    $b = 'dev';
    
    echo $a === $b ? 'OK' : 'NO';
    
  • 上記を実行すると「NO」と出力される。

  • 下記の様なコードを実行した時の結果を考える。

    $a = 'dev';
    $b = 'dev';
    
    echo $a === $b ? 'OK' : 'NO';
    
  • 上記を実行すると「OK」と出力される。

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

elasticsearch-php で全件取得

elasticsearch-php で特定のindexから全件取得する方法です。

方法1

index だけを指定すると全件取得になるようです。
sort 設定をしたいので body に入れています。

use Elasticsearch\ClientBuilder;

class ElasticSearch
{
    public function getAll()
    {
        $client = ClientBuilder::create()
            ->setHosts([ENV('ELASTICSEARCH_HOST', 'elasticsearch') . ':' . ENV('ELASTICSEARCH_PORT', '9200')])
            ->build();

        $searchResults = $client->search([
            'index' => 'index_name',
            'body' => [
                'sort' => [
                    'created_at' => ['order' => 'desc'],
                ],
            ],
        ]);
    }
}

方法2

最初こちらの方法2しか知らなかったので方法1を使わなかったのですが、特に理由がなければ方法1で良さそうでした。
動作に微妙な違いがあるかもしれませんが、詳細は未検証です。

match_all を使うと全件取得になります。

use Elasticsearch\ClientBuilder;

class ElasticSearch
{
    public function getAll()
    {
        $client = ClientBuilder::create()
            ->setHosts([ENV('ELASTICSEARCH_HOST', 'elasticsearch') . ':' . ENV('ELASTICSEARCH_PORT', '9200')])
            ->build();

        $searchResults = $client->search([
            'index' => 'index_name',
            'from' => 0,
            // 設定可能上限値なので実質無制限扱い
            'size' => 10000,
            'body' => [
                'query' => [
                    // see: see: https://github.com/elastic/elasticsearch-php/issues/495
                    'match_all' => (object)[]
                ],
            ],
        ]);
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PhpStorm】ファイルのすべての関数にPHPDocを生成する

コマンド

Alt + Insert でGenerate ウィンドウを開き、一番下のPHPDoc Blocksを選択
generate.PNG

PHPDocを生成したい関数を指定して、OKを押すと自動でPHPDocを生成してくれる

補足

Generate ウィンドウは他にgetter setterやコンストラクタも生成してくれるので便利

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

PHP: CouchDB のデータを削除 (Delete)

couch_delete.php
#! /usr/bin/php
<?php
// ------------------------------------------------------------------
//  couch_delete.php
//
//                      Jul/31/2020
//
// ------------------------------------------------------------------
include('Requests/library/Requests.php');

fputs (STDERR,"*** 開始 ***\n");
$key_in = $argv[1];
print   "key_in = " . $key_in . "\n";

Requests::register_autoloader();

$url_base = 'http://localhost:5984/nagano';
$url_target = $url_base . "/" . $key_in;

$request = Requests::get($url_target, array('Accept' => 'application/json'));

// var_dump($request->status_code);

$json_string = $request->body;
$data_aa = json_decode ($json_string,true);

// var_dump($data_aa);

if (array_key_exists ("_rev",$data_aa))
    {
    print($data_aa["_rev"] . "\n");
    print($data_aa["name"] . "\n");

    $url_del=$url_target . "?rev=" . $data_aa["_rev"];

    $result = Requests::delete($url_del);

    // var_dump($result);
    }
else
    {
    fputs (STDERR,"*** key doesn't exist ***\n");
    }

fputs (STDERR,"*** 終了 ***\n");

// ------------------------------------------------------------------

実行

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

PHP: CouchDB のデータを更新 (Update)

couch_update.php
#! /usr/bin/php
<?php
// ------------------------------------------------------------------
//  couch_update.php
//
//                      Jul/31/2020
//
// ------------------------------------------------------------------
include('Requests/library/Requests.php');

fputs (STDERR,"*** 開始 ***\n");
$key_in = $argv[1];
$population_in = $argv[2];

print   "key_in = " . $key_in . "\n";
print   $population_in . "\n";

Requests::register_autoloader();

$url_base = 'http://localhost:5984/nagano';
$url_target = $url_base . "/" . $key_in;

$request = Requests::get($url_target, array('Accept' => 'application/json'));

// var_dump($request->status_code);

$json_string = $request->body;
$data_aa = json_decode ($json_string,true);

// var_dump($data_aa);

if (array_key_exists ("_rev",$data_aa))
    {
    print($data_aa["_rev"] . "\n");
    print($data_aa["name"] . "\n");

    $url_up=$url_target . "?rev=" . $data_aa["_rev"];

    date_default_timezone_set('Asia/Tokyo');
    $today = date ("Y-m-d");

    $unit_aa = array();
    $unit_aa["name"] = $data_aa["name"];
    $unit_aa["population"] = $population_in;
    $unit_aa["date_mod"] = $today;
    $str_json = json_encode ($unit_aa);

    print $str_json . "\n";
    $headers = array('Content-Type' => 'application/json');
    $result = Requests::put($url_up,$headers,$str_json);

//  var_dump($result);
    }
else
    {
    fputs (STDERR,"*** key doesn't exist ***\n");
    }

fputs (STDERR,"*** 終了 ***\n");

// ------------------------------------------------------------------

実行

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

PHP: CouchDB のデータを読む (Read)

couch_read.php
#! /usr/bin/php
<?php
// ------------------------------------------------------------------
//  couch_read.php
//
//                      Jul/31/2020
//
// ------------------------------------------------------------------
include('Requests/library/Requests.php');

fputs (STDERR,"*** 開始 ***\n");

Requests::register_autoloader();

$url = 'http://localhost:5984/nagano/_all_docs?include_docs=true';

$request = Requests::get($url, array('Accept' => 'application/json'));

// var_dump($request->status_code);

$json_string = $request->body;
$data_aa = json_decode ($json_string,true);
$rows = $data_aa['rows'];

foreach ($rows as $unit)
    {
    $key = $unit['key'];
    $unit_aa = $unit['doc'];
    $str_out = $key . "\t" . $unit_aa["name"];
    $str_out .= "\t" . $unit_aa["population"];
    $str_out .= "\t" . $unit_aa["date_mod"];
    print "$str_out\n";
    }

fputs (STDERR,"*** 終了 ***\n");

// ------------------------------------------------------------------

実行

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

PHP: CouchDB のデータを作成 (Create)

couch_create.php
#! /usr/bin/php
<?php
// ------------------------------------------------------------------
//  couch_create.php
//
//                      Jul/31/2020
//
// ------------------------------------------------------------------
include('Requests/library/Requests.php');

fputs (STDERR,"*** 開始 ***\n");

Requests::register_autoloader();

$headers = array('Content-Type' => 'application/json');
$url_base = 'http://localhost:5984/nagano';

$result = Requests::delete($url_base);

$result = Requests::put($url_base,$headers,"{}");

$dict_aa=data_prepare_proc ();

foreach ($dict_aa as $key => $value)
    {
    $str_json = json_encode ($value);

    print $str_json . "\n";

    $url = $url_base . "/" . $key;

    $result = Requests::put($url,$headers,$str_json);
    }

fputs (STDERR,"*** 終了 ***\n");

// ------------------------------------------------------------------
function data_prepare_proc ()
{
    $dict_aa = array ();

$dict_aa = dict_append_proc ($dict_aa,'t2021','長野',18945,'2002-3-12');
$dict_aa = dict_append_proc ($dict_aa,'t2022','松本',69537,'2002-10-7');
$dict_aa = dict_append_proc ($dict_aa,'t2023','上田',72186,'2002-9-15');
$dict_aa = dict_append_proc ($dict_aa,'t2024','小諸',49672,'2002-5-22');
$dict_aa = dict_append_proc ($dict_aa,'t2025','岡谷',82341,'2002-11-11');
$dict_aa = dict_append_proc ($dict_aa,'t2026','塩尻',32597,'2002-9-21');
$dict_aa = dict_append_proc ($dict_aa,'t2027','茅野',42519,'2002-8-24');
$dict_aa = dict_append_proc ($dict_aa,'t2028','飯田',52986,'2002-9-28');
$dict_aa = dict_append_proc ($dict_aa,'t2029','中野',72513,'2002-8-5');
$dict_aa = dict_append_proc ($dict_aa,'t2030','諏訪',58146,'2002-6-17');
$dict_aa = dict_append_proc ($dict_aa,'t2031','駒ヶ根',25371,'2002-8-15');
$dict_aa = dict_append_proc ($dict_aa,'t2032','佐久',78529,'2002-4-14');
$dict_aa = dict_append_proc ($dict_aa,'t2033','伊那',29416,'2002-7-21');
$dict_aa = dict_append_proc ($dict_aa,'t2034','千曲',81729,'2002-6-19');


    return $dict_aa;
}

// ------------------------------------------------------------------
function dict_append_proc ($dict_aa,$id,$name,$population,$date_mod)
{
    $dict_unit = array ();
    $dict_unit['name'] = $name;
    $dict_unit['population'] = $population;
    $dict_unit['date_mod'] = $date_mod;
    $dict_aa[(string)$id]= $dict_unit;

    return  $dict_aa;
}
// ------------------------------------------------------------------

実行

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

PHPで正規表現を扱う際の基本的な3つのポイント

基本的なメタ文字については別記事をご覧ください

1. パターンは文字列として扱うため、' '又は" "で囲む

(例)

  • 文字末尾をチェックしたい場合
    • ⭕️ '#xyz$#'
    • #xyz$#
      • $は~で終わる を示す


2. パターンの最初と最後に区切り文字(デリミタ)が必要

  • 何でも良い
  • パターンに出現しない文字を使う

(例)

  • 文字末尾をチェックしたい場合
    • ⭕️ '#xyz$#''\xyz$\'
    • 'xyz$'


3. メタ文字はエスケープする必要がある

  • メタ文字の前に\を入れエスケープする
  • 変数展開される" "ではなく、変数展開のされない' 'で囲む必要がある

(例)

  • 拡張子をチェックしたい場合
    • ⭕️ '#\.jpg$#'
    • "#\.jpg$#"(ダブルクオートで展開される)
    • '#.jpg$#'(メタ文字の前にバックスラッシュがない)


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