これはメモです

それ以上でもそれ以下でもないのです

Laravel10でlaravel-langを使って日本語化する

Laravel勉強中の身なので何もわかりませんがメモ。

sailを使用している前提です。またコマンドはすべてプロジェクトルートで実行する想定です。

config/app.phpの言語設定を日本語に変更

- 'locale' => 'en'
+ 'locale' => 'ja'

'fallback_locale' => 'en'については、localeで指定した言語がない場合のフォールバックだそうなので、そのままでOK。

プロジェクトルートにlangディレクトリを生成

下記コマンドを実行。

sail artisan lang:publish

下記構成でlangディレクトリが生成される。

lang
└── en
    ├── auth.php
    ├── pagination.php
    ├── passwords.php
    └── validation.php

言語化プラグインlaravel-langをインストール

sail composer require laravel-lang/lang

本番環境で使用する想定なので--devは付けていません。

日本語化の適用

sail artisan lang:update

config/app.phpの変更が反映され、langディレクトリ内に日本語化に必要なファイルが追加され下記のようになる。

lang
├── en
│   ├── auth.php
│   ├── pagination.php
│   ├── passwords.php
│   └── validation.php
├── en.json
├── ja
│   ├── auth.php
│   ├── pagination.php
│   ├── passwords.php
│   └── validation.php
└── ja.json

以上で日本語化できるはず。

【参考】

PHP CSVの1行目をキー、2行目以降を値にした連想配列を作りたい

例えば以下のようなCSVデータがあって、

"name","email"
"Sato Asuka","satoasuka@example.com"
"Goto Yousuke","yousukegoto@example.net"
"Fujita Takahiro","takahiro_fujita@example.org"

下記のような形にして扱えるようにしたいということです。

<?php
[
    [
        'name' => 'Sato Asuka',
        'email' => 'satoasuka@example.com',
    ],
    [
        'name' => 'Goto Yousuke',
        'email' => 'yousukegoto@example.net',
    ],
    [
        'name' => 'Fujita Takahiro',
        'email' => 'takahiro_fujita@example.org',
    ],
];

1. CSVファイルの読み取り

ファイル読み取りは内部関数・ファイル操作クラスを使った方法がありますが、 CSVの場合は後者のほうがスムーズなようです。

<?php
$file = new SplFileObject('./dummy.csv');
// CSVを読み取るためのオプションを指定
$file->setFlags(
    SplFileObject::READ_CSV // CSV形式のファイルを読み込む
        | SplFileObject::DROP_NEW_LINE // 行末の改行を削除
        | SplFileObject::READ_AHEAD // 先読み・巻き戻しで読み出す(?)
        | SplFileObject::SKIP_EMPTY // 空行をスキップする。 READ_AHEADの指定がないと無効
);

READ_AHEADオプションについてはよくわかりませんでした…。(どこを見ても「先読み・巻き戻し」としか書いてない)

SplFileObjectクラスはIteratorインターフェースを実装しているため、 foreachでループさせることができます。

<?php
// 1行ずつループ処理
foreach ($file as $line) {
    mb_convert_variables('UTF-8', 'SJIS-win', $line); // 任意:CSVはSJISで保存されていることが多く、その場合UTF-8への変換が必要
    print_r($line);
}

■結果

Array
(
    [0] => name
    [1] => email
)
Array
(
    [0] => Sato Asuka
    [1] => satoasuka@example.com
)
Array
(
    [0] => Goto Yousuke
    [1] => yousukegoto@example.net
)
Array
(
    [0] => Fujita Takahiro
    [1] => takahiro_fujita@example.org
)

とりあえず配列として取り出すことができました。

2. キーの配列と値の配列に分ける

ループの1番目がキーにしたい行なので、インデックスを指定すれば分けられそうです。

<?php
$keys = [];
$userList = [];
foreach ($file as $i => $line) {
    mb_convert_variables('UTF-8', 'SJIS-win', $line);
    if ($i === 0) {
        $keys = $line;
    } else {
        $userList[] = $line;
    }
}
print_r($keys);
print_r($userList);

■結果

Array
(
    [0] => name
    [1] => email
)
Array
(
    [0] => Array
        (
            [0] => Sato Asuka
            [1] => satoasuka@example.com
        )

    [1] => Array
        (
            [0] => Goto Yousuke
            [1] => yousukegoto@example.net
        )

    [2] => Array
        (
            [0] => Fujita Takahiro
            [1] => takahiro_fujita@example.org
        )

)

問題なく分けられました。

