symfony(MySQL)で前後の記事(次のレコード)を取得する

ブログとかでよくあるような「前の記事」「次の記事」リンクを表示しようと思ってちょっと悩んだ。

記事リストのページで次のリストを取るような場合は普通にページング処理をすればいいだけなので簡単だが、MySQLで「前のレコード」「次のレコード」を取るようなクエリがないので、記事単位だと以外と面倒なことに気づいた。

前提として、そのサイトは記事の新しい順(降順)で表示している。


没案1

ページャと同じ様に記事リストを取得し、ループを回しながら現在の記事を探して前後の記事を取得する。

負荷がかかりそうな上に処理が面倒なので却下


没案2

現在の記事付近の塊を適当に取ってきて、適当に前後の記事っぽいものを取る。

適当すぎる上に負荷が(ry


採用案

前の記事(getPreviousEntry)の場合…現在の記事の日時より後の記事を抜き出して、日時の昇順(早い日付順)にするとだいたい前の記事が取れる

次の記事(getPreviousEntry)の場合…現在の記事の日時より前の記事を抜き出して、日時の降順(遅い日付順)にするとだいたい次の記事が取れる


この方法の問題点同じ公開日時の記事があると飛ばされることだが、
運用的に秒単位で公開日時の同じ記事というのはほぼほぼありえないので(゚ε゚)キニシナイ!!

symfony1.4 のpropelでmodelを書いたが、他の環境でも考え方は一緒かな。

public static function getPreviousEntry($entryId)
{
  $entry = EntryPeer::retrieveByPk($entryId);
  
  $c = new Criteria();
  $c->add(self::DELETE, 0);
  $c->add(self::PUBLISH_AT, $entry->getPublishAt(), '>');
  $c->addAscendingOrderByColumn(EntryPeer::PUBLISH_AT);
  $c->setLimit(1);
  
  return self::doSelectOne($c);
}
public static function getNextEntry($entryId)
{
  $entry = EntryPeer::retrieveByPk($entryId);
  
  $c = new Criteria();
  $c->add(self::DELETE, 0);
  $c->add(self::PUBLISH_AT, $entry->getPublishAt(), '<');
  $c->addDescendingOrderByColumn(EntryPeer::PUBLISH_AT);
  $c->setLimit(1);
  
  return self::doSelectOne($c);
}


結構いい方法な気がする

セレクトボックス選択型リンク

セレクトボックスがあってそっから選んでクリックすると別のページのとばされるタイプのリンク

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>セレクトボックスで選択してURL遷移するテスト</title>
</head>
<body>
  <h2>リダイレクト(戻るボタンが効かない)</h2>
  <form action="" method="GET" name="select">
    <select onchange="location.replace(this.options[selectedIndex].value)" >
      <option>-選択してください-</option>
      <option value="http://e0166.blog89.fc2.com">ホームページを作る人のネタ帳</option>
      <option value="http://www.paji.me/">パパパパ</option>
      <option value="http://www.phpbook.jp/">PHPBook</option>
    </select>
  </form>

  <h2>URL移動(戻るボタンが効かない)</h2>
  <form action="" method="GET" name="select">
    <select onchange="location.href = this.options[selectedIndex].value" >
      <option>-選択してください-</option>
      <option value="http://e0166.blog89.fc2.com">ホームページを作る人のネタ帳</option>
      <option value="http://www.paji.me/">パパパパ</option>
      <option value="http://www.phpbook.jp/">PHPBook</option>
    </select>
  </form>
</body>
</html>


いじょう

MySQLのクエリキャッシュを削除する

MySQLのクエリチューニングをしている時主に実行時間とEXPLAINの値を見ているが、クエリキャッシュが聞いてると二回目以降はキャッシュにヒットするため実際の実行時間がわからない。
そういう時は以下のコマンドでクエリキャッシュを全削除できる。

RESET QUERY CACHE;

そこそこアクセスのある本番サーバなんかでやると悲惨なので注意。

SELECT文を発行する際にSELECTの後につけて

SELECT SQL_NO_CACHE

とするのも有り

print_rとvar_dumpの違い

配列の話し

$array = array("田村ゆかり"=>"Little Wish", "水城奈々"=>"SECRET AMBITION", "堀江由衣"=>"YAHHO!!", 2=>"あいうえお", 120);


var_dump($array);

print_r($array);


出力結果(ソース)

array(5) {
  ["田村ゆかり"]=>
  string(11) "Little Wish"
  ["水城奈々"]=>
  string(15) "SECRET AMBITION"
  ["堀江由衣"]=>
  string(7) "YAHHO!!"
  [2]=>
  string(10) "あいうえお"
  [3]=>
  int(120)
}
Array
(
    [田村ゆかり] => Little Wish
    [水城奈々] => SECRET AMBITION
    [堀江由衣] => YAHHO!!
    [2] => あいうえお
    [3] => 120
)

basic認証時にパスワードを取得する方法がPHPにあるらしい

PHP技術者認定・上級模擬問題
をやっていて知ったのだが、$_SERVER['PHP_AUTH_PW']なるグローバル変数で取得できるらしい。


やってみた


index.php

<?php
echo "認証に成功しました<br>";
echo "ID:".$_SERVER['PHP_AUTH_USER']."<br>";
echo "パス:".$_SERVER['PHP_AUTH_PW'];
?>

.htpasswd

kunikiya:GZnkccJy7Ynbo

.htaccess

AuthUserFile .htpasswd
AuthName "Please enter your ID and password"
AuthType Basic
require valid-user


表示結果

認証に成功しました
ID:kunikiya
パス:pass


昔はセキュリティのためユーザー名は取得できるけど、パスワードは取得できなかったはず・・


変わったのか?勘違いだったのか?

symfony propel:build-model がうまくいかない

symfony1.2でpropel:build-modelをしたらエラーが出た

PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 41 bytes) in /usr/share/pear/symfony/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/om/php5/PHP5ObjectBuilder.php on line 133
Buildfile: /usr/share/pear/symfony/plugins/sfPropelPlugin/lib/vendor/propel-generator/build.xml
[resolvepath] Resolved /home/porvie/symfony/config to /home/porvie/symfony/config

