PHP」タグアーカイブ

Escape

INI ファイルの読み書きページを更新しました。
INI ファイルの読み書き – Paepoi

セクションを見つける正規表現に最初戸惑った。

EXP = r'^\[\w+\]$'

でイケると思ったけど文字列に半角スペースがあると認識できない。
半角スペースを使うなで済ませようとも思ったけど。

EXP = r'^\[[^\]]+\]$'

そうだ「閉じブラケット以外の文字列なら何でもいい」にすれば!
こんなアホな思いつきに対応できる正規表現ってやはり面白い。

とほほの正規表現入門 – とほほのWWW入門
ところで、とほほさんで見た「ブラケット内は記号の意味を失う」なんですが。

#! /usr/bin/env python3

import re

# [..] にマッチさせる正規表現
EXP = r'^\[[^\]]+\]$'
# EXP = r'^\[[^]]+\]$' # Python OK

a = ['[test]', '[test2]', '[test3] ', ' [test4]', '[test 5]']

for s in a:
    if re.search(EXP, s):
        print(s)

Python

#! /usr/bin/env php

<?php

// [..] にマッチさせる正規表現
$EXP = '/^\[[^\]]+\]$/';
// $EXP = '/^\[[^]]+\]$/'; # PHP OK

$a = ['[test]', '[test2]', '[test3] ', ' [test4]', '[test 5]'];

foreach ($a as $s) {
    if (preg_match($EXP, $s))
        echo $s.PHP_EOL;
}
?>

PHP

#! /usr/bin/gjs

// [..] にマッチさせる正規表現
const EXP = /^\[[^\]]+\]$/;
//const EXP = /^\[[^]]+\]$/; // Gjs NO

let a = ['[test]', '[test2]', '[test3] ', ' [test4]', '[test 5]'];

for (let s of a) {
    if (EXP.test(s)) {
        print(s)
    }
}

Gjs ダメだった。

JavaScript エンジンは複数あるので全部かどうかは試していないけど。
エスケープすれば全部イケたのでブラケット内もエスケープしたほうがいいかと。

PHP8: match switch

そういえば PHP8 について調べなきゃ。
と書いて一ヶ月もたっていたわい。

【PHP8.0】PHP8.0の新機能 – Qiita

変更というよりひたすら機能強化みたい。
筆者に関係ありそうなのは match くらいしかないな。
str_starts_with や str_contains は正規表現でいいし。

#!/usr/bin/env php

<?php

$text = "最初含む最後";

if (preg_match('/含む/', $text)) echo "@含む@";
if (preg_match('/^最初/', $text)) echo "@最初@";
if (preg_match('/最後$/', $text)) echo "@最後@".PHP_EOL;;

//=> @含む@@最初@@最後@

?>

ね。

match は Python 3.10 にも追加されたし流行なのだろうか。
Python と同じ感じなのか試してみよう。

#!/usr/bin/env php

<?php

function switch_func($num) {
    switch($num) {
        case 1:
            echo 'one;';
            //break;
        case 1:
            echo 'once again;';
            //break;
        default:
            echo 'default;';
    }
}

function match_func($num) {
    $s = match($num) {
        1 => 'one;',
        1 => 'once again;',
        default => 'default;'
    };
    echo $s;
}

switch_func(1);
echo PHP_EOL;;
match_func(1);

/* output
one;once again;default;
one;
*/

?>

全然違った。

PHP の match は値を返す式で最後にセミコロン必須。
switch とはそもそもの書式が違うので混同するはずがない。
break が不要なのとマッチしなかった場合の処理があるのは Python と同じ。

match 式内で echo とかはできない、戻り値が必要な場面に限定される。
けれどそういう場合 if や switch より圧倒的に短いコードになるね。
Python の match もこんな感じにすれば良かったのに。

PHP Imagick

さて PHP をやるといっても言語仕様なんてすぐに理解できる。
筆者はすぐ忘れる人なのでまたチップスページを作る、はいいとして。
PHP で何をやるかだ、とりあえず画像のリサイズだな。

PHPで画像をリサイズしよう!表示・保存方法もわかる | 侍エンジニア塾ブログ(Samurai Blog) – プログラミング入門者向けサイト

GD は定番として Imagick ってココ(さくら)で使えるのかな?
手持ちパソコン内だけで可能なのでは意味がないし。
と思ったけれど、どちらも問題なく使えるようだ。

【さくらのレンタルサーバ】基本仕様 ? さくらのサポート情報

ところで Fedora 自体は PHP をインストールしただけでは両方使えない。
てなわけで dnf する。

