今回は CakePHP で作られた
オープンソースにオリジナルの機能を追加する方法を
紹介してみようと思います。
この記事の肝は
・データベースからデータを拾う方法
・データベースにデータを追加する方法
の 2 点になります。
さくっとこの記事を読みたい方は
データベースを触る箇所まで
読み飛ばす事を推奨します。
機能を追加する方法の概要
機能を追加する時は
対象の View と Controller に追記します。
例えば irohaBoard で
「コース」に「複製」機能を追加したい場合は
View/Courses の admin_index.ctp と
Controller の CoursesController.php を編集します。
View の編集方法
View を編集する場合は
html を編集する感覚で編集します。
例えば「複製」ボタンを追加したい場合は
「削除」ボタンなどの似たボタンを複製して
action を copy に変更します。
「削除」というテキストも
「複製」に変えます。
Controller の編集方法
Controller を編集する場合は
自作のメソッドを追加する形になります。
追加するメソッド以外は触る必要がありません。
View ファイルを編集した際に
action を copy で作成した場合は
admin_copy メソッドか
copy メソッドを作成する事になると思います。
admin_edit メソッドや
edit メソッドなど
よく似たメソッドを丸々コピーして
メソッド名を変更して
中身を書き換える事を推奨します。
そして中にデータベースにアクセスする記述をします。
データベースへアクセスする記述が
この記事の肝になります。
それをこれから説明していきます。
データベースからデータを取得する手順
下記のようにデータベースを取得・変更をします。
これは Course を複製する機能の記述ですが
記事を読んでいて分からなくなった場合に
このメソッドを読みなおして下さい。
/**
* コースのコピー
* @param int $course_id コースID
*/
public function admin_copy($course_id = null)
{
/*if($this->readAuthUser('role') != 'admin')
{
throw new NotFoundException(__('Invalid course'));
}*/
if(!$this->Course->exists($course_id))
{
throw new NotFoundException(__('Invalid course'));
}
$myGet = $this->Course->find('first', array('conditions' => array('Course.id' => $course_id)));
$coursedata = array('title' =>$myGet['Course']['title'], 'introduction' => $myGet['Course']['introduction'], 'opened' => $myGet['Course']['opened'], 'created' => $myGet['Course']['created'], 'modified' => $myGet['Course']['modified'], 'deleted' => $myGet['Course']['deleted'], 'sort_no' => $myGet['Course']['sort_no'], 'comment' => $myGet['Course']['comment'], 'user_id' => $myGet['Course']['user_id']);
$this->Course->save($coursedata);
$oneTimeID = $this->Course->id;
//$this->log($myGet['Content'], 'error');
//$this->log($myGet, 'error');
//$this->log($this->Course->id, 'error');
foreach ($myGet['Content'] as $article) {
//$this->log($article, 'error');
$oneTimeID2 = $article['id'];
$contentdata = array('user_id' => $article['user_id'], 'course_id' => $oneTimeID, 'title' => $article['title'], 'url' => $article['url'], 'file_name' => $article['file_name'], 'kind' => $article['kind'], 'body' => $article['body'], 'timelimit' => $article['timelimit'], 'pass_rate' => $article['pass_rate'], 'question_count' => $article['question_count'], 'wrong_mode' => $article['wrong_mode'], 'status' => $article['status'], 'opened' => $article['opened'], 'created' => $article['created'], 'modified' => $article['modified'], 'deleted' => $article['deleted'], 'sort_no' => $article['sort_no'], 'comment' => $article['comment']);
//$this->log($contentdata, 'error');
$this->loadModel('Content');
$this->Content->create();
$this->Content->save($contentdata);
$oneTimeID3 = $this->Content->id;
if($article['kind'] == 'test' || $article['kind'] == 'enquete') {
$this->loadModel('ContentsQuestion');
$myGet2 = $this->ContentsQuestion->find('all', array('conditions' => array('ContentsQuestion.content_id' => $oneTimeID2)));
//$this->log($myGet2, 'error');
foreach($myGet2 as $oneMyGet2) {
//$this->log($oneMyGet2, 'error');
$contentsQuestiondata = array('content_id' => $oneTimeID3, 'question_type' => $oneMyGet2['ContentsQuestion']['question_type'], 'title' => $oneMyGet2['ContentsQuestion']['title'], 'body' => $oneMyGet2['ContentsQuestion']['body'], 'image' => $oneMyGet2['ContentsQuestion']['image'], 'options' => $oneMyGet2['ContentsQuestion']['options'], 'correct' => $oneMyGet2['ContentsQuestion']['correct'], 'score' => $oneMyGet2['ContentsQuestion']['score'], 'explain' => $oneMyGet2['ContentsQuestion']['explain'], 'comment' => $oneMyGet2['ContentsQuestion']['comment'], 'created' => $oneMyGet2['ContentsQuestion']['created'], 'modified' => $oneMyGet2['ContentsQuestion']['modified'], 'sort_no' => $oneMyGet2['ContentsQuestion']['sort_no']);
unset($this->ContentsQuestion->validate['question_type']);
$this->ContentsQuestion->create();
$this->ContentsQuestion->save($contentsQuestiondata);
}
}
}
return $this->redirect(['action' => 'index']);
}
データベースからデータを取得する場合は
$this->loadModel('Controller 名(最後の s を抜く) ');
$this -> Controller 名(最後の s を抜く) ->find
メソッドを使うのが楽だと思います。
loadModel メソッドは
$this -> Controller 名(最後の s を抜く)
を実行する際に
実行する必要があります。(使用する Controller が変わる度に実行)
1 件取得したい場合は
$myGet = $this->Course->find('first', array('conditions' => array('Course.id' => $course_id)));
で取得して
$myGet['Course']['title']
等で取得する形です。
'Course' 部分は
$this->log($myGet, 'error');
で調査します。
複数件取得したい場合は
$myGet2 = $this->ContentsQuestion->find('all', array('conditions' => array('ContentsQuestion.content_id' => $oneTimeID2)));
等の記述で取得した後に
foreach($myGet2 as $oneMyGet2) {
}
で各要素について実行していきます。
$oneMyGet2['ContentsQuestion']['title']
等で各値を取得します。
新規で見た目を作成するのは面倒なため
処理が完了したら元の画面に
リダイレクトする事を推奨します。
return $this->redirect(['action' => 'index']);
といった記述になると思われます。
データベースに要素を追加する
データベースに要素を追加する場合は
$mydata = array('title' => 'Hellow World', 'body' => 'こんにちは世界');
$this->loadModel('Controller 名(最後の s を抜く)');
$this->Controller 名(最後の s を抜く)->create();
$this->Controller 名(最後の s を抜く)->save($mydata);
//$oneTimeID = $this->Controller 名(最後の s を抜く)->id; //新規作成された id を知りたい場合
という記述をします。
バリデーションエラーが発生した場合は
unset($this->ContentsQuestion->validate['question_type']);
といった記述が必要な可能性もあります。
どのバリデーションがエラーになっているか調べる場合は
$this->Controller 名(最後の s を抜く)->validationErrors
を使用します。
if (!$this->ContentsQuestion->save($contentsQuestiondata)) {
$this->log($this->ContentsQuestion->validationErrors, 'error')
}
等が手堅いと思います。
以上、駆け足になりましたが
CakePHP で作成されたオープンソースに
機能を追加する手順を紹介しました。
じっくり紹介してしまうと
記事を量産する事になるため
駆け足で紹介させて頂きました。
この記事を使ってオープンソースに機能を
追加出来た人が現れたならば嬉しいです。
なお私は Windows11 標準の
メモ帳で機能を追加しています。
さくっと実装する場合は
エディタをインストールする手間を嫌って
メモ帳で機能を追加するのも一考です。
閲覧ありがとうございました。