Piece_ORMのデフォルトのinsert文についての質問です。

10 views
Skip to first unread message

katarou

unread,
Nov 28, 2007, 1:08:27 AM11/28/07
to Piece Framework Users (ja)
田川です。

Piece_ORMのデフォルトで作成されるinsert文の仕様について教えてください。
下記内容のテーブルにて
CREATE TABLE mstuser (
idmstuser INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
idmstsection INTEGER UNSIGNED NOT NULL,
idmstdivision INTEGER UNSIGNED NOT NULL,
firstname VARCHAR(100) NOT NULL,
lastname VARCHAR(100) NOT NULL,
passwd VARCHAR(12) NULL,
email VARCHAR(255) NOT NULL,
* frepresentor INTEGER UNSIGNED NOT NULL,
* fworker INTEGER UNSIGNED NOT NULL,
* fvaildator INTEGER UNSIGNED NOT NULL,
* fapprover INTEGER UNSIGNED NOT NULL,
fadministartor INTEGER UNSIGNED NOT NULL,
modified DATETIME NULL,
* fdeleted INTEGER UNSIGNED NOT NULL,
PRIMARY KEY(idmstuser)
);
$mapper->insert()を使用すると、*印の付いたフィールドの値が反映されていませんでした。
少し調べたのですが、*印の付いたフィールドではデフォルト値が0で認識されており、
また文字列長も1と認識されていて、デフォルトinsert文作成時のフィールドに含まれず、
結果データにはデフォルト値の0(?)が反映されているようでした。
このような場合はinsert文を再定義したほうがよいでしょうか?

出来上がったデフォルトのinsert文は下記のようになるようです。
INSERT INTO mstuser (idmstsection, idmstdivision, firstname, lastname,
firstkana, lastkana, userid, passwd, email, modified) VALUES
($idmstsection, $idmstdivision, $firstname, $lastname, $firstkana,
$lastkana, $userid, $passwd, $email, $modified)

確認したコードは、Piece/ORM/Mapper/Generatior.phpの708行目あたりです。

以上、長文で申し訳ありませんが、ご教授のほどよろしくお願いいたします。

katarou

unread,
Nov 28, 2007, 3:41:40 AM11/28/07
to Piece Framework Users (ja)
田川です。


insertについてですが、デフォルト値を削除したところ、insertを再定義せず正常に動作するようになりました。
とりあえずお知らせしておきます。

KUBO Atsuhiro

unread,
Nov 28, 2007, 11:49:59 AM11/28/07
to piece-framew...@googlegroups.com
久保です。

デフォルトの INSERT クエリは、

* デフォルト値を持たない
* オートインクリメントではない

の 2 つの条件を満たすフィールドで構成されるようになっています。
コードは下記のとおりです。(Subversion trunk より)

Piece/ORM/Mapper/Generator.php:

function _generateDefaultInsertQuery()
{
$fields = array();
foreach ($this->_metadata->getFieldNames() as $fieldName) {
if (!$this->_metadata->hasDefault($fieldName) && !$this->_metadata->isAutoIncrement($fieldName)) {
$fields[] = $fieldName;
}
}

return 'INSERT INTO ' . $this->_metadata->getTableName() . ' (' . implode(", ", $fields) . ') VALUES (' . implode(', ', array_map(create_function('$f', "return '\$' . Piece_ORM_Inflector::camelize(\$f, true);"), $fields)) . ')';
}

念のため、こちらでも下記テーブル定義によって確認しましたが再現すること
ができませんでした。artist_id が該当するフィールドになります。

テーブル定義の SQL:

CREATE TABLE album (
id int(11) NOT NULL AUTO_INCREMENT,
artist_id INTEGER UNSIGNED NOT NULL,
name varchar(255) NOT NULL,
version int(11) NOT NULL DEFAULT '0',
rdate datetime NOT NULL,
mdate timestamp,
PRIMARY KEY(id)
);

mysql コマンドから確認したテーブル定義:

mysql> desc album;
+-----------+------------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| artist_id | int(10) unsigned | NO | | | |
| name | varchar(255) | NO | | | |
| version | int(11) | NO | | 0 | |
| rdate | datetime | NO | | | |
| mdate | timestamp | NO | | CURRENT_TIMESTAMP | |
+-----------+------------------+------+-----+-------------------+----------------+
6 rows in set (0.01 sec)

生成された SQL:

INSERT INTO album (artist_id, name, rdate) VALUES ($artistId, $name, CURRENT_TIMESTAMP)

原因として考えられるのは、何らかの理由によりテーブル定義の SQL と実際
のスキーマが同期していないことです。
可能であれば、示して頂いたテーブル定義の SQL を使って、テーブル名を変
更した上でテーブルを作成し、生成される SQL を確認頂けないでしょうか。

以上、よろしくお願いいたします。