3. 2.で得られた配列から、表題の連想配列を作成する

「2つの配列をキー、値にして一つにする関数とかありそうだな。PHP死ぬほど関数あるし」と思ってたらありました。

www.php.net

キーと値の要素数が一致しないと配列が作成できないため、ループ内で配列を作成します。

<?php
$keys = [];
$userList = [];
foreach ($file as $i => $line) {
    mb_convert_variables('UTF-8', 'SJIS-win', $line);
    if ($i === 0) {
        $keys = $line;
    } else {
-        $userList[] = $line;
+        $userList[] = array_combine($keys, $line);
    }
}
- print_r($keys);
print_r($userList);

■結果

Array
(
    [0] => Array
        (
            [name] => Sato Asuka
            [email] => satoasuka@example.com
        )

    [1] => Array
        (
            [name] => Goto Yousuke
            [email] => yousukegoto@example.net
        )

    [2] => Array
        (
            [name] => Fujita Takahiro
            [email] => takahiro_fujita@example.org
        )

)

PHP シングルクォーテーションとダブルクォーテーションの違いにハマる

悔しいので備忘としてメモ。

以下のような文字列の改行をhtmlの<br>に変換したくnl2br()を使用したものの、 もともとあった改行が削除されない。

<?php
// <textarea>などで入力されたテキストとお考えください
$text = <<<EOL
あいうえお
かきくけこ
EOL;
var_dump(nl2br($text, false));

出力

string(35) "あいうえお<br>
かきくけこ"

これではhtmlとして表示された際に余分なスペースが空いてしまうことになる。 そのためstr_replace()を使用して改行を削除しようとしたのだが…

<?php
$text = <<<EOL
あいうえお
かきくけこ
EOL;

$newText = nl2br($text, false);
$newText = str_replace(['\r\n', '\r', '\n'], '', $newText);
var_dump($newText);

出力

string(35) "あいうえお<br>
かきくけこ"

結果が何も変わらず、依然として改行文字が残り続けている状態。 結果として、改行文字をくくるのにシングルクォーテーションを使っていることが原因だった。

// \nの場合
シングル -> 単なる \n という文字列として扱う
ダブル -> 改行文字として扱う

php.netにも記載がある。