エラー内容通りに解釈して、メモリサイズが足りてないのかと思い、
PHPのmemory_limitを大きくしてみたが、6Gとかにしてもエラーは変わらず

そんだけあって足りないとか何事?と思って調べまくってたら、どうやらpropelのバグだった様子

2011-11-20 symfony propel:build-○○ task でハマった

defaultValue: CURRENT_TIMESTAMP 

があるとうまくいかないっぽい…


今回はスキーマからDBを構築することはなくモデルをビルドしたいだけなので、取り合えず消し去る


symfony propel:build-modelしておわり

AIRアプリに自動アップデート機能を実装する

デスクトップアプリの自動アップデート機能を普通に実装するとめちゃめちゃ工数がかかるが、
AIRアプリの場合はAirAutoUpdaterという一行で実装できる便利なライブラリがある。


が、しかし、Flex4.5だと多少変わってたのでメモ


公式サイト

AirAutoUpdaterとは


サンプルにある通り一行追記してみる

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
					   xmlns:s="library://ns.adobe.com/flex/spark" 
					   xmlns:mx="library://ns.adobe.com/flex/mx"
					   windowComplete="init();">
	<jx:AirAutoUpdater url="http://jirox.net/as3/BlurHighlight/version.xml"/>
	<fx:Declarations>
		<!-- 非ビジュアルエレメント (サービス、値オブジェクトなど) をここに配置 -->
	</fx:Declarations>
	<fx:Script>
		<![CDATA[
			
		]]>
	</fx:Script>
</s:WindowedApplication>



『エレメント "jx:AirAutoUpdater" の接頭辞 "jx" がバインドされていません。』


ふむ

AIRソフトウェアを自動でネットワークアップデート(1行で!)

だそうなので

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
					   xmlns:s="library://ns.adobe.com/flex/spark" 
					   xmlns:mx="library://ns.adobe.com/flex/mx"
					   xmlns:jirox="net.jirox.*"
					   windowComplete="init();">
	<jirox:AirAutoUpdater url="http://jirox.net/as3/BlurHighlight/version.xml"/>
	<fx:Declarations>
		<!-- 非ビジュアルエレメント (サービス、値オブジェクトなど) をここに配置 -->
	</fx:Declarations>
	<fx:Script>
		<![CDATA[
			
		]]>
	</fx:Script>
</s:WindowedApplication>


『"AirAutoUpdater" 宣言は、デフォルトプロパティの型 "Array" にもエレメントの型 "mx.core.IVisualElement" にも代入できないので、 タグの中に含まれている必要があります。』


ふむ


ってことで

<jirox:AirAutoUpdater url="http://jirox.net/as3/BlurHighlight/version.xml"/>

<fx:Declarations>

</fx:Declarations>

の中に入れてやる

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
					   xmlns:s="library://ns.adobe.com/flex/spark" 
					   xmlns:mx="library://ns.adobe.com/flex/mx"
					   xmlns:jirox="net.jirox.*"
					   windowComplete="init();">
	<fx:Declarations>
		<!-- 非ビジュアルエレメント (サービス、値オブジェクトなど) をここに配置 -->
		<jirox:AirAutoUpdater url="http://jirox.net/as3/BlurHighlight/version.xml"/>
	</fx:Declarations>
	<fx:Script>
		<![CDATA[
			
		]]>
	</fx:Script>
</s:WindowedApplication>

でOK