--
KUBO Atsuhiro e-mail: ku...@iteman.jp

katarou

unread,
Nov 28, 2007, 12:40:37 PM11/28/07
to Piece Framework Users (ja)
田川です。

フォローありがとうございました。
すみません、最初に記載したSQLは*印をつけたフィールドにdefault 0 が入っていました。確認中のSQLで間違って貼り付けてしまいまし
た。
申し訳ありません。

ご返答ありがとうございます。

行いたかったのはチェックボックスの値をテーブルに保存する場合、フラグとして0か1を持たせたくdefault 0をつけていました。
確認すると全部デフォルト値となっていたので、相談した次第です。

defaultが指定されているフィールドは値を渡されてもdefaultが優先されるということですね。
処理を考えてみたいと思います。

ありがとうございました。
> +-----------+------------------+------+-----+-------------------+-----------------+
> | Field | Type | Null | Key | Default | Extra |
> +-----------+------------------+------+-----+-------------------+-----------------+
> | id | int(11) | NO | PRI | NULL | auto_increment |
> | artist_id | int(10) unsigned | NO | | | |
> | name | varchar(255) | NO | | | |
> | version | int(11) | NO | | 0 | |
> | rdate | datetime | NO | | | |
> | mdate | timestamp | NO | | CURRENT_TIMESTAMP | |
> +-----------+------------------+------+-----+-------------------+-----------------+
> 6 rows in set (0.01 sec)
>
> 生成された SQL:
>
> INSERT INTO album (artist_id, name, rdate) VALUES ($artistId, $name, CURRENT_TIMESTAMP)
>
> 原因として考えられるのは、何らかの理由によりテーブル定義の SQL と実際
> のスキーマが同期していないことです。
> 可能であれば、示して頂いたテーブル定義の SQL を使って、テーブル名を変
> 更した上でテーブルを作成し、生成される SQL を確認頂けないでしょうか。
>
> 以上、よろしくお願いいたします。
>
> --
> KUBO Atsuhiro e-mail: k...@iteman.jp

KUBO Atsuhiro

unread,
Nov 28, 2007, 12:59:34 PM11/28/07
to piece-framew...@googlegroups.com
久保です。

katarou さんは書きました:


> 行いたかったのはチェックボックスの値をテーブルに保存する場合、フラグとして0か1を持たせたくdefault 0をつけていました。
> 確認すると全部デフォルト値となっていたので、相談した次第です。
>
> defaultが指定されているフィールドは値を渡されてもdefaultが優先されるということですね。
> 処理を考えてみたいと思います。

なるほど、理解いたしました。
INSERT クエリがひとつでも問題なければ、insert のクエリを再定義するとい
いでしょう。その場合は、必ず対象フィールドの値が設定されるように、オブ
ジェクトの対象プロパティに必ず値を設定するか、SQL側で対象プロパティの
値によって条件分岐することで対応してください。
ちなみに、プリペアドステートメントのプレースホルダと異なり、Piece_ORM
のクエリ内の変数は、左辺値としても使用可能です。

INSERT クエリが複数必要と思われる場合は、insert には手を付けずに、
insertXXX のように insert で始まるメソッドを定義するといいでしょう。

なお、メソッドの再定義は下記のいずれも可能となっています。

* findAllXXX
* findOneXXX
* findXXX
* insertXXX
* updateXXX
* deleteXXX

KUBO Atsuhiro

unread,
Nov 28, 2007, 1:03:23 PM11/28/07
to piece-framew...@googlegroups.com
久保です。

KUBO Atsuhiro さんは書きました:
> なお、メソッドの再定義は下記のいずれも可能となっています。

すみません、
「なお、メソッドの定義は下記のいずれも可能となっています。」が正解です。

メソッドは、それが再定義かどうかにかかわらず定義可能です。

katarou

unread,
Nov 29, 2007, 3:03:26 AM11/29/07
to Piece Framework Users (ja)
田川です。

フォローたびたびすみません。ありがとうございます。

>ちなみに、プリペアドステートメントのプレースホルダと異なり、Piece_ORM
>のクエリ内の変数は、左辺値としても使用可能です。
というのは

where $foo=0

という風に記載できるということですね。了解です。
Finder記載の幅が広がりました。ありがとうございます。

希望なのですが
通常のSQLのdefaultはsql内に該当フィールドがあればその値を、そうでなければdefaultを使うという仕様が一般的かと思います。
マッパーにたとえば、insertByDynamincFieldsというメソッドがあり、引数で
$value = $mapper->createObject();
$value->foo = 1;
$value->bar = 2;
$mapper->insertByDynamincFields($value);
とやれば、与えられたフィールドでinsertをおこなうメソッドがあれば、有用ではないかと思うのですがいかがでしょうか?

