CAKEPHP READ 不支援復合KEY的問題 primary key composed ?

edited 十月 2013 in CakePHP
老實說~

我覺得這個地方 有很多不錯的人 給我不少不錯的建議.

跟大家討論 蠻有趣的 有空我會常來..

不過我相信這只是討論 ^^

##################################

對了 小弟指的三層式架構說的是 :

展示邏輯層 , 程式邏輯層 , 內容邏輯層

可能有些大有 layer7 的觀念.

不過 這是小弟 將 應用層再細分三層的講法.

看的懂就好了 ^^!!


https://trac.cakephp.org/ticket/2811 <<<< 唉唉唉~~老實說 我說 CAKEPHP 是玩具實在太客氣了

盡然處理順序還排在中間 ....

我可以體量它的 三層架構都要因為這個問題而大改.

同時也可以發現寫 CAKEPHP 的人對 WEB 原件的 功力真的有待加強..這種東西一開始設計時就要考慮到了.

^^!! 雖然它的架構OK 但是 這是最基本的說...

一句話送給大家 ... 在它還沒有成熟前千萬不要用來寫專案.

當玩具玩 很OK .
00707 /**
00708  * Returns a list of fields from the database
00709  *
00710  * @param mixed $id The ID of the record to read
00711  * @param mixed $fields String of single fieldname, or an array of fieldnames.
00712  * @return array Array of database fields
00713  * @access public
00714  */
00715     function read($fields = null, $id = null) {
00716         $this->validationErrors = array();
00717 
00718         if ($id != null) {
00719             $this->id = $id;
00720         }
00721 
00722         $id = $this->id;
00723 
00724         if (is_array($this->id)) {
00725             $id = $this->id[0];
00726         }
00727 
00728         if ($this->id !== null && $this->id !== false) {
00729             $db =& ConnectionManager::getDataSource($this->useDbConfig);
00730             $field = $db->name($this->alias) . '.' . $db->name($this->primaryKey);
00731             return $this->find($field . ' = ' . $db->value($id, $this->getColumnType($this->primaryKey)), $fields);
00732         } else {
00733             return false;
00734         }
00735     }
看起來有支援 復合 KEY 不過我看它的程式應該邏輯上是不可能支援復合KEY的

當我做實驗 :
function edit($id = null)
   {
       if (empty($this->data))
       {
           //$this->Fun->id = $id;
           //$this->data = $this->Fun->read();
           $this->set('fun', $this->Fun->read(array('id','pjid'),array('userms','0')));
       }
       else
       {
           //print_r($this->data);        exit ;
           if ($this->Fun->save($this->data['Fun']))
           {
               //$this->flash('Your post has been updated.','/fun');
                $this->redirect('/fun');
           }
       }
   }
結果 DB 組合結果 :

SELECT `Fun`.`id`, `Fun`.`pjid` FROM `ecstart_funs` AS `Fun` WHERE `Fun`.`id` = 'userms' LIMIT 1

果然真的很去它的難用....

用的超級 美爽爽的情況之下...

發現 它最後是吐 return $this->find($field . ' = ' . $db->value($id, $this->getColumnType($this->primaryKey)), $fields);

回來的格式.

看來 READ 的部份只好 另外 再新增一個 METHOD 來寫了...

鳴鳴~~ 如果一開始有支援就不用搞這麼多飛機了.

CAKEPHP 的成熟度還有待加強 ...

解決了 :

^^!! 好辛苦 CAKEPHP 真難用 鳴鳴~~~

雖然它不夠成熟 但是還好它的 架構夠強 ^^ 可以自定新的 METHOD ....

寫了一支新 METHOD 來解決它.
function edit($id = null)
   {
       if (empty($this->data))
       {
           //$this->Fun->id = $id;
           //$this->data = $this->Fun->read();
                $search_str = "
                                AND:    Fun:    id:             =:                      ,
                                AND:    Fun:    pjid:           =:
                ";
                //echo "<pre>";
                //print_r($this->ecstart_get_one_record($this->Fun,$search_str));
                //exit ;
                $this->data =  $this->ecstart_get_one_record($this->Fun,$search_str);
       }
       else
       {
           //print_r($this->data);        exit ;
           if ($this->Fun->save($this->data['Fun']))
           {
               //$this->flash('Your post has been updated.','/fun');
                $this->redirect('/fun');
           }
       }
   }
這裡我解釋一下 :

$search_str = "
AND: Fun: id: =: ,
AND: Fun: pjid: =:
";
這個字串是要告訴 我的 $this->ecstart_get_one_record($this->Fun,$search_str);

我有二個 ID 分別是 ID 和 PJID 這二個 ID 要用 AND 的方式.

然後丟給 ecstart_get_one_record() METHOD

它會自動演算將 RECORD 丟回來給我.

然後我再把它丟給

$this->data 則版型就會取用 解決 READ 不能做覆合 KEY 的問題 .
####################################################################################################
        function ecstart_get_one_record($CALL,$field_str){
                $field_arr = explode(",",str_replace("\t","",str_replace("\n","",str_replace(" ","",$field_str))));
                $subquery = array();
                foreach($field_arr as $fv){
                        $fd = explode(":",$fv);
                        if(isset($this->params["url"][$fd[2]])){
                                if($this->params["url"][$fd[2]] != ""){
                                        $fd[1] = ucfirst($fd[1]);
                                        $subquery[$fd[0]]["`".$fd[1]."`.`".$fd[2]."`"] = $fd[3] ." ".@$fd[4].$this->params["url"][$fd[2]].@$fd[5] ;
                                        //@$search[";status"]["search"][$fd[2]] = $this->params["url"][$fd[2]] ;
                                        //@$search[";status"]["path"]["search"] .= $fd[2].'='.$this->params["url"][$fd[2]] ;
                                }
                        }
                }

                if(is_array($subquery)){

                        //print_r($subquery); exit ;

                        $record =
                                   $CALL->find(
                                                        $conditions = $subquery,
                                                        $fields = null,
                                                        $order = null,
                                                        $page = 1,
                                                        $recursive = null
                                   );

                        return  $record ;
                }
                else{
                        return false ;
                }


        }


