ブログ・エス技研

当ブログは引越しをしました。10秒後に自動で転送しますが、転送されない場合は、http://blog.s-giken.net/ をご覧ください。

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
[ --年--月--日 --:-- ] カテゴリ:スポンサー広告 | TB(-) | CM(-)

baserCMS ID以外のカラムでアソシエーション(連携)をさせる場合

baserCMSは、CakePHPの上で動いていますので、基本的に CakePHPの仕様に従ってプログラムを作っていけばいいのですが、ID以外のカラムでアソシエーション(テーブルの連携)をさせる処理で、CakePHPと違う処理がありましたので書いておきます。


CakePHPにおいて、テーブルの連携については(http://ssgiken.blog.fc2.com/blog-entry-63.html)に記事を書きましたので参考にしてください。


では、何が違うのか!
  baserCMSは $hasOne しか使えない
ということです。


プラグインでオリジナルのテーブルから情報を取得する処理を作成していたのですが、その際、テーブル連携に ID以外のカラム同士の連携をさせたい場面がありました。
ですが、CakePHPの仕様の通りに連携させようとしていましたが、なかなかうまくいかず、あれこれと試した結果、baserCMSは $hasOne しか使えないということにたどり着きました。

もしかすると、baserCMS全体ではなく、baserCMSのプラグインの仕様なのかもしれませんが、少なくともプラグインとして作った場合は、$hasOneでの連携しか動きませんでした。

具体的な記述の方法は、上記に書いた CakePHPのテーブル連携で書いた処理を参考にしてください。

また、プラグインを作るのに参考にしたサイトは、以下になります。
http://blog.komomo.biz/log/archives/1
http://blog.komomo.biz/log/archives/3

また、下記のページにも記事を書いています。
http://ssgiken.blog.fc2.com/blog-entry-62.html


プラグインからの設置になってしまいますが、上記のサイトを参考にしながら設置をしてみてください。
基本的には、「http://blog.komomo.biz/log/archives/1」のサイトを参考にしながら、CakePHPでテーブル連携した処理と同じ処理を書いたものになります。

CakePHPでも同じように作ってもらえると分かるのですが、CakePHPでは表示される「$belongsTo」で取得する「Detail2」が表示されないのです。
「Detail3」は、$hasOne で処理しますので取得できます。


もともとは、こちらの baserCMSの中でテーブルの連携の実験をやっていましたので、正解にたどり着くまでかなりの試行錯誤をする結果となってしまいましたが、それをそのまま baserCMSを挟まない CakePHPの環境に持って行ったところどちらでも動いたことで、baserCMS特有の問題なのだと判明しました。


※この方法で「$primaryKey = 'sec_code'」を指定すると、個別の詳細ページを表示させる際のキーになるカラムが「sec_code」になりますので注意が必要です。
 詳しくは http://ssgiken.blog.fc2.com/blog-entry-64.html を参照ください。

-----------------テーブル「bc_pg_bcforum_posts」
CREATE TABLE IF NOT EXISTS `bc_pg_bcforum_posts` (
  `id` int(8) NOT NULL AUTO_INCREMENT,
  `sec_code` char(4) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
-----------------

-----------------テーブル「bc_pg_bcforum_details」
CREATE TABLE IF NOT EXISTS `bc_pg_bcforum_details` (
  `id` int(8) NOT NULL AUTO_INCREMENT,
  `post_id` int(8) NOT NULL,
  `sec_code` char(4) DEFAULT NULL,
  `list` varchar(255) DEFAULT NULL,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
-----------------

-----------------/app/plugins/bcforum/models/bcforum_post.php
<?php
class BcforumPost extends AppModel {
  var $name = 'BcforumPost';
  var $plugin = 'Bcforum';
  var $useDbConfig = 'plugin';

  var $primaryKey = 'sec_code';

  var $belongsTo = array(
    "Post2" => array(
      "className" => "PgBcforumDetail",
      "foreignKey" => "sec_code",
      "conditions" => "",
      "fields"     => "",
      "order"      => ""
    ),
  );

  var $hasOne = array(
    "Post3" => array(
      "className" => "PgBcforumDetail",
      "foreignKey" => "sec_code",
      "conditions" => "",
      "fields"     => "",
      "order"      => ""
    ),
  );
}
?>
-----------------

-----------------/app/plugins/bcforum/models/bcforum_detail.php
<?php
class BcforumDetail extends AppModel {
  var $name = 'BcforumDetail';
  var $plugin = 'Bcforum';
  var $useDbConfig = 'plugin';

  var $primaryKey = 'sec_code';

  var $belongsTo = array(
    "Detail2" => array(
      "className" => "PgBcforumPost",
      "foreignKey" => "sec_code",
      "conditions" => "",
      "fields"     => "",
      "order"      => ""
    ),
  );

  var $hasOne = array(
    "Detail3" => array(
      "className" => "PgBcforumPost",
      "foreignKey" => "sec_code",
      "conditions" => "",
      "fields"     => "",
      "order"      => ""
    ),
  );
}
?>
-----------------

-----------------/app/plugins/bcforum/controllers/bcforum_details_controller.php
<?php
// 継承するコントローラのpluginsをインポートする
app::import('Controller', 'Plugins');

// baserCMS にパッケージされている PluginsController を継承させます
class BcforumDetailsController extends PluginsController {
  var $name = "BcforumDetails";
  var $uses = array('Plugin', 'Bcforum.BcforumDetail');
  var $components = array('BcAuth','Cookie','BcAuthConfigure');

  function index() {
    $this->pageTitle = 'トピックス一覧・New';
    $datas = $this->BcforumDetail->find('all');
    $this->set('datas', $datas);
  }
}
?>
-----------------

-----------------/app/plugins/bcforum/views/bcforum_details/index.php
<?php
  echo "
\n";
  print_r($datas);
  echo "
\n"; ?>
-----------------


【Cakephp 2.3・baserCMS テーブルの連携(アソシエーション)関連記事】
baserCMSでオリジナルのデータベースから情報を取得する場合
CakePHP 2.3 ID以外のカラムでアソシエーション(連携)をさせる場合
CakePHP 2.3 ID以外のカラムでアソシエーション(連携)をさせる場合の詳細ページの注意点
CakePHP 2.3 連携先のテーブルの項目で条件抽出する場合
CakePHP 2.3 テーブルの項目を演算した結果を条件として抽出する方法
baserCMS ID以外のカラムでアソシエーション(連携)をさせる場合


スポンサーサイト
[ 2013年12月24日 00:21 ] カテゴリ:baserCMS | TB(0) | CM(0)

CakePHP 2.3 テーブルの項目を演算した結果を条件として抽出する方法

CakePHP 2.3 連携先のテーブルの項目で条件抽出する場合」連携先のテーブルの項目をキーとして条件を抽出したい場合の記述方法について書きましたが、今回は、単純にテーブルの項目をキーとするのではなく、その項目に対して何かしらの演算を行ったうえで抽出条件として利用しよう、という場合の方法です。

例えば...
100円のリンゴ 10コ在庫があります。テーブルには、リンゴの単価 100円。在庫 10コ。という項目しか保存されていませんが、在庫が 800円以上の商品を抽出したいという場合などを想定しています。

この場合は、リンゴの単価と在庫数を書けた結果を抽出のキーにできたらいいなぁ、と考えるでしょう。そのやり方についての説明です。


各テーブルの構成などは、テーブルの連携の仕組みについて書いた http://ssgiken.blog.fc2.com/blog-entry-63.html を参照してください。


例えば、「Detail.id」と「Detail3.id」のそれぞれの IDの値を足して、ある一定の数未満のレコードを抽出する場合の記述方法です。
変更したのは 5行目だけです。
実に簡単です。

-----------------/Controllers/DetailsController.php
<?php
class DetailsController extends AppController {
  function index() {
    $datas = $this->Detail->find('all',
      array ( 'conditions' => array ( "( Detail.id + Detail3.id ) <" => 17 ) )
    );
    $this->set('datas', $datas);
  }
}
?>
-----------------

あくまでもこれはサンプルですので、単に四則演算ができる「int()」の項目として IDを例にとっていますが、同一テーブル内の計算もソートキーとしての利用も可能です。

(これまた baserCMSではこの方法が利用できず....)


【Cakephp 2.3・baserCMS テーブルの連携(アソシエーション)関連記事】
baserCMSでオリジナルのデータベースから情報を取得する場合
CakePHP 2.3 ID以外のカラムでアソシエーション(連携)をさせる場合
CakePHP 2.3 ID以外のカラムでアソシエーション(連携)をさせる場合の詳細ページの注意点
CakePHP 2.3 連携先のテーブルの項目で条件抽出する場合
CakePHP 2.3 テーブルの項目を演算した結果を条件として抽出する方法
baserCMS ID以外のカラムでアソシエーション(連携)をさせる場合


[ 2013年12月20日 23:11 ] カテゴリ:CakePHP 2.x | TB(0) | CM(0)

CakePHP 2.3 連携先のテーブルの項目で条件抽出する場合

http://ssgiken.blog.fc2.com/blog-entry-63.html でテーブルの連携の仕組みについて書きましたが、連携先のテーブルの項目をキーとして条件を抽出したい場合の記述方法です。

上記のページで説明した内容は、複数のテーブルの連携(テーブルのアソシエーション)を行って、複数のテーブルをまたいでデータを取得する方法を記述しました。

だいたいの場合においては、自分のテーブル内にある項目を条件抽出のキーとして条件抽出をすると思いますが、場合によっては連携先のテーブルにある項目を条件抽出のキーとして条件抽出したい場合も出てくるでしょう。
そんな場合の記述方法です。


結構悩んでいろいろと妙な試行錯誤を行いましたが、分かってしまえば記述方法は簡単です。そして「そりゃそうだな」と思える記述方法です。

テーブルや、Model、Viewなどは上記の説明ページを参考にしてください。


変更する点は Controllerです。

例えば、通常「details.sec_code = "1234"」の値を取得する場合は、「conditions句」を使って下記の様に記述します。

-----------------/Controllers/DetailsController.php
<?php
class DetailsController extends AppController {
  function index() {
    $datas = $this->Detail->find('all',
      array ( 'conditions' => array ( 'Detail.sec_code' => '1234' ) )
    );
    $this->set('datas', $datas);
  }
}
?>
-----------------

そして、連携先のテーブルの項目で抽出したい場合は、5行目の「Detail2.sec_code」を連携先の情報にするだけです。
連携先のテーブル名は、Modelで連携の名前として記述したものを記述し、項目名はそのまま項目名を記述します。
下記の例は、いずれのテーブルも「sec_code」という項目がありますのでわかりにくいですが、「Detail2.name」などと条件を設定しても検索されます。

-----------------/Controllers/DetailsController.php
<?php
class DetailsController extends AppController {
  function index() {
    $datas = $this->Detail->find('all',
      array ( 'conditions' => array ( 'Detail2.sec_code' => '1234' ) )
    );
    $this->set('datas', $datas);
  }
}
?>
-----------------

また、「Detail2」「Detail3」のどちらも検索できますので、「$hasOne」「$belongsTo」のいずれも対応できることが分かります。


何事も分かってしまえば簡単なのですが、今回も結構試行錯誤してしまいましたね。
(ちなみに、baserCMSのプラグインとして試行錯誤をしていましたので、うまく動いていないだけでした。この辺も CakePHPと baserCMSとで動作が違うようですね。)


【Cakephp 2.3・baserCMS テーブルの連携(アソシエーション)関連記事】
baserCMSでオリジナルのデータベースから情報を取得する場合
CakePHP 2.3 ID以外のカラムでアソシエーション(連携)をさせる場合
CakePHP 2.3 ID以外のカラムでアソシエーション(連携)をさせる場合の詳細ページの注意点
CakePHP 2.3 連携先のテーブルの項目で条件抽出する場合
CakePHP 2.3 テーブルの項目を演算した結果を条件として抽出する方法
baserCMS ID以外のカラムでアソシエーション(連携)をさせる場合


[ 2013年12月19日 23:05 ] カテゴリ:CakePHP 2.x | TB(0) | CM(0)

CakePHP 2.3 ID以外のカラムでアソシエーション(連携)をさせる場合の詳細ページの注意点

CakePHPにおいて、Modelで「$primaryKey」を指定すると、個別の詳細ページを表示させる際のキーになるカラムが「$primaryKey」で指定したになりますので注意が必要、という記事になります。


また、下記の ID以外のカラムでテーブルのアソシエーション(テーブルの連携)をさせる場合の説明を下記のページで行いましたが、今回の記事は、下記の記事の続きとして書いています。
CakePHPの場合
 http://ssgiken.blog.fc2.com/blog-entry-63.html
baserCMSの場合
 http://ssgiken.blog.fc2.com/blog-entry-67.html

※baserCMSは、CakePHP上で動いている CMSですので、基本的には CakePHPの仕様に則って動いているのですが、テーブルの連携の部分は若干処理が違うようでした。そのため、別々に記事を書いていますが、今回の処理はどちらでも同じ結果でしたので、記事を分けていません。
また、ソース自体は、CakePHPのものとして書いています。


通常、一覧ページには詳細ページへのリンクがあり、詳細ページへのリンクは「ID」を設定します。

具体的なリンクの記述は以下のようになります。
----------------------
foreach ( $datas as $data ):
   echo ($this->html->link('詳細', array('controller' => 'details', 'action' => 'view', $data['Detail']['id'])));
endforeach;
----------------------

そして、受ける側の処理は、下記の様になります。

----------------------
function view($id) {
  if ($id) {
    $data = $this->Detail->read(null, $id);
    $this->set('data', $data);
  }
}
----------------------

ですが、Modelで「$primaryKey = 'sec_code'」を指定しているため、引数として IDの情報を渡しても何も表示されません。
(この場合だと「id」と「sec_code」が同じレコードは表示されますが。)

なぜなら、Modelで「$primaryKey = 'sec_code'」と指定しているため、すべての処理の PrimaryKeyが「sec_code」になってしまっているからです。

そのため、リンクの設定の部分で下記の様に「id」の部分を「sec_code」に変えることで正しくリンクがされるようになります。
----------------------
   echo ($this->html->link('詳細', array('controller' => 'details', 'action' => 'view', $data['Detail']['sec_code'])));
----------------------



私はこのことには比較的早く気付いたものの、これまで使っていた処理をそのまま使って、エラーが表示されるでもなく、値が取得できないというのは結構焦りますね。
悩む原因の一つになるでしょう。

同じように悩む方の悩みが早く解消されることを祈りつつ...


【Cakephp 2.3・baserCMS テーブルの連携(アソシエーション)関連記事】
baserCMSでオリジナルのデータベースから情報を取得する場合
CakePHP 2.3 ID以外のカラムでアソシエーション(連携)をさせる場合
CakePHP 2.3 ID以外のカラムでアソシエーション(連携)をさせる場合の詳細ページの注意点
CakePHP 2.3 連携先のテーブルの項目で条件抽出する場合
CakePHP 2.3 テーブルの項目を演算した結果を条件として抽出する方法
baserCMS ID以外のカラムでアソシエーション(連携)をさせる場合


[ 2013年12月18日 23:02 ] カテゴリ:CakePHP 2.x | TB(0) | CM(0)

CakePHP 2.3 ID以外のカラムでアソシエーション(連携)をさせる場合

CakePHPで ID以外のカラム同士でテーブルをアソシエーション(連携)させたい場合の方法について書いておきます。


そもそもは baserCMSでプラグインを作っているとき、いずれの項目もユニークではありつつ、IDにはしたくない項目同士を連携させたい、と思ったことがきっかけでした。
ただ、baserCMSのテーブル連携は、CakePHPとは少し仕様が違うようですので、baserCMSで悩んでいる方は、http://ssgiken.blog.fc2.com/blog-entry-67.html を参照してください。
(baserCMSは、CakePHPをベースに作られている CMSですので、本来はプラグインを作る際も CakePHPのルールに則って作っていきます。)


下記の「details.post_id」と「posts.id」の項目を連携させることは、CakePHPのルールに命名規約に則っていますので、「$hasOne」でも「$belongsTo」でもどちらでも簡単に連携させることができます。

ですが、「details.sec_code」と「posts.sec_code」を連携させたい場合にはどうすればいいの?という場合の対応が今回の主題です。


まず、下記 2つのテーブルを生成します。
データは、適当に登録してください。その際、それぞれのテーブルの「sec_code」の項目で連携をさせますので、いくつかのレコードは連携できるよう同じ情報を編集してください。

-----------------テーブル「posts」
CREATE TABLE IF NOT EXISTS `posts` (
  `id` int(8) NOT NULL AUTO_INCREMENT,
  `sec_code` char(4) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
-----------------

-----------------テーブル「details」
CREATE TABLE IF NOT EXISTS `details` (
  `id` int(8) NOT NULL AUTO_INCREMENT,
  `post_id` int(8) NOT NULL,
  `sec_code` char(4) DEFAULT NULL,
  `list` varchar(255) DEFAULT NULL,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
-----------------

続いて、Modelの設定です。
今回の件においては、この Modelの設定が一番大事な処理になります。

「$primaryKey」は、「/model/Detail.php」「/model/Post.php」の両方に書いてありますが、「Detail2」の「$belongsTo」で連携させる場合は、連携先の「/model/Post.php」の方に記述します。
「$hasOne」で連携させる場合は、自身の「/model/Detail.php」の中に記述をします。

その動きを確認するために、どちらかの「$primaryKey」の行を消してみると、消した方の変数が表示されなくなりますので、動きの内容が理解できるでしょう。

-----------------(/Model/Detail.php)
<?php
class Detail extends AppModel {

  var $primaryKey = 'sec_code';

  var $belongsTo = array(
    "Detail2" => array(
      "className" => "Post",
      "foreignKey" => "sec_code",
    ),
  );

  var $hasOne = array(
    "Detail3" => array(
      "className" => "Post",
      "foreignKey" => "sec_code",
    ),
  );
}
?>
-----------------

-----------------(/model/Post.php)
<?php
class Post extends AppModel {

  var $primaryKey = 'sec_code';

}
?>
-----------------

続いて、Controllerです。
こちらは、単にテーブルの値を表示させる処理とするため、簡単に記述しています。

-----------------/Controllers/DetailsController.php
<?php
class DetailsController extends AppController {
  function index() {
    $datas = $this->Detail->find('all');
    $this->set('datas', $datas);
  }
}
?>
-----------------

最後に View。
こちらも受け取った値を表示させるだけですので、「print_r」コマンドで簡単に表示しています。

-----------------/Views/Details/index.ctp
<?php
  echo "
\n";
  print_r($datas);
  echo "
\n"; ?>
-----------------


また、今回の記事を書くのに参考にしたのは下記のサイトですが、下記のサイトには Model内に記述する方法の他に、Controllerで記述する方法も書かれています。
http://labo.tsuchinokopro.com/2010/02/287/

※この方法で「$primaryKey = 'sec_code'」を指定すると、個別の詳細ページを表示させる際のキーになるカラムが「sec_code」になりますので注意が必要です。
 詳しくは http://ssgiken.blog.fc2.com/blog-entry-64.html を参照ください。


【Cakephp 2.3・baserCMS テーブルの連携(アソシエーション)関連記事】
baserCMSでオリジナルのデータベースから情報を取得する場合
CakePHP 2.3 ID以外のカラムでアソシエーション(連携)をさせる場合
CakePHP 2.3 ID以外のカラムでアソシエーション(連携)をさせる場合の詳細ページの注意点
CakePHP 2.3 連携先のテーブルの項目で条件抽出する場合
CakePHP 2.3 テーブルの項目を演算した結果を条件として抽出する方法
baserCMS ID以外のカラムでアソシエーション(連携)をさせる場合


[ 2013年12月17日 23:58 ] カテゴリ:CakePHP 2.x | TB(0) | CM(0)
プロフィール

エス技研

Author:エス技研
性別:男性
職業:Web系エンジニア
エンジニアになって 15年ほど経ちますが、その途中で 5年ほどディレクタ、マネジメントを中心とした業務を行っていたためにやや現場を離れていましたが、転職をきっかけに 2012年に現場に復帰し、新たな技術を楽しみながら勉強しています。
メインの環境は LAMP環境です。

FC2ブログランキング
FC2カウンター
FC2拍手ランキング
GoogleAdWords
カレンダー
04 | 2017/05 | 06
- 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31 - - -
検索フォーム
ブロとも申請フォーム
QRコード
QR
フリーエリア


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。