あと、Finderについても、複数条件検索の場合はFinderを定義しなければならないと思いますが、
同様にfindBy(All)DynamincFieldsというメソッドがあり、
$value->foo = 1;
$value->bar = 2;
$mapper->findByDynamincFields($value);
とやれば、複数条件で検索ができるとか、、
Finderを定義しなくてよい分コーディングが楽になるような気がしてます。デフォルトなのでAND条件、比較は'='で。
それ以外のケース(Between, OR結合 , '<' , '>'など)が発生した場合は別定義でやればよいかと。

自分で作れればいいのですが、技量がなくてわがまま言ってすみません。(汗
> KUBO Atsuhiro e-mail: k...@iteman.jp

KUBO Atsuhiro

unread,
Dec 12, 2007, 8:29:24 AM12/12/07
to piece-framew...@googlegroups.com
久保です。

要望を頂きましてありがとうございます。

katarou さんは書きました:


> 希望なのですが
> 通常のSQLのdefaultはsql内に該当フィールドがあればその値を、そうでなければdefaultを使うという仕様が一般的かと思います。
> マッパーにたとえば、insertByDynamincFieldsというメソッドがあり、引数で
> $value = $mapper->createObject();
> $value->foo = 1;
> $value->bar = 2;
> $mapper->insertByDynamincFields($value);
> とやれば、与えられたフィールドでinsertをおこなうメソッドがあれば、有用ではないかと思うのですがいかがでしょうか?

こちらについては、SQL で対象の変数を評価することによって実現できるこ
とから、機能としての採用は見送りたいと思います。

> あと、Finderについても、複数条件検索の場合はFinderを定義しなければならないと思いますが、
> 同様にfindBy(All)DynamincFieldsというメソッドがあり、
> $value->foo = 1;
> $value->bar = 2;
> $mapper->findByDynamincFields($value);
> とやれば、複数条件で検索ができるとか、、
> Finderを定義しなくてよい分コーディングが楽になるような気がしてます。デフォルトなのでAND条件、比較は'='で。
> それ以外のケース(Between, OR結合 , '<' , '>'など)が発生した場合は別定義でやればよいかと。

こちらについては、2 つの方法があります。ひとつは、SQL を使うことです。
(推奨) 例えば下記のようなファインダ定義によって、簡単に複数条件検索を
実現することができます。

- name: findAllByCriteria
query: |
SELECT
*
FROM
person
WHERE
(($firstName IS NULL OR $firstName = '') OR first_name LIKE $firstName)
AND (($lastName IS NULL OR $lastName = '') OR last_name LIKE $lastName)
AND (($loginName IS NULL OR $loginName = '') OR login_name LIKE $loginName)

もうひとつは、何らかの手段によって自分で SQL を構築することです。
下記のメソッドを使って任意の SQL を実行し結果を取得することができます。

* findAllWithQuery()
* findWithQuery()
* findOneWithQuery()

SQL の構築には、PEAR の (M) DB_QueryTool や
http://d.hatena.ne.jp/fbis/20070613/1181737366 などを使うといいでしょう。

こちらについても機能としての採用は見送りたいと思います。

以上、よろしくお願いいたします。

katarou

unread,
Dec 14, 2007, 10:46:48 AM12/14/07
to Piece Framework Users (ja)
田川です。

ご検討いただき有難うございます。

ご教授いただき有難うございます。少し試してみます。


別件なのですが、
Authenticationを利用して認証を行っているのですが、redirectされない場合があって、苦慮しています。

認証ロジック
:
:

$authentication = &new Piece_Unity_Service_Authentication();
$authentication->login();
$authentication->redirectToCallbackURL();
return 'goDisplayMenu';
といった流れで現在認証処理を組んでいるのですが、
何かのタイミングでredirectToCallbackURLがスルーし、そのまま次のステートに移ってしまうという現象が発生しています。
コードを追ったのですが、Piece_Unity_Service_Authentication内で保持しているcallbackURLがnullに
なっており、コールバックが行われていないようでした。

一度認証していれば、redirect先以外はそのまま認証処理は通過してアクセスできます。ただ、ブラウザを閉じずにredirect先にアクセスし
た場合は再度認証処理が行われ結果としてredirect先にはアクセスできなくなってしまうというものです。
認証が行われていないページにアクセスした後、認証ページへいくとredirectされるようです。

再現性があるかといえばそうではなく、redirectされたり、されなかったりしている状況です。
詳しく状況をお知らせしようと調べていたのですが、再現条件や、原因などがわからずとりあえずお知らせしている次第です。

ちなみにリソースの保護は
- name: resourcesMatch
type: configuration
value:
- "/admin/.*"
で行っています。

また、詳しい状況がわかり次第ご連絡いたします。
もし、お気づきの点などありましたら、ご教授ください。
> KUBO Atsuhiro e-mail: k...@iteman.jp
Reply all
Reply to author
Forward
0 new messages