CakeEmailでメール本文が文字化けする

とっても悩んで解決したのでメモを残しておく。

CakePHPのCakeEmailを初めて使ってみたら、送信したメールの本文が文字化けする。今までQdmailを使っていたので、そんな現象には合わなかった。

Googleさんに聞いてみると

CakeEmailを使っていて本文が文字化けたらとりあえずcharsetを疑ってみる

なんて書いてあるけど、charsetにISO-2022-JPを設定しても現象は変わらない。今度はメールヘッダがも文字化けする。

しかたないので、CakeEmailをNetBeansのデバッガで追ってみる。CakeEmailの_encodeString()メソッド辺りに見当をつけてブレークポイントを設定する。デバッグしてみると何とmb_convert_encoding()を処理する前にreturnしていた。

原因はmb_convert_encoding()関数が存在しないことだった。つまり、mbstringモジュールをインストールしていないことが、そもそもの原因である。

php.iniにmbstringモジュールを読み込んであげて、mbstringモジュールの設定を適当にしてphpinfo()でmbstringがサポートされていることを確認する。

今度は文字化けせずにメールを送れた。

WindowsのローカルPCに開発環境にPHPをインストールしたままで動かしたのが原因かもしれない。

PHP 5.6 にアップデートする

ここのサーバーにインストールされているPHPを5.6にアップデートする。今さら遅いくらいですが。本当なら7にアップデートすればいいのですが・・・。

remiのレポジトリを変更すれば簡単にできました。詳しくはこちらのサイトを参照のこと。この通りにやりました。

WordPressの固定ページの中に投稿最新一覧を表示する

お客さんのWordPressサイトでカテゴリごとに投稿の最新一覧を表示している固定ページがあります。いい加減手作業で更新するのも面倒になってきましたので、プログラムで対応します。

Googleさんに聞いてみるとショートコードを登録して呼び出すようなことをみなさん書いています。何と皆さん出しているPHPのコードはすべて同じです。所謂コピペ記事です。何か気持ち悪い状態になっています。さて、誰がオリジナルなんでしょうか?

しかしながら、WordPressって固定ページ内にPHPのプログラムを書けないのでしたね。今ごろ気が付きました。

そのコードをコピペしてもいいのですが、2つのカテゴリの記事一覧を表示したいので、2つコピペしなければいけませんし、第一コピペコピペで気持ち悪いです。パラメーターを渡して切り替えなんて改造すればいいのですが、それも面倒ということで、何か別の方法を探します。

What’s New Generator というよさげなプラグインが見つかりました。早速インストールして試してみます。しかし、カテゴリのフィルターが1つで固定されてしまうので、2つのカテゴリの最新一覧を並べることができません。惜しいですがこれでありません。

次に当たったのは、Shortcodes Ultimateです。基本的にショートコードでWordPressのいろいろな部分にアクセスできるのですが、今回は投稿のカテゴリ別にタイトルだけを最新3件の記事を一覧に表示します。具体的には、

[su_posts template="templates/teaser-loop.php" posts_per_page="3" tax_term="8"]

なんて書いてしまいます。出力されるタイトルがHTMLのコードのh2タグで吐き出してしまいますので、この辺りは本当なら修正しないといけないのでしょう。CSSで指定してデザインを合わせて作業完了です。

 

#baserCMS で管理者ページにログインできないときの対応メモ

今のお客さんのIRサイトをリニューアルをしたいという案件で、以前テストで作成したbaserCMSのテストサイトを復活させます。テストサイトはvagrant+VirtualBoxでローカルのPCに作成しています。

久しぶりにvagrant upでサーバーを起動してきます。Vagrantで起動したらberkshelfでのmysqlのChefのクックブックの仕様が変わって動かないというトラブルがありましたが、これは自分でレシピを作って対応します。後はMySQLのバックアップを投入すれば、今まで作成したサイトにはアクセスできます。しかし、baserCMSの管理者ページにはログインできません。

ここでNetBeansのデバッガを使ってログインの処理を追っていきます。ログインが成功した後のリダイレクトの処理以降がうまくいっていないようです。管理者ページのトップにリダイレクトしようとして、どういう訳か遷移しません。

調べてみるとCakePHPのエラーログを見ろとあります。ログには

2015-08-18 11:16:43 Warning: Warning (2): Unknown: Failed to write session data
(files). Please verify that the current setting of session.save_path is correct
(/vagrant/app/tmp/sessions) in [Unknown, line 0]

