[PHP 7.4.11] 消費税の1円以下の端数処理を考える

財務省の見解

「税抜価格」に上乗せする消費税相当額に1円未満の端数が生じる場合がありますが、その端数をどのように処理 (切捨て、切上げ、四捨五入など)して「税込価格」を設定するかは、それぞれの事業者のご判断によることとなります。

え? 要するになんでもいいの?
phpで計算するとき。

$price = 5678;
echo $price * 0.1;

-> 567.8

$price = 5678;
echo floor($price * 0.1) . "<br>"; // 切り捨て
echo ceil($price * 0.1) . "<br>"; // 切り上げ
echo round($price * 0.1) . "<br>"; // 四捨五入

567
568
568

切捨て、切上げ、四捨五入 どれでも対応はできるようです。って当たり前か。

[PHP7.4.11] 郵便番号の正規表現(ハイフン有無)

$zipcode = ["100-0001","1000001","abcdefg"];
foreach($zipcode as $data){
	if(preg_match("/^(([0-9]{3}-[0-9]{4})|([0-9]{7}))$/", $data)){
		echo $data . " is ok<br>";
	} else {
		echo $data . " is not zipcode<br>";
	}
}

ハイフン有りのみの場合は

/^[0-9]{3}-[0-9]{4}$/

電話番号

/^(([0-9]{2,4}-[0-9]{2,4}-[0-9]{3,4})|([0-9]{8,11}))$/

OK、これでカスタムバリデーションを作っていく

[aws/aws-sdk-php 3.166.2] 複数画像をphpでS3にアップロード

$ composer require aws/aws-sdk-php

require_once "vendor/autoload.php";

$bucket = '';
$key = '';
$secret = '';

$s3client = new Aws\S3\S3Client([
    'credentials' => [
        'key' => $key,
        'secret' => $secret,
    ],
    'region' => 'ap-northeast-1',
    'version' => 'latest',
]);

$file = "img/flower.jpg";

$result = $s3client->putObject(array(
	'Bucket' => $bucket,
	'Key' => 'test/flower.jpg',
	'ACL' => 'public-read',
	'SourceFile' => $file,
	'ContentType' => mime_content_type($file),
));

echo "<pre>";
var_dump($result);
echo "</pre>";

これをファイル複数一括で行いたい。
複数ファイルの取得はglobだったかな。

foreach(glob("img/*.*") as $file) {
    $files[] = $file;
}

$s3client = new Aws\S3\S3Client([
    'credentials' => [
        'key' => $key,
        'secret' => $secret,
    ],
    'region' => 'ap-northeast-1',
    'version' => 'latest',
]);

foreach($files as $file){
		$result[] = $s3client->putObject(array(
		'Bucket' => $bucket,
		'Key' => $file,
		'ACL' => 'public-read',
		'SourceFile' => $file,
		'ContentType' => mime_content_type($file),
	));
}

echo "<pre>";
var_dump($result);
echo "</pre>";

ちょっと時間かかるな。手動でやった方が良さげ。

[PHP] 拡張子不明の画像名を変数として持ち、imgフォルダ内にあれば表示

imgフォルダ内に画像が複数(数千枚)置いてあり、拡張子は不明だが、ファイル名だけ変数として持っており、該当のファイル名があればその画像を表示、無ければplaceholderの画像を表示したい。

まず画像を用意します。

拡張子分foreachで探してみたが、

$name = "cat";
$cfg = array('jpg', 'jpeg', 'png', 'gif');

foreach($cfg as $key){
	if(file_exists("img/" .$name . "." . $key)){
		echo "<img src='img/" . $name . "." .$key."' width='150px' height='100px'>";
	}
}

これだと、拡張子の配列分回さないといけないのと、画像が無ければ、placeholderの表示ができない。

globとワイルドカードを使う

$name = "cat";
$result = glob("img/" . $name . ".*");

if(in_array($result)) {
	echo '<img src="'.$result[0].'" width="150px" height="100px">';
} else {
	echo '<img src="/img/150x150.png">';
}

