CakePHP 2.3.10 変更点
公式アナウンス
今回のリリースはバグフィックスリリース
です。
パフォーマンスの改善、PHP5.5.2でのSessionの動作改善、Emailクラスの改善が主な変更点になります。
また、CakePHP2.3系のリリース方針についてアナウンスがあり、CakePHP2.6.0までセキュリティフィックスを継続していくそうです。
今回は同時に CakePHP2.4 もリリースされています。 CakePHP3 の開発も CakePHP2系以上にリソースをつぎ込んで開発が進められており、 片手間ではコミットを追いきれないほどです。
主な変更点
ドキュメント・テストケース・小さな修正は除きます。
全般
- null チェックが
is_null
から=== null
へ統一され、パフォーマンスを改善した=== null
はis_null
より 40倍程度高速に動作する。
Network/Email
AbstractTransport::config
が引数を直接代入していたのを、$config + $this->_config
になり、デフォルト値が省略できるようになった。SmtpTransport::config
でもarray_merge($default, $this->_config, $config)
に変更になった。
CakeEmail::_renderTemplates
'layout' が null の場合、レイアウトが描画されなくなった- ドキュメントでは null で描画と停止できると書いてあるが、null をそのまま View::render に渡すと、null はデフォルトレイアウトを呼び出す意味を持っているので、正しい挙動ではなかった。
- null を渡すと、View::render で描画されない false に内部で置き換わるようになった。
Utility/CakeTime
CakeTime::timeAgoInWords
過去の時間を約1日前などと大雑把に表現できるようになった。また、翻訳も可能にした。CakeTime::CakeTime
strtotime("0000-00-00 00:00:00") の結果が32bit(FALSE)と64bit(-62169955200)で異なるため、false を返すよう修正
Utility/CakeNumber
CakeNumber::precision
整数区切に「,」を使う国・地域の場合、結果が正しくなかったのを修正
Model/AclNode
AclNode::node
結合が'LEFT'から'INNER'へ変更し、パフォーマンスの向上を図る- 2.3.9で変更されなかった部分が今回変更され、すべて'INNER'で結合されるようになった。
Utility/Sanitize
Sanitize::paranoid
データベースとのコネクションを開くのを引数チェックの前から後へ変更し、パフォーマンスを改善した
Routing/Route
RedirectRoute::parse
options['persist'] を正しく運用するよう変更された
Model/Model
Model
使用されていないdeleteQuery
insertQuery
が削除された- 1.3 までの機能であり、利用ようとしても利用できなく、ユーザーに混乱を招くため、削除された。
Console/ShellDispatcher
ShellDispatcher::_initEnvironment
'ROOT' 'APP_DIR' 'APP' の定数が事前に定義済みかどうかを判別するようになり、外部から制御できるようになった。
Model/Datasource
CakeSession::_defaultConfig
'session.auto_start' => 0,
が削除された
Model/Datasource/Database
Sqlite::buildColumn
bigint primary key が正しく生成されるようになった
Cache/Engine
FileEngine::key
Windows 環境で、ファイル名として使えない文字をアンダーラインに変更する処理を追加'<', '>', '?', ':', '|', '*', '"'
が処理されるようになった
エクセル・アクセスで自然順ソート
概要
excel や Access では自然順ソート(natsort) が提供されていません。(PHP では提供されています!) 自然順ソートを真面目に実装するのは意外に大変です。
大変なポイントとして、以下の3点があります。
- 数字とそれ以外に分割を行い、個別に比較しないといけないので、ワークシート関数のみではほぼ不可能
- 01, 001, 0001 のような0の桁埋めされたものとされてないものを区別するかで処理が分岐
- 空白文字の扱い
仕様
今回のコードは、住所の並び替えを念頭においた仕様です。
- エクセル上で並び替える必要上、手軽に並び替えを行いたいので、1セルにまとめるため、数字の桁埋めの上限に制限がある(truncateLen = 5)
- 全角数字は、事前に半角数字に変換
- 全角空白は、事前に半角数字に変換
- 漢数字の地番は考慮しない
- 環境依存文字が含まれると、処理できない(Unicodeで処理しないといけないが、手抜き)
- 0の桁埋めを考慮しない
参考URL
- JavaScriptでオレオレnatsortを実装してみました - latest log
- シンプルな記述のため、処理を理解する手助けになりました。
- pythonでnatsort(自然順ソート) - Python仲間募集中
- python だけど、処理毎の詳しい解説
- Natural Order String Comparison
- 仕様が書かれているページ
- sourcefrog.net/projects/natsort/natcompare.js
- 仕様に沿った JavaScript による実装。
コード
- 仕様に沿った JavaScript による実装。
Function formatNatsort(ByVal text As String) As String Dim i As Long, length As Long, ascii As Long Dim char As String, bufferString As String, padding As String Dim beforeState As Long, currentState As Long, truncateLen As Long length = Len(text) padding = "0000000000000000" beforeState = -1 currentState = 0 bufferString = "" truncateLen = 5 If length = 0 Then formatNatsort = "" Exit Function End If For i = 1 To length char = Mid(text, i, 1) ascii = Asc(char) If ascii = 32 Then currentState = 0 ElseIf ascii >= 48 And ascii <= 57 Then currentState = 1 Else currentState = 2 End If If i = 1 Then beforeState = currentState End If If currentState <> 0 Then If currentState = beforeState Then bufferString = bufferString & char Else If currentState = 1 Then formatNatsort = formatNatsort & bufferString Else formatNatsort = formatNatsort & Right(padding & bufferString, truncateLen) End If bufferString = char End If beforeState = currentState End If Next i If currentState = 1 Then formatNatsort = formatNatsort & Right(padding & bufferString, truncateLen) Else formatNatsort = formatNatsort & bufferString End If End Function
使い方
モジュールを新規に追加して、コードをコピペしてください。
オリジナル | 処理後 |
---|---|
東京都千代田区永田町2丁目3−1 | 東京都千代田区永田町00002丁目00003−00001 |
東京都千代田区永田町1−7−1 | 東京都千代田区永田町00001−00007−00001 |
後は、処理後のフィールドをキーにして並び替えを実行してください。
CakePHP 2.3.9 変更点
公式アナウンス
- CakePHP 2.3.9 released
今回のリリースは
メンテナンスリリース
です。 20のバグフィックス及びパフォーマンスの改善が行われています。
主な変更点
ドキュメント・テストケース・小さな修正は除きます。
CakeResponse
_fileRange
Content-Range ヘッダーが正しい範囲を返すよう修正
Range: bytes=0- Range: bytes=-500
のような HTTP_RANGE の開始値や最終値がない場合、計算結果が正しくなかった。
Bake
Bake Controller で作成されるページネートが Paginator コンポーネントに変更
以前は古い形式 $this->paginate()
だったが、$this->Paginator->paginate()
に新しくなった。
FormHelper
_introspectModel
動的なルールの追加に対応
$object->validate のチェックが削除された。バリデート関連のメソッドはModelクラスから、ModelValidator へ委譲されている。
AuthComponent
redirectUrl
App.baseUrl を指定しているとき、それが含まれてしまうデグレードを修正
CakePHP2.3.7 のデグレードを解消したCakePHP2.3.8 から発生。
I18n
translate
$domain が空文字の場合、例外が発生するように変更
ちなみに初期値の null の場合はデフォルト $domain が使用される
FileEngine
clear
グループを設定している場合、Cache::clear
でファイルが削除されなかったのを修正
clear
使用されていない設定のファイルパスが存在しない場合、エラーが発生するのを解消
clear
上記の修正で、Windows 環境にて、デグレートが発生するのを再修正
この問題はWindows環境でよくある問題(Rubyでも発生する)で、ファイルリソースを開いたまま、リネームや削除ができないというもの。一旦、ファイルリソースを閉じてからならば、リネームや削除が可能になる。
ComponentCollection
setController
が追加された
ControllerTestCase::generate を使用時、setController
により コントローラーモックオブジェクトを挟み込むことで、ComponentCollection::$_Controller に依存するコンポーネントがTrying to get property of non-object
エラーを発するケースを解消するようになった。
CakeRoute
persistParams
用のオプション設定が必須ではなくなった
以前は、CakeRoute::$options['persist'] をキーのチェックや型のチェックをなしに、foreach で回していたが、事前に、キーのチェックや型のチェックを行うようになった。CakeRoute::$options['persist'] はデフォルト値もなく、サブクラスやインスタンスで定義される保証がなかった。
Model
save
fieldList や whitelist の配列の指定の解釈が正しくなかったのを修正。
呼び出す元のモデル(自モデル)の指定の場合、自モデルのエイリアスを省略でき、そうでない場合、モデルのエイリアスをキーとした配列を記述しなければならない。今回の場合、自モデルの指定がなく、他モデルの指定だけがある場合、自モデルの指定として解釈する場合があったのを解消した。
Configure
bootstrap
App::$bootstrapping = false;
が App::init
の後に移動し、パフォーマンスが向上するようになった
App::$bootstrapping
は bootstrap 処理中かどうかを表す boolean。初期値は、false だが、Cake/bootstrap.php が読み込まれると、true になる。その後、今回の変更のある Configure::bootstrap が呼ばれる。
false 時にマッピングされていないファイルを読み込むと、App::$cacheChange が true になる。スクリプト処理が完了した際、App::init で register_shutdown_function により登録された App::shutdown が呼び出され、App::$cacheChange が true と評価されると、Cache::write('file_map', array_filter(self::$_map), '_cake_core_');
でキャッシュの書き込みが行われる。
今回のチケットの問題は、手元の環境では再現できなかったが、App::init 中に読み込まれるファイルが、別のファイルを読み込む場合に、再キャッシュを防ぐという目的で今回の変更が行われた模様。
travis
mysql の時だけ AllTests を実行し、それ以外の場合は、データベースが関係する AllDatabase を実行することでテスト時間を短縮
実行タイミングによるものの1分程度の短縮が見られる。
CookieComponent
_write
複数のキーを書き込む場合、期限が正しく設定されなかったのを修正
AclNode
node
JOIN を LEFT
から INNER
に変更し、パフォーマンスを改善
ShellDispatcher
_bootstrap WWW_ROOT
と TMP
が自由に設定できるようになった。
今までは、決まったパスしか利用できなかった。
URLへのキーワードの埋め込みと管理IDの実装調べ
概要
SEO ではURLに商品名を加えたものが良いとされます。 但し、英語圏ならまだしもマルチバイトな日本語では、
- 日本語のままURLへ含める
→重複の可能性、これをキーにするのは実装上問題が多そう
- URL用に英語名を入力
→重複の可能性と入力の手間とカタカナ英語以外で効果が低そう
と問題が考えられます。
SEO上の効果の程度や実装の手間を考慮すると、 「データベースの一意なIDをそのまま使用する」(オートインクリメントなIDやハッシュ値、UUID)実装が シンプルで変更に強く魅力的に思えてきます。
また、多数のパラメータを持つ商品(服ならばサイズ・色)をどこまでURLへ反映させているかが気になったので、 各社のURL構造を自分なりに調べました。
※URLの構造とその実装に興味があります。
※中の人ではないため、意図を読み違えている可能性があります。
※SEO上の効果を検証したり、また、それ自体について議論するものではありません。
クックパッド
シンプルな構成
http://cookpad.com/recipe/2221390
recipe のディレクトリの下に、シーケンシャルなIDの構成です。 レシピサイトのため、レシピへのオプションは存在しません。 また、他にキーとするならタイトルしかありませんが、レシピは投稿されるもののため、 タイトルの変更を考慮すると、IDしか使用できないと思われます。
ID がデータベースのキーになっている可能性が高く、実装や運用がシンプルに行えそうです。 IDがシーケンシャルに発行されているようなので、クックパッドの規模ですと、SPOFをどう回避しているかが気になります。
アスクル
シンプルな構成
http://www.askul.co.jp/v/4853/
http://www.askul.co.jp/p/5784852/
http://www.askul.co.jp/p/K302379/
v または p の1文字のディレクトリの直下にシーケンシャルなIDの構成です。 色・サイズ違いは別IDになります。
v と p の違いは不明です。v だけ、p だけのカテゴリもあれば、同じカテゴリ内でも混在する場合もあります。 IDは頭にアルファベットの頭文字がつくときがあります。この ID がデータベースのキーになっている可能性が高いです。
実装上の意図が分かりにくいところがありますが、考え方はシンプルです。
lighthouseapp
内部IDとタイトルを同時に表示している例
projects プロジェクトであることを示す 42648 アカウントID tickets チケットであることを示す 3891-cakeemail-cant-set-invalid-rfc-email-address 個別チケット(シーケンシャルなIDとタイトルのスラグの構成) ※正規化はされていないが、シーケンシャルなIDだけである
https://cakephp.lighthouseapp.com/projects/42648/tickets/3891
でも同じページを返すので、内部的には、3891だけを見ている可能性が高いです。
コンテンツの内容をURLに含めるが、管理上はなくても構わないという実装です。
アマゾン
内部IDとタイトルを同時に表示している例
書籍の場合
正規化されたURL
http://www.amazon.com/Quiet-Power-Introverts-World-Talking/dp/0307352153 http://www.amazon.co.jp/Quiet-power-introverts-world-talking/dp/0141029196 http://www.amazon.co.jp/内向型人間の時代-社会を変える静かな人の力-スーザン・ケイン/dp/4062178591
洋書のままではIDは同じで、翻訳の場合は異なります。 書籍の場合、商品IDはISBNになります。
上記の記述では、タイトルの内容を削ることが可能で、最小構成は以下になります。(リダイレクトされません)
http://www.amazon.co.jp/dp/4062178591
但し、サイト内では以下のようなタイトル部分が「gp」に置き換えられたURLが使用されています。(リダイレクトされません)
http://www.amazon.co.jp/gp/dp/4062178591
また、カート内からのリンクでは、「product」が含まれるURLが使用されています。(リダイレクトされません)
http://www.amazon.co.jp/gp/product/4062178591
おそらく、タイトル部分の容量を削減しているのでしょう。
ファッションの場合
サイズ・色毎に商品IDが用意されています。URLへはIDによって商品のオプションが反映されています。 但し、変わっているのは、これらの商品の正規化されるURLがサイズ・色毎の個別の商品IDでなく、全く別の商品IDになることです。
つまり、代表する商品IDがあり、これを直接注文することはできず、それらにぶら下がるサイズ・色が具体的に決まった商品IDで注文するという構成になっています。 おそらく、サイズ・色毎にURLを用意したいが、サイズ・色は生産計画や在庫の都合でなくなる可能性があるため、代表する商品IDを別途用意していると思われます。
カート内からの商品個別のURL(サイズ違いはなく、色違いが2種類のみ)
http://www.amazon.co.jp/dp/B00E97LP7W
http://www.amazon.co.jp/dp/B00E97LOO6
上記から正規化されたURL
http://www.amazon.co.jp/dp/B00E97LNLU
書籍以外の商品IDはB[0-9A-Z]{9}で構成され、1桁目から採番されているようです。 36の9乗≒10の14乗で約100兆のアイテムが登録可能になっています。
流石アマゾン、必要な要件をすべて取り揃えています。
楽天ブックス
内部IDとタイトルを同時に表示している例 正規化されたURL
http://books.rakuten.co.jp/rb/内向型人間の時代-社会を変える静かな人の力-スーザン・ケイン-9784062178594/item/12279831/
アマゾンより複雑な構成で、 rb は商品単位のディレクトリであることを示していますが、item の扱いが不明です。 また、タイトル後の 9784062178594 が何を示しているのかも不明です。 タイトル部分は削ることができ、アマゾン同様に以下まで削ることが可能です。
http://books.rakuten.co.jp/rb/item/12279831/
但し、削られたURLは正規化されたURLへリダイレクトされます。
サイト内では、
http://books.rakuten.co.jp/rb/12279831/
が使用されていますが、このURLも正規化されたURLへリダイレクトされます。
商品IDは、整数値がインクリメントされるもののようです。ちなみに、現在の最小idは以下の商品でした。
http://books.rakuten.co.jp/rb/ア-スアンカ-による圧入工法の設計と施工-角田安一-9784274099434/item/12/
zappos
タイトルだけを表示している例
正規化されたURL
http://www.zappos.com/oakley-full-auto-tour
http://www.zappos.com/oakley-full-auto-tour-black
ディレクトリなしで、商品名をスラグ(+属性[色])にした構成です。 商品名が色なしが正規化されたURLで、 デフォルトの色のURLや色違いのURLは色なしに正規化されます。 但し、サイズはURLに含まれず、HTMLから判断するに、個別の商品idを持っているようです。
後発ほど、商品名の重複を気にしなければならないので、運用はどうやっているのかが気になります。 また、 URLが任意に指定できる以上、変更があった場合、URLの永続化をどのようにしているかも気になりましたが、 外部からうかがい知ることはできませんでした。
Qiita
ハッシュで構成されているURL
http://qiita.com/dz_/items/55ae18f7fe3a873bace1
- dz_ はユーザー名
- items は固定
- 55ae18f7fe3a873bace1 TIPSを特定するID
DELL
商品の最小URL v323010dc2ojp でカスタマイズ前の商品構成を識別している模様
http://configure.apj.dell.com/dellstore/config.aspx?oc=v323010dc2ojp
カートから商品を編集する際に発行されるURL
UUIDの e66da8b6-2362-451c-89ff-a102f6eacea2 がカスタマイズされた内容を保持しているキーになるようです。 カートから削除したり、別のセッションでは利用できないことを考慮すると、セッションと一緒に管理されており、 カスタマイズ後のURLは提供されていないようです。
ゾゾタウン
オートインクリメントな商品IDを持つシンプルなURLです。 商品IDは、サイズ・色を統括する「商品」に振られ、サイズ・色毎の個別のURLは生成されないようです。
グラフィック
商品の選択が進んだ後のURL
http://www.graphic.jp/price/12_2_1/250_2
「12_2_1」について
- 12 はA4チラシのID
- 2 は用紙コート63kgのID
- 1 は5日納期のID
「250_2」について
- 250 は部数の数
- 2 は両面モノクロのID
と、ディレクトリ構造にはあまり意味がなく、実装側の都合のURLのようです。 オプションについては、URLに反映されませんでした。
納期・カラー数・部数を選ぶ画面
http://www.graphic.jp/price/12_2_3/
上記の価格一覧表では、行列の項目と生成されるURLに規則性があることから、すべて自動生成されているようです。 また、こんなにURLを生成していると、どうインデックスされているのかと思ったら、 「A4チラシ」と最初に仕様を選んだページまでがインデックスされるようになっており、 その後の用紙の種類以降は、「noindex,follow」とリンクは辿るけど、インデックスはしないという指定がされていました。
まとめ
各社とも考えられたURLの構造をしており、勉強になる部分が多かったです。
特に、 アマゾン、lighthouseapp、楽天のような、管理IDとコンテンツ内容をURLに含めつつ、 その実際は、管理IDだけでアクセス可能な仕組みは、SEO上のURLと実装・運用の妥協点となっているようでした。
CakePHP 2.3.8 変更点
- 公式アナウンス
- セキュリティリリース
- AssetDispatcher を有効にしている(デフォルトでは有効)アプリケーションが対象
- CakePHP 2.2.9 も同時にリリースされている
- このバグに対する詳細は、後日、公式から発表されるそうです。
- このバグは2.0.5から存在するが、2.0系、2.1系のリリースはない(1.x系は未調査)
- AssetDispatcher を有効にしている(デフォルトでは有効)アプリケーションが対象
主な変更点
ドキュメント・テストケースの修正は除きます。
Console
ExtractTask
I18nShell のプラグインのバリデーションメッセージを正しく表示できるようになったExtractTask
App::objects の第3引数を false に設定- 第3引数はキャッシュ設定、Console 時は、常にキャッシュしない方針だが、ここだけキャッシュをしていたので他と整合性が取れるようになった。
ServerShell
カスタム documentRoot を設定したとき、その後のパスが正しくなかったのを修正ServerShell
静的ファイルのクエリーパラメータ付のリクエストが処理できなかったのを修正- クエリーパラメータ付のパス名を file_exists でファイルが存在するかどうか調べていたのを修正
Utility
Inflector
複数化できる単語を追加
CakeResponse
send
206 ステータスコードの Content-Range を正しく処理できるようになった。- rfc2616 に準拠した Content-Range を返すようになった。
- 416 Requested Range Not Satisfiable (リクエストしたレンジは範囲外にある。実ファイルのサイズを超えるデータを要求した。)を追加
Component
AuthComponent
2.3.7 での redirectUrl メソッドのリグレッションを修正- 2.3.7 の修正で、サブディレクトリを含めた redirectUrl が正しく動作しなくなっていた。
Blink HTMLTokenizer を PHP に移植して、HTML Minifyをできるようにした「html-minifier」
概要
Webkit からフォークされたレンダリングエンジン Blink で使用されている HTMLTokenizer をPHPに移植して、 HTML の Minify(圧縮) を行う「html-minifier」を作りました。
※アルファ版にも満たないため、名称の変更、APIの変更、歴史改変のための push -f がありえます。
できること・できないこと
- 条件付きコメントを残す
- textarea や pre 要素内のテキストのHTMLの意味を変えない
- 開始タグ内のホワイトスペースの最適化
- タグ間の文字列のホワイトスペースの最適化
但し、未実装の部分があります。
- DOCTYPE memo SYSTEM の Tokenizer が未実装(PUBLICはOK)。ここを通る処理は未実装のメソッドがあります。
- invalid なHTMLを処理する際のエラー処理に未実装が多い。
- 実体参照(©等)が最低限
- 最適化が甘い(type="checkbox" → type=checkbox や disabled="disabled" → disabled はまだ未実装)
動機
css の最適化なら LESS や Sass があり、JavaScript ならば、Closure Compiler, YUICompressor, UglifyJS 等のライブラリが存在していますが、 それらを活用する HTML には代表的なものをあまり聞きません。
必要な要件は以下の通りです。
MUST
HTMLの意味を変えない- 条件付きコメントは除外されると、挙動が変わってしまうので、条件付きコメント(ダウンレベルから見えない/見える)を除去しない
- textarea や pre タグ内の要素の空白は意味があるので、最適化を行わない
MUST
アプリケーションレベルで最適化の実行が可能better
最適化のレベルが選択できる- ドキュメントタイプによる最適化の違い(<br>, <br/>, <br />)
- 属性の最適化( type="checkbox" → type=checkbox 一定の条件で「"」は省略できます。また、disabled="disabled" → disabled という最適化もあります。 )
- コメントを除去を On/Off 可能(ライブラリによっては、コメントタグに情報を持たせるものが存在するので、問答無用に削除してもらっては困ります。)
今回はブラウザの処理を理解したいのと、PHPでデバック情報も取得したいので、Blink(現時点では、フォーク前のWebkitのWebcoreとほとんど変わりありません)の処理を移植することにしました。
最適化の分類
HTMLに独自タグを埋め込む方式
Twig (Symfony 等で採用されているテンプレート言語です。)では、spaceless
ブロックによって、そのブロック内のタグ間のホワイトスペースを除外できます。
処理方法は正規表現により、「'/>\s+</', '><'」という形式になっており、タグ間のホワイトスペースを一律削除します。
欠点は、テンプレートの導入とコンテンツの移植が必要なことと、属性の最適化・複雑なホワイトスペース・条件付コメントに対応していないことです。
別のマークアップ言語からHTMLへ変換する方式
最高のパフォーマンスを発揮できる形式だと思われますが、有名どころが haml や slim等で Ruby なのが残念。
欠点は、テンプレートの導入とコンテンツの移植が必要なことです。
HTMLの文字列に対して最適化を実行する方式
今回採用した方式、汎用性がある代わり、ブラウザが解釈するレベルの実装でないと、適切な最適化ができません。
PageSpeed Module
最適化のタイミングは、PHP等の処理が行われた後のHTMLに対して処理されます。
ブラウザ → Webサーバー → PHP等 → Webサーバー(ここ) → ブラウザ
実装は、C言語で、Tokenization の簡略化された処理でトークンを作成後、各種フィルタによって圧縮が行われています。 処理の精度も高く、条件付きコメントを残し、インラインの css や JavaScript まで処理してくれます。
欠点は、Webサーバーにインストールを行うので、アプリケーションレベルで最適化を行うとすると、HTTPリクエストが必要になってしまう点です。
minify
PHP で動作するHTML最適化ライブラリです。 方式は正規表現による置換で最適化を行います。 HTMLの構造は正規表現で表現しきれないので、過剰な最適化が発生してしまいます。
欠点は、最適化が甘いこと、過剰な最適化を行う場合がある、更新が止まっていることです。
kangax/html-minifier
JavaScript で動作するHTML最適化ライブラリです。 方式は、正規表現によるトークンの検出後に最適化を実施する方式です。
開発が止まっておらず、ほしい要件も満たしていました。 Node.js からも利用できるので、PHP内で最適化された結果を取得することも可能ですし、そのままPHPへ移植することも可能です。
使い方
composer からインストールできます。
composer.json
{ "require": { "zaininnari/html-minifier": "0.1.*" } }
<?php require 'vendor/autoload.php'; $html = 'HTML文字列'; $out = zz\Html\HTMLMinify::minify($html);
example.com のTOPページの最適化の様子です。左が最適化前、右が最適化後です。
CakePHP 2.3.7 変更点
- 公式アナウンス
- バグフィックスリリース
- CacheHelper 使用時、content-type ヘッダーを含めるようになったのが個人的には一番よい修正。
- CakePHP 2.4.0-betaのリリース
主な変更点
ドキュメント・テストケースの修正は除きます。
View
CacheHelper
使用時、content-type ヘッダーを含めるようになった。- 以前は Routing/Filter/CacheDispatcher, View/Helper/CacheHelper に加えて、 View/View にも手を加えなければならなかったのが解消された。
- Cached Render Time の出力が xml 以外から html のみに変更された。
SmtpTransport
Return-Path ヘッダーを含めないよう変更CakeEmail::_render
_createBoundary
の呼び出しをsend
から_render
へ移動View::render
のイベント後に、_createBoundary
されるようになり、自由度が増した。- boundary は添付ファイルやtextとhtmlを指定した際の境界線。
Model
- strtotime('now') の生成をループの外で生成するようになった。
- bootstrap の TIME_START を使った方がよい気もするが・・・。参考:コード内で「現時刻」を気軽に取得してはいけない - nekoya press
- ただし、TIME_START は 定数 なので、テストがやりにくくなる
basics
- SCRIPT_FILENAME と SERVER_IIS によるドキュメント化もテストもされないコードを削除
Helper
TextHelper::autoLinkUrls
閉じタグを含めないように正規表現を修正
<?php $text = '<li>lorem: http://example.org?some</li>'; $result = $this->Text->autoLink($text, array('escape' => false)); // -> <li>lorem: <a href="http://example.org?some">http://example.org?some</a></li>
FormHelper::dateTime
現在より未来の年と指定した時、maxYear
になるよう修正
Component
AuthComponent::redirect
URL の最初のセグメントがbase
プロパティと同一の場合誤ったURLを生成してしまうのを修正- リリース後に、別の問題が見つかっている( #3916 fail to redirct '/' in 2.3.7 - CakePHP - cakephp )
PaginatorComponent::validateSort
Model::order を自動的に継承するようになった
App
load
..
を含むクラス名を指定したとき、処理が止まり、false を返すようになった。- explode との組み合わせにより、ディレクトリトラバーサルの危険性を排除したってことかな。