なんて書かれています。セッションデータをうまく書き込まれていないようです。

Googleさんにセッションデータがなぜ書き込めないかを聞いてみると、Vagrantの同期フォルダの権限の設定が間違っているとのこと。こちらのページのsynced_folderの設定を行うとうまく行きました。オーナーとグループをapacheにすればよさそうです。

baserCMSのGitHubにVagarantFileのサンプルがありますが、こちらのsynced_folderの設定のままだと、私のところではうまくセッションの書き込みができませんでした。今までうまくいっていましたがどうしてなのだろうか?

以上、2日位悩んだ結果のメモです。まずはCakePHPで何かあったらログを読めということでしょうか。いつも基本を忘れます。

CakePHPのDebugKitプラグインでのエラー

CakePHPを2.6.3にバージョンアップしたら、コントローラーでセットした値がビューに渡っていない。色々調べてみるとDebugKitプラグインでエラーをしている。

Could not load class DebugKitLogListenerLog

このエラーメッセージから調べると、GitHubのDebugKitのissusが見つかった。

https://github.com/cakephp/debug_kit/issues/144

APP/Plugin/DebugKit/Lib/Panel/LogPanel.phpの25行目を

'engine' => 'DebugKit.DebugKitLogListener',

'engine' => 'DebugKit.DebugKitLog',

にする。これでエラーがなくなった。

#CakePHP 3を試してみました。

環境を作ってインストールできたので、CakePHP 3を試してみました。試したみたと言ったけど、簡単にいつものブログのデータベースを作って、ControllerとModelをBakeして、使用している値をダンプしてみる。あとは、CakePHP3のドキュメントを読んでみる。

つまるところ、大幅に変わったMVCのModelの部分が肝かな。ModelがTable ObjectEntitiesになって、ORMがどう関わってくるというところが大事か。それとコントローラーとTable ObjectEntities、ビューがどう関しているかをもっと理解しなくてはいけない。

CakePHP3のドキュメントTable ObjectEntitiesを訳しながら読み進めていたけど、これはおもしろぞ。

Berkshelf のWindowsへのより簡単なインストール方法。

以前、Berkshelf のインストールが面倒、と書きましたが、もっと簡単なイントール方法が紹介されていました。紹介されていたのは、「CakePHPで学ぶ継続的インテグレーション」という本です。ここで、ChefDK(Chef Development Kit)を利用する方法が書かれています。

ChefDKを使えば、Rubyやgemをインストールことなく、ChefやBerkshelfなどのChefに関連するツールをまとめてWindows上にインストールできます。面倒なRuby関連のツールをChefDKでWindowsに簡単にでききます。これでChefを使いたいだけなのに、Ruby関連のインストールと格闘しなければいけない、なんてことがなくなります。

#PHP のis_file()で必ずfalseが返ってしまう

タイトル通り、PHP のis_file()で必ずfalseが返ってしまうということで、丸半日悩んだこと。原因は簡単なことでした。簡単なことだけど、どうせ忘れるので、覚え書きを書いておきます。

ファイルが存在するのに、is_file()で必ずfalseが返ってしまいます。調べてみたら、フルパスでファイルを指定しろとか言われます。最初からフルパスの指定です。

ローカルのVagrantで動かしているサーバー上では、正しくtrueが返ります。テストサーバーで使用している実サーバーではfalseになってしまいます。両方ともCentOSでバージョンも同じ。PHPもバージョンも同じです。