OK!上等!
続いて、少々細かいことを調査していきます。

[PHP7.4.11] 二次元配列に空白の列を追加してCSVでダウンロード

### CSVの作成
– 文字化けしないよう、stream_filter_prepend($f,’convert.iconv.utf-8/cp932′);の一文を挿入する

$ary = [
	["名前", "年齢", "血液型", "備考"],
	["山田", "12", "O",""],
	["田中", "20", "A",""],
	["吉田", "18", "AB",""],
	["伊藤", "19", "B", "エンジニア"]
]; 

$filename = "test.csv";
$f = fopen($filename, "w");
stream_filter_prepend($f,'convert.iconv.utf-8/cp932');
if($f) {
	foreach($ary as $line){
		fputcsv($f, $line);
	}
}

fclose($f);

### 配列にカラムを追加

$ary = [
	// ["名前", "年齢", "血液型", "備考"],
	["山田", "12", "O",""],
	["田中", "20", "A",""],
	["吉田", "18", "AB",""],
	["伊藤", "19", "B", "エンジニア"]
]; 
$column = ["名前", "年齢", "血液型", "備考"];

array_unshift($ary,$column);

### 配列の途中に空白を追加

$column = ["名前", "年齢", "血液型", "備考"];

array_splice($column, 1, 0, "");

echo "<pre>";
var_dump($column);
echo "</pre>";

### 二次元配列の途中に空白を追加

// DBから抽出
$ary = [
	["山田", "12", "O",""],
	["田中", "20", "A",""],
	["吉田", "18", "AB",""],
	["伊藤", "19", "B", "エンジニア"]
]; 

// 空白追加
foreach($ary as $key => $value){
	 array_splice($ary[$key], 1, 0, "");
}

// カラム追加
$column = ["名前", "無記入", "年齢", "血液型", "備考"];
array_unshift($ary, $column);

echo "<pre>";
var_dump($ary);
echo "</pre>";

これでCSVをエクスポートすると…

### csv.fileのダウンロード

$filename = "test.csv";
header('Content-Type: application/octet-stream');
header('Content-Length: '.filesize($filename));
header('Content-Disposition: attachment; filename=test.csv');

readfile($filename);

作成とダウンロードを一緒にやる場合の方が多いと思うが、予め作成したcsvファイルをダウンロードするだけ、ということも可能。
OK, 次行こう。

[PHP7.4.11] 配列の足し算

$ary = [
	"いちご" => 1,
	"バナナ" => 2
];

foreach($ary as $key => $value){
	if($key == "いちご"){
		$ary["いちご"] = $value + 3;
	}
}
echo "<pre>";
var_dump($ary);
echo "</pre>";


なるほど、これを応用する

$ary = [
	"A商事" => 1200,
	"B商事" => 2000
];


$name ="C商事";
$subtotal = 2000;

foreach($ary as $key => $value){
	if($key == $name){
		$ary[$key] = $value + $subtotal;
	} else {
		$ary[$name] = $subtotal;
	}
}

echo "<pre>";
var_dump($ary);
echo "</pre>";

OK, これをLaravelでやりたい。

[PHP7.4.11] 多次元配列

$ary = [
	"fruits" => ["apple", "banana"],
	"animal" => ["monkey", "cat"]
];

$ary["fruits"][] = "kui";

foreach($ary as $key => $value){
	echo "-" . $key . "<br>";
	foreach($value as $k => $v){
		echo $v . " ";
	}
	echo "<br>";
}

– 二次元配列の中に配列を入れたい

$ary = [
	"A商事" => [
		"注文1" => ["商品1", "500円", "3個", "1500円"],
		"注文2" => ["商品2", "600円", "2個", "1200円"]
	],
	"B商事" => [
		"注文3" => ["商品3", "700円", "1個", "700円"]
	]
];

$ary["B商事"]["注文4"] = ["商品4", "200円", "10個", "2000円"];

