オブジェクト指向プログラミングでフレームワークを使わずに掲示板を作るよその7。
画面が出来たから編集と削除が出来るようにしようそうしよう。

目次

  • 序章
  • Step1 : MVCを揃える
  • Step2 : テンプレート作成
  • Step3 : 書き込み
  • Step4: ログの表示
  • Step5: 設定ファイルと細かな修正
  • Step6: 編集&削除画面
  • Step7: 編集&削除機能 ← 今ここ
  • Step8: ページング

編集と削除は投稿者任せで、選択された記事を別ページに表示するスタイルになっています。

oopbbs-step6-edit

各画面からPOST送信すればdeleteActionかeditActionが実行されます。

処理の流れをざっと挙げてみる。

編集の場合

  1. キーの真偽チェック
  2. 送信内容のバリデーション
  3. 古いログの上に新しいログを上書き
  4. メッセージ表示

削除の場合

  1. キーの真偽チェック
  2. IDと同じログ以外のログを保存
  3. メッセージ表示

ファイル関数的にはありきたりな処理なので、これを読んでいる諸兄には詳しい説明は不要と思う。

コントローラーの方はStep6で作っておいたメソッド内にソースを書くだけです。
簡単な削除の方からやります。

削除篇

ほとんど書き込みと変わらない。
POSTされたIDを元に記事を探して、LogオブジェクトのkeyとPOSTされたkeyが一致するかチェック。
一致していたらModelのdeleteメソッド(後述)を実行。
エラーがなかったら成功メッセージを出してreadLogメソッドで再読み込みします。

lib/controller.php (class Controller)

function deleteAction()
{
	$id = $this->model->clean($_POST['id']);
	$log = $this->model->findData($id);
	
	if($log->key === sha1($_POST['key'])){
		if($this->model->delete($id)){
			$this->view->setSystemMessage('success', '削除しました');
			$this->model->readLog();//再読み込み
		}else{
			$this->view->setSystemMessage('error', '削除出来ませんでした');
		}
	}else{
	   $this->view->setSystemMessage('error', 'キーが違います');
	}
}

削除後にreadLogメソッドが実行されると、ビューに渡される$logdataが空になるので、
テンプレートの !empty でfalseとなってメッセージだけが表示されるっていう寸法です。

oopbbs-step7-delete

function delete

idと一致するログ以外をfwriteすれば削除に。

lib/model.php (class Model)

public function delete($id)
{
	if(empty($id) || !$this->getLogData()) return false;
	
	$new = array();//新しいログ
	$logs = file($this->_getLogfileName());
	
	$fp = fopen($this->_getLogfileName(), 'w');
	
	foreach($logs as $i => $log){
		list($pid, $str) = split(',', $log, 2);
		if($pid != $id){
			fwrite($fp, trim($new));
		}
	}

	fclose($fp);
	
	return true;
}

編集篇

バリデーションが入る以外はdeleteと同じ。

lib/controller.php (class Controller)

function editAction()
{
	$this->model->setPostdata($_POST);//送信内容のセット
	
	if($this->model->validation()===true){
		
		$id = $this->model->clean($_POST['id']);
		$log = $this->model->findData($id);
		
		if($log->key === sha1($_POST['key'])){
			
				if($this->model->edit($id)){
					$this->view->setSystemMessage('success', '編集しました');
					$this->model->readLog();//再読み込み
				}else{
					$this->view->setSystemMessage('error', '編集出来ませんでした');
				}
		}else{
			$this->view->setSystemMessage('error', 'キーが違います');
		}
	 
	 }else{
		 $this->view->setSystemMessage('error', $this->model->getError());//エラーをViewに渡す
	 }
}

function edit

メソッドの中身はwriteとdeleteを足して割ったような感じです。

class/model.php (class Model)

public function edit($id)
{
	if(empty($id) || !$this->getLogData()) return false;
	
	$data = $this->_getPost();
	
	$data = array_map(array($this,'clean'), $data);//クリーンアップ
	array_unshift($data, $id, time());//先頭にIDとタイムスタンプ
	
	if($this->_userControll){//キー暗号化
		$data['key'] = sha1($data['key']);
	}
	
	$logs = file($this->_getLogfileName());//ログ確保

	$fp = fopen($this->_getLogfileName(), 'w');
	
	foreach($logs as $i => $log){
		list($pid, $str) = split(',', $log, 2);
		if($pid == $id){
			$this->myFputcsv($fp, $data);
		}else{
			fwrite($fp, trim($log));
		}
	}
	
	fclose($fp);
	
	return true;
}

編集のときは$logdataを再読み込みしたときに新しく書き込んだ内容が出るようになります。

oopbbs-step7-edit

動作的にはこれでOKなんだけどコードがダブってるのが気になる 🙁

同じコードを2箇所以上で見たら1箇所に纏めることを考えると良い、というマーチン・ファウラーの言に習い
editとwriteの中にある同じコードをメソッドにして纏めるとします。

ダブっているのはクリーンアップ、ID&タイムスタンプ追加、キーの暗号化なので、
新しくaddLogStatusというメソッドを作って、その中にソースを移動。

lib/model.php (class Model)

/**
 * 新しいログにIDやdate情報を加える
 */
protected function addLogStatus($id){
	
	$data = $this->_getPost();
	
	$data = array_map(array($this,'clean'), $data);//クリーンアップ
	
	array_unshift($data, $id, time());//先頭にIDとタイムスタンプ
	
	if($this->_userControll){//キー暗号化
		$data['key'] = sha1($data['key']);
	}
	
	return $data;
}

これに合わせてeditとwriteメソッドを変更。

lib/model.php (class Model)

public function edit($id)
{
	if(empty($id) || !$this->getLogData()) return false;
	
	$data = $this->addLogStatus($id);//IDとタイムスタンプ追加、key暗号化
	
	$logs = file($this->_getLogfileName());//ログ確保

	$fp = fopen($this->_getLogfileName(), 'w');
	
	foreach($logs as $i => $log){
		list($pid, $str) = split(',', $log, 2);
		if($pid == $id){
			$this->myFputcsv($fp, $data);
		}else{
			fwrite($fp, trim($log));
		}
	}
	
	fclose($fp);
	
	return true;
}

いくらかすっきりしたかな?

これで削除と編集が出来るようになりましたーイエー 😀
やれることが増えたから掲示板というかアプリケーションらしさがぐっと増した気がする。
あと最初に挙げた機能で足りないのはページングだけですね。

Step7 Download

動作確認はローカルで行ってください。ライセンスはCreative Commons BY-NCです。

“OOPでBBS Step7” をダウンロード oop-bbs-step7.zip – 414 回のダウンロード – 17 KB

リファクタリングの本

上でちらっと出したこの本、例文ソースはJavaだけど
どういう場面でリファクタリングすればいいのかとか、どうまとめたらさっぱりしたソースになるのかとかが
before-afterの例と共に解説してあるからとても参考になります。
PHPでオブジェクト指向プログラミングすればJavaと似るから言語の違いはそう気にならない。
結構高いし、全部書き直したくなる衝動に駆られて困るんだけどもw
こなれてきた時に読んでおくとタメになる良書です。