sudo dnf install php-gd php-pecl-imagick

httpd を通すのが面倒だからスクリプトで直接試す。
Linux はコレができるから楽なんだよね。

#!/usr/bin/env php

<?php

    // php-gd
    [$width, $hight] = getimagesize('test.jpg');
    $baseImage = imagecreatefromjpeg('test.jpg');
    $image = imagecreatetruecolor(100, 100);
    imagecopyresampled($image, $baseImage, 0, 0, 0, 0, 100, 100, $width, $hight);
    imagejpeg($image , 'out_01.jpg');

    // php-pecl-imagick
    $image2 = new Imagick('test.jpg');
    $image2->thumbnailImage(100, 0); // Segmentation fault...
    $image2->writeImage('out_02.jpg');
    $image2->clear();

?>

Imagick::thumbnailImage でセグメンテーション違反になってしまうヤン。
縮小画像は問題なく作成されるけど。
下記のように起動すればこのエラーは出なくなる、けどソレでいいのか?

env MAGICK_THREAD_LIMIT=1 php test.php

おまけ、cairo も使えるんだね。
PHP: Cairo – Manual
94. PHPからCairoを使う | 日経 xTECH(クロステック)

dnf で見つからないし必要性もあまり感じないので無視するけど。
せっかくなのでリンク先コードを Python3 で書き直ししてみた。
create なんてメソッドは無いのでこんなふうに。

#!/usr/bin/env python3

import cairo

surface = cairo.PDFSurface('sample.pdf', 605.0, 855.0)
cr = cairo.Context(surface)

cr.set_source_rgb (0.0, 0.0, 1.0)