echo "<pre>";
var_dump($ary);
echo "</pre>";

これを呼び出したい

foreach($ary as $key => $value){
	echo "-". $key . "<br>";
	foreach($value as $k => $v){
		echo $k. ":";
		foreach($v as $n => $data){
			echo $data . " ";
		}
	}
	echo "<br>";
}

OK、 これに$keyごとの小計を加えたい

[PHP7.4.11] 二次元配列

配列の中に配列

$ary = [
["a", "b", "c", "d"],
["e", "f", "g", "h"],
["i", "j", "k", "l"]
];

echo "<pre>";
var_dump($ary);
echo "</pre>";

配列の追加

$ary = [
// 省略
];

$ary[] = ["m", "n", "o", "p"];

多次元配列

$ary = [
	"fruits" => ["apple", "banana"],
	"animal" => ["monkey", "cat"]
];

多次元配列の追加

$ary = [
	"fruits" => ["apple", "banana"],
	"animal" => ["monkey", "cat"]
];

$ary_b = [
	"contory" => ["japan","usa"]
];


echo "<pre>";
var_dump(array_merge($ary, $ary_b));
echo "</pre>";

ただこれ、下のようにやると、fruitsが上書きされてしまうな。

$ary = [
	"fruits" => ["apple", "banana"],
	"animal" => ["monkey", "cat"]
];

$ary_b = [
	"fruits" => ["kui"]
];

こうすると上手くいく

$ary = [
	"fruits" => ["apple", "banana"],
	"animal" => ["monkey", "cat"]
];

$ary["fruits"][] = "kui";

echo "<pre>";
var_dump($ary);
echo "</pre>";

OK, これを応用して考える

[PHP 7.4.11] MySQLにCSVインポートする

### dbとテーブルの作成
mysql> create database myapp;
mysql> use myapp;
mysql> create table users(
-> id int primary key auto_increment,
-> name varchar(255),
-> sports varchar(255)
-> );

nameとsportsを入れたcsvファイル(users.csv)を作成します。

### pdoの確認
$ php -i|grep PDO
PDO
PDO support => enabled
PDO drivers => mysql, sqlite
PDO Driver for MySQL => enabled
PDO Driver for SQLite 3.x => enabled

### csv.php

ini_set('display_errors', 1);

try {
		$pdo = new PDO('mysql:host=localhost;dbname=myapp;charaset=utf8','root','****',
				array(PDO::ATTR_EMULATE_PREPARES => false));
	} catch (PDOException $e){
		exit('データベース接続失敗.'.$e->getMessage());
	}

$fp = fopen("users.csv", "r");

while(! feof($fp)){
	$csv = fgets($fp);
	$csv = trim($csv,'"');
	$csv = mb_convert_encoding($csv, "UTF-8", "utf-8");
	$csv = str_replace('"','',$csv);
	$csv_array = explode(",",$csv);

	$stmt = $pdo->prepare("INSERT INTO users(name, sports) VALUES(:name, :sports)");

	$stmt->bindParam(':name', $csv_array[0],PDO::PARAM_STR);
	$stmt->bindParam(':sports', $csv_array[1],PDO::PARAM_STR);
	$stmt->execute();
}

echo "insert done";

$ php csv.php
insert done

mysql> select * from users;
+—-+—————–+—————-+
| id | name | sports |
+—-+—————–+—————-+
| 1 | name | sports
|
| 2 | Efa Trujillo | Gynastics
|
| 3 | Erica Werner | Rowing
|
| 4 | Amin Guerrero | Wiffleball
|
| 5 | Abbie Bender | Rugby
|
| 6 | Kamron Mcneill | Surfing
|
| 7 | Arabella Sutton | Basketball
|
| 8 | Emily Kerr | Curling
|
| 9 | Connar Small | Ice skating
|
| 10 | Haidar Fletcher | Figure skating |
+—-+—————–+—————-+
10 rows in set (0.00 sec)

1行目からinsertされてしまうので、1行目は抜かす必要がありますね。