再加強一下 限定

$search_str = "
AND: Fun: id: =: ,
AND: Fun: pjid: =:
";

ID 和 PJID 的欄位 在 GET 上都不能是空值 ...
function ecstart_get_one_record($CALL,$field_str){
                $field_arr = explode(",",str_replace("\t","",str_replace("\n","",str_replace(" ","",$field_str))));
                $subquery = array();
                foreach($field_arr as $fv){
                        $fd = explode(":",$fv);
                        if(@$this->;params["url"][$fd[2]] != ""){
                                        $fd[1] = ucfirst($fd[1]);
                                        $subquery[$fd[0]]["`".$fd[1]."`.`".$fd[2]."`"] = $fd[3] ." ".@$fd[4].$this->params["url"][$fd[2]].@$fd[5] ;
                                        //@$search[";status"]["search"][$fd[2]] = $this->params["url"][$fd[2]] ;
                                        //@$search[";status"]["path"]["search"] .= $fd[2].'='.$this->params["url"][$fd[2]] ;
                        }
                        else{
                                $this->ecstart_alert_msg(MSG_SEARCH_ID);  // 回傳 錯誤 
                        }

                }

                if(is_array($subquery)){

                        //print_r($subquery); exit ;

                        $record =
                                   $CALL->find(
                                                        $conditions = $subquery,
                                                        $fields = null,
                                                        $order = null,
                                                        $page = 1,
                                                        $recursive = null
                                   );

                        return  $record ;
                }
                else{
                        return false ;
                }


        }

結果.... SAVE METHOD 好像也要改一下版...

哇哈哈哈~~ 看起來

展示邏輯層 , 程式邏輯層 , 內容邏輯層 都要做出對應的元件才能解決這個問題

看來又要花我一些時間

CAKEPHP 才能使用 鳴鳴~~老闆可以不要用它來寫小專案嗎~~ << 心聲

原始討論: http://twpug.net/x/modules/newbb/viewtopic.php?topic_id=3123

評論

  • edited 一月 2008
    展示邏輯層 , 程式邏輯層 , 內容邏輯層

    看不慣的老大們可以把它看成

    展示邏輯區 , 程式邏輯區 , 內容邏輯區

    本來想說 cakephp 後台 程式產生器快完成了.

    想不到又碰到復合 key 的問題..

    只好再拉一個 componer 物件 配合 db_sources 取代 model 來用

    然後 再拉一個 helper 取代 html helper ...

    要把它改到 能用 還要一點時間

    有興趣的可以一起玩 ...
  • edited 一月 2008
    結果我又發現....

    hasAndBelongsToMany

    hasone

    hasmany

    也不支援 primary key composed
  • edited 一月 2008
    嗯...
    我看到 ROR 上已經有人解決這個問題了.

    http://compositekeys.rubyforge.org/

    不曉得 cakePHP 什麼時候會提出解法.
  • edited 一月 2008
    ccc 老大...

    我大楖看了一下

    如果 用 model view controler 的觀念去看.

    model 上 有太多原件都只吃 單一 key

    而 view 也對應了這個方法.

    如果要改進.

    可能要動到的東西很多很多.

    如果 primary key composed 用很兇的人.

    用起 cakephp 應該會很痛苦.
  • edited 一月 2008
    我之前在設計資料庫時也有類似的問題,後來確認 CakePHP 不支援後就主動迴避了,並沒有發現非得使用 primary key composed 的狀況。

    下面是相關討論:
    http://groups.google.com/group/cake-php/browse_thread/thread/4a3f44f8217435cc
    nat 提到雙主鍵的設定不利於 REST 架構

    https://trac.cakephp.org/ticket/1293
    官方確定不會支援雙主鍵設計

    ZF 有支援:
    http://framework.zend.com/issues/browse/ZF-37
  • edited 一月 2008
    謝謝 kiang 站大的 補充說明


    其實我也想過要避開它.

    但是 這在 db 設計上的考量 我覺得可讀性會大打折扣.

    畢竟 relation model 的設計 有它的考量

    不是要你為了 cakephp 去配合它只能採 唯一 key的做法.

    這也讓我想到 如果系統長的太大 我真的不知道怎麼去跟大家解釋.

    在畫文件時我也會覺得手腳難伸.

    碰到 駭客級的新進同人 想要一打開 系統就改的 順手 應該會有點困難.

    還要請同人好好 k 一下這個奇怪的文件.

    而且 pky 在 效能上,我覺得(趕快強調一下 ^^!! 等等又引來太多的討論) 

    我覺得 pky 的 在 mysql 的效能表現上 比 index 來的好.

    而且 index 常會有 otpimize 的需要 , 我實在不想一直去 otpimize 所有的 db 說.

    而 在日後 系統設計上 覆合 key 的問題一定會出現 .

    如果是一個長期要開發的專案 , 我實在擔心它會成為一個很大的隱憂 .

    當然 套 norman 前輩說的話 :

    各種需求有各種需求 可以配合的 工具 .

    cakephp 在 開發的速度 和合作上 可以達到蠻不錯的效果.

    而小弟 (個人覺得) 若要長期或是做大型專案.

    這點讓我蠻擔心的.
Sign In or Register to comment.