文字列を指定する最も簡単な方法は、引用符 (文字 ') で括ることです。(中略) \r や \n といったおなじみのエスケープシーケンスを書いても特別な効果は得られず、 書いたままの形式で出力されます。

www.php.net

シングルクォーテーションをダブルクォーテーションに変更して試してみる。

<?php
$text = <<<EOL
あいうえお
かきくけこ
EOL;

$newText = nl2br($text, false);
- $newText = str_replace(['\r\n', '\r', '\n'], '', $newText);
+ $newText = str_replace(["\r\n", "\r", "\n"], '', $newText);
var_dump($newText);

出力

string(34) "あいうえお<br>かきくけこ"

無事、改行文字を削除することができた。

シングルクォーテーションとダブルクォーテーションの違いは変数展開ができる・できないくらいの認識だったので勉強になった。

でも少ないとはいえ時間を溶かしてしまったので悔しい。

【参考】

$wp_queryをブラウザコンソールに出力して簡易デバッグを行う

WordPressデバッグに便利な'query monitor'というプラグインがある。

ja.wordpress.org

有用なのだが、ブラウザの開発者ツールと合わせて開くと画面を占領してしまうという難点がある。 また、知りたい情報に対して情報量が多すぎると感じる場面が多い。

そこで簡易的にデバッグする方法。メインクエリの$wp_queryをブラウザコンソールに出力することで、var_dump()のようにブラウザの表示に影響を与えることなく条件分岐やSQLなどを確認できる。

  • wp-config.phpで'WP_ENVIRONMENT_TYPE'を指定しておく必要あり
<?php
add_action(
    'wp_head',
    function(){
        if( wp_get_environment_type() === 'production' ){
            return;
        }
        if( is_main_query() && is_user_logged_in() ){
            global $wp_query;
            $json = json_encode( $wp_query );
            echo "<script async>console.log( '\$wp_query:', {$json} );</script>";
        }
    }
);

外部に漏らしてはいけない情報も含まれているため、wp_get_environment_type()is_user_logged_in()などを使用して開発者にのみ表示されるようにしている。

この他に、自分は$_SERVERの値を確認する機会があるのでこちらも出力している。

<?php
add_action(
    'wp_head',
    function(){
        if( wp_get_environment_type() === 'production' ){
            return;
        }
        if( is_main_query() && is_user_logged_in() ){
            $json = json_encode( $_SERVER );
            echo "<script async>console.log( '\$_SERVER:', {$json} );</script>";
        }
    }
);

var_dump()を書いたり消したりする手間が省けなかなか快適。よかったら試してみてください。

PHP URLをいい感じに分解する

WordPressで、月別アーカイブパーマリンクを下記のように書き換えたいケースに遭遇した。

// これを
https://example.com/2022/11/?post_type=cpt

// こう書き換えたい
https://example.com/cpt/date/2022/11/

「URLは'/'で区切られてるからそれでexplode()して、ごにょごにょすればいけるでしょ」と思っていたが、そう甘くはなかった。

<?php
var_dump(explode('/', 'https://example.com/2022/11/?post_type=cpt'));
array(6) {
  [0]=>
  string(6) "https:"
  [1]=>
  string(0) ""
  [2]=>
  string(11) "example.com"
  [3]=>
  string(4) "2022"
  [4]=>
  string(2) "11"
  [5]=>
  string(14) "?post_type=cpt"
}

感じた問題点としては、

  1. 'https://'のスラッシュもヒットして消えてしまう
  2. '2022/11/'の部分など不要な部分まで分解される
  3. クエリはそのまま残るので、必要な部分を取り出すのにもうひと手間必要

という感じで、全体的に少し冗長に感じた。

なにかいい方法がないかとググったところ、良さそうな関数を発見。

parse_url()を使う

www.php.net

前述のURLに適用すると、こんな感じ。

<?php
var_dump(parse_url('https://example.com/2022/11/?post_type=cpt'));
array(4) {
  ["scheme"]=>
  string(5) "https"
  ["host"]=>
  string(11) "example.com"
  ["path"]=>
  string(9) "/2022/11/"
  ["query"]=>
  string(13) "post_type=cpt"
}

問題点の2.しか解決していないのだけど、より意図が明確になると感じたのでこちらを使用した。

一連の操作は以下の通り。

<?php
$url = 'https://example.com/2022/11/?post_type=cpt';
$url_frags = parse_url($url);

$origin = $url_frags['scheme'] . '//' . $url_frags['host'];
$post_type = str_replace('post_type=', '', $url_frags['query']);
$new_url = $origin . '/' . $post_type . '/date' . $url_frags['path']; // "https//example.com/cpt/date/2022/11/"

注意点

php.netにも記載があるように、

  • URLデコードされない
  • 不正なURLでも受け入れる

ため、デコードやチェックは自前で行う必要がある。

WordPressではwp_parse_url()を使う

WordPressのフォーマッタを入れていると、 wp_parse_url()を使えと怒られる。

これは、PHPのバージョン間でparse_url()の戻り値の一貫性を保つためのものらしい。そのためWordPressでURLを分解したい場合はwp_parse_url()を使うのがベターのよう。

[参考]

MAMP環境でMySQLのパスを通す

ほぼ参考サイトと同じですが、メモ。

手順

  1. ルートディレクトリに移動
  2. .bash_profileの作成、パス書き込み
  3. パスの反映
  4. パスが通っているかテスト

1. ルートディレクトリに移動

cdだけ入力するとルートに移動。

cd

2. .bash_profileの作成、パス書き込み

viで.bash_profileファイルを開く。(なければ新規作成される)

vi .bash_profile

MAMPにある、MySQLの実行ファイルにパスを通す。新規作成時はoを入力してテキスト挿入モードに入る。

export PATH=$PATH:/Applications/MAMP/Library/bin

binディレクトリは実行ファイルなどを格納するディレクトリ。パスを通すことで、binディレクトリまで移動せずともMySQLの実行ファイルを実行することができる。

終わったらesc>:wqで保存する。

補足:viのコマンド

viわからないので備忘。慣れると操作性良さそう。

コマンド 意味
o カーソルがある下の行にテキストを挿入
:wq 変更を保存して vi を終了

3. パスの反映

以下のコマンドでパスを反映させる。sourceコマンドは、設定ファイルの更新後直ちにその内容を実行中のシェルに反映させるのに使われる。

source .bash_profile

4. パスが通っているかテスト

パスが通っていれば、以下コマンド入力後パスワードが求められる。

mysql -u root -p

コマンドの意味

  • mysqlMySQLに接続(ログイン)
  • -u root … rootユーザーで
  • -p … パスワードを指定

ちなみに、-Dオプションではデータベース指定が、-hでホスト指定ができる。

参考