$path_name = Configure::read('Pdf.upload_dir') . $fileName;
if( is_file($path_name) ){
    :
    :

このようなCakePHPのコードです。デバックすると正しくパスからファイル名が設定されています。

ふと気なったのは、ファイル名の後ろに空白が入っていた。まさかと思ってtrim()で空白をカットしてみる。

するとうまくいった。だけど、どうしてローカルで動いていたかは謎です。

phpMyAdminでログインできない問題。#php

テストサーバーを作りたくて、いろいろとインストールします。しかし、phpMyAdminがログインできない問題に遭遇。「phpMyAdmin ログインできない」でGoogleさんに聞いた結果のサイトに書いてある通り phpMyAdmin の config.inc.php の設定ファイルを変えてもダメ、MySQLの認証を設定設定してもダメ。

しかたないので、一旦phpMyAdminを削除して、再度インストール。これもダメ。phpMyAdminの最新版をソースからダウンロードしてインストール。こちらはMySQLが古いと怒られてダメ。もうダメダメです。

ふと、Apahceのエラーログを見てみると、

[Tue Sep 23 16:46:03 2014] [error] [client 192.168..xxx.xxx] PHP Warning:  Unknown: POST Content-Length of 104 bytes exceeds the limit of -1048576 bytes in Unknown on line 0, referer: http://192.168..xxx.xxx/phpmyadmin/index.php

というのが出ていた。Unknown: POST Content-Length of というのをまたまた Googleさんに聞いてみると、php.ini の post_max_size の値が小さいとのこと。今、設定している post_max_size の値を確認してみる。すると、

; Maximum size of POST data that PHP will accept.
; http://www.php.net/manual/en/ini.core.php#ini.post-max-size
post_max_size = 3232323232323232323232323232323232323232323232323232323232323232M

となっていた。こらー誰が設定した???

post_max_size = 32M

に設定すると、無事にphpMyAdminにログインできた。phpMyAdminの問題というよりも、PHPの問題。やはり、ログを見ることは大事。

#baserCMS のPDFリンクプラグイン作成

baserCMS公式サイト10年以上お付き合いしている会社の株主向けのサイトを運営しているのですが、そろそろリニューアルしましょうということになりました。今まではベタにPHPを使って書いていましたので、キチンとPHPのフレームワークを使って作成することにします。PHPのフレームワークといっても、CakePHPしか知らないので、CakePHPで作成してきます。

CakePHPの上で作っていくのもいいのですが、今回はCakePHPの上で動いているbaserCMSというコンテンツ管理システムの上で作成して行きます。会社のサイトですので、Wordpressのように時系列で記事を並べていくのではなく、固定ページ中心ですので、WordpressではなくbaserCMSが丁度いいのです。

しかし、会社サイトといっても、株主向けのサイトでもありますので、PDFファイルのIR情報やニュースリリースを掲載しなければいけません。しかも、IR情報というのは面倒なもので、証券取引所からのお達しで発表時間よりも、PDFファイルを前に見せることは厳禁です。IR情報を見て株の売買をするのですから、発表前の情報を手に入れられてしまうことは御法度です。

そこで、PDFファイルを時間によって記事リストを生成できるようなことを実現します。時間での表示管理はbaserCMSにデフォルトでインストールされているブログプラグインに、日付でアクセス制限をする機能がありますので、こちらを利用することにします。

今回はブログブラグインにPDFファイルを登録できるようにしました。ブログプラグインのpostテーブルにPDFファイル名の項目を追加して、プラグインを直接改造する訳にはいかないので、PDFリンクプラグインを別途開発して、postテーブルに1対1でPDF情報を格納するテーブルを用意しました。これでbaserCMSがアップデートした場合にも対応できます。

ブログプラグインの管理ページでPDFファイルを指定してファイルをアップできる機能を、PDFリンクプラグインとして追加しています。同じような機能を持ったプラグインを探しても見つからなかったので自分で作ることにしました。もしも、存在したならば、今回はbaserCMSのプラグインの開発のスキルを習得できたということでよしとしましょう。

作成したbaserCMSのPDFリンクプラグインをGitHubに置いておきます。

https://github.com/muneando/basercms-plugin-pdf

ご自由にお使いください。バグを見つけたり機能アップしたら、GitHubから連絡ください。ただし、今回のサイトを作成するにあたっての必要最上限の機能しか実現していませんので、機能アップをしていただければ、大変うれしいです。

ページ内で表示するPDFファイルへのリンクは、PDFリンクプラグインのヘルパーで実現しています。ブログの本文とPDFファイルをどちらを優先してリンク先で表示できるかを、PDFリンクプラグインの管理ページで指定できます。前述の通りPDFファイルへの直リンクはダメですので、ユーザーがアクセスできないところにPDFファイルを置いて、PDFファイルをダウンロードする前に、時間をチェックできるようにしています。

使い方の説明は、GitHub の README.md をご覧ください。

このプラグインの作成で参考したのは、materializing 氏の Keyword プラグインです。参考というよりも、baserCMSのプラグインのイベント辺りは丸写しです。おかげでCakePHPのイベントについて理解できました。materializing 氏には、baserCMSのプラグインについて相談に乗っていただき感謝です。

実際に動いているサイトは、まだテスト段階なので公開していません。PDFリンクプラグイン以外にも、IRカレンダーを表示するためのbaserCMSブラグインも作成してしましました。もし、お客さんにOKいただいたら、baserCMSの利用例としてご覧いただけるようにします。