cr.move_to(150, 150)
cr.select_font_face('Monospace', cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
cr.set_font_size(72)
cr.show_text('日本語OK!')
cr.show_page()

# 破棄はガベージコレクション

Linux てか GNOME って本当にプログラミングは楽チンだよね。

PHP SELinux

Fedora Tips | Web 開発
なんてページを作ったのだから超久々に PHP をやろうと思う。
だってプログラミングといいながらインストールして設定してハローワールドするだけじゃまるでサルブンツみたいじゃん、やだー。

というか筆者の知識は PHP 5、それも一部分で止まっているままだったりする。
本サイトも全部 PHP だけど 5 でも 7 でも動く標準関数しか使っていないかったり。
fstring(Python3) やアロー関数(js)をガッツリ使っているのにコレじゃいかん。

基本から PHP を勉強やりなおし、いきなり詰まった。
SELinux で。
write.txt には 666 のパーミッションを付けてね。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Write Test</title>
</head>
<body>
<p>
<?php
    file_put_contents("write.txt", "SUZUKI のバイクはカッコイイ<br />\n", FILE_APPEND);
    echo file_get_contents("write.txt");
?>
</p>
</body>
</html>

リロード毎に行が追記されるサンプル。
のはずなのに PHP でファイルへの書き込みできない!

SELinux にブロックされていると気がつくのに時間が掛かった。
ほわいとのホームサーバ:Fedora構築メモ

httpd 経由で書き込みを行う属性を付ける必要があるみたい。
Fedora 30 では以下でイケた。

# chcon -t 属性名 ファイル名
chcon -t httpd_sys_rw_content_t write.txt

しかもこの属性、Gedit で上書きとかすると消えちゃう。
面倒だと思ったと同時にサーバー用途と考えるとなるほどって感じ。
いやいや SELinux の勉強になった。

関係ないけど file_get_contents って GLib の関数と同じジャン!
echo は sh だし、Linux に慣れた人は多分 PHP が楽しい。

Here Document

ヒアドキュメントが便利なのでもう少し調べる。
Y901x のインストールスクリプトで使っているから経験はあるのだが。

ヒアドキュメント – Wikipedia

シェルスクリプトはバッククォーテーションでコマンドも使えるのか。

#!/bin/sh

func() {
    echo バッククオートで関数も使える
}
shstr=シェルスクリプト
hdstr=ヒアドキュメント

cat << __EOS__
${shstr}で$hdstrは今更だけど
最初の改行は無視される、最後は echo や cat が改行する
エスケープ文字 \\ は有効
記号は\$とバッククオートを除いて <'"{[+=~ と普通に使える
`func`
__EOS__

自作関数でもいいようだ。

# output
シェルスクリプトでヒアドキュメントは今更だけど
最初の改行は無視される、最後は echo や cat が改行する
エスケープ文字 \ は有効
記号は$とバッククオートを除いて <'"{[+=~ と普通に使える
バッククオートで関数も使える

これはもしかして PHP でも関数が使えるかも。

<?php

function func() { return "関数"; }
$plstr = "Perl";
$shstr = "シェルスクリプト";

echo <<< __EOS__
PHP は${shstr}や $plstr 同様に利用できる
最初と最後の改行は無視されるので最後は一行開けるとよし
エスケープ文字 \\ は有効
記号は\$を除いて <'"{[+=~` と普通に使える
`func` って PHP にこんな機能はもともと無いよ!

__EOS__;
/* output
PHP はシェルスクリプトや Perl 同様に利用できる
最初と最後の改行は無視されるので最後は一行開けるとよし
エスケープ文字 \ は有効
記号は$を除いて <'"{[+=~` と普通に使える
`func` って PHP にこんな機能はもともと無いよ!
*/
?>

んなわけないか。
ところで PHP のヒアドキュメントは最後を改行しなくて最初戸惑った。
よく考えたら echo, cat, print() が改行していただけだった。
PHP の echo は改行しないもんね。

Perl や Lua って Fedora に最初から入っているけど使ったことが無いな。
余程のことがないかぎり今後も使うことは無いと思うけど。
GNOME は以前 JavaScript を押していたけど今はどうなんだろう?

// Gjs
// imports /usr/share/gjs-1.0/format.js

const Format = imports.format;

String.prototype.format = Format.format;

let jstr = "\
JavaScript はエスケープで強引な改行しか手段が無い\n\
更に%s機能は無い\n\
しかし %s ならこんなことができる\n\
%%s, %%d, %%x, %%f のみ";

print(jstr.format("文字列フォーマット", "Gjs"));
/*
JavaScript はエスケープで強引な改行しか手段が無い
更に文字列フォーマット機能は無い
しかし Gjs ならこんなことができる
%s, %d, %x, %f のみ
*/

これだものな。
面倒臭くなってブン投げたのは筆者だけではないと思う。

#include <stdio.h>

#define CSTR "\
%s は\n\
説明不要だよね\n"

int
main (int argc, char ** argv) {
	printf (CSTR, "C 言語");
	return 0;
}
/*
C 言語 は
説明不要だよね
*/

C のほうが簡単なんて洒落にもならん。
プラス記号で成形するのって最初は分かり易いのでいいと思うが。

#!/usr/bin/env python3

DOCSTR = """{0} はお馴染 {1}
最初と最後の改行も有効だけど print が最後を改行する
{2}
{1} は \\ エスケープが有効"""

def func():
    return "関数は format で実行すれば文字列さ"

print(DOCSTR.format("Python", "docstring", func()))

''' output
Python はお馴染 docstring
最初と最後の改行も有効だけど print が最後を改行する
関数は format で実行すれば文字列さ
docstring は \ エスケープが有効
'''

あぁ楽チン、やっぱりコレだよコレ!

しかしやっぱりヒアドキュメントに変数を直書きできたほうが便利。
それには $ 記号を変数に利用する言語しか無理なんだろうな。
と思っていました。

// Vala

const string DOCSTR = """Python と同じ
%s も使える、でも ''' は使えない
何故か \\ エスケープ\nは使えない
""";

string func() { return "無理"; }

int main (string[] args) {
    string one = "Vala";
    string tow = "ヒアドキュメント";
    stdout.printf(@"$one は実は@\"\"を使って$towもどきが利用できる
ですが$${one}みたいなブレース表記はダメみたい
最初と最後の改行も有効、エスケープ文字 \\ は有効
記号は$$と\"を除いて <'{[+=~` と普通に使える
`func` は当然不可能\n\n");
    //
    stdout.printf(DOCSTR, "docstring");
    return 0;
}
/* output
Vala は実は@""を使ってヒアドキュメントもどきが利用できる
ですが${one}みたいなブレース表記はダメみたい
最初と最後の改行も有効、エスケープ文字 \ は有効
記号は$と"を除いて <'{[+=~` と普通に使える
`func` は当然不可能

Python と同じ
docstring も使える、でも ''' は使えない
何故か \\ エスケープ\nは使えない
*/

Vala はやってくれました。
おかげで解った、滅茶苦茶使い辛いということを。
これなら docstring 方式のほうがいいや。

最後に、Gedit の色分けってスゴすぎる!

gedit

まさかこの Vala の $ 変数を見分けて色分けするとは思わなかった。
PHP 部分と HTML 部分をしっかり見分けるとかは知っていたが。
どの言語でもヒアドキュメント内でマズい記号を打つと即座に色が変わる。
これがデフォルトエディタって GNOME 恐るべしだよ。