//コントローラクラス内の処理 $errors = $this->TestHasManyA->validationErrors;$errorsはバリデーション情報。
if(empty($this->Animal)){
App::uses('Animal','Model');
$this->Animal=ClassRegistry::init('Animal');
//$this->Animal=new Animal();
}
//SELECT情報
$fields=array(
'id',
'xxx',
'name',
);
//WHERE情報
$conditions=array(
"id = {$id}",
"xxx = '{$xxx}'",
"delete_flg = 0",
);
//ORDER情報
$order=array('sort');
//オプション
$option=array(
'fields'=>$fields,
'conditions'=>$conditions,
'order'=>$order,
'recursive' => -1,
);
//DBから取得
$data=$this->Animal->find('all',$option);
//2次元配列に構造変換する。
if(!empty($data)){
$data=Hash::extract($data, '{n}.Animal');
}
return $data;
if(empty($this->Animal)){
App::uses('Animal','Model');
$this->Animal=new Animal();
}
//SELECT情報
$fields=array(
'Animal.id',
'Animal.xxx',
'Animal.name',
'Food.name',
);
//WHERE情報
$conditions=array(
"Animal.xxx = '{$xxx}'",
"Animal.name like '%{$name}%'",
);
//ORDER情報
$order=array('Animal.sort');
//JOIN情報
$joins = array(
array(
'type' => 'left',//innerも指定可能
'table' => 'foods',
'alias' => 'Food',
'conditions' => array(
'Animal.food_id = Food.id',
),
),
//他に連結するテーブルがあれば上記のような配列を連結
);
//オプション
$option=array(
'fields'=>$fields,
'conditions'=>$conditions,
'joins'=>$joins,
'order'=>$order,
'recursive' => -1,
);
//DBから取得
$data=$this->Animal->find('all',$option);
//データ構造を変換(2次元配列化)
$data2=array();
foreach($data as $i=>$tbl){
foreach($tbl as $ent){
foreach($ent as $key => $v){
$data2[$i][$key]=$v;
}
}
}
return $data2;
//データを構造変換してエンティティを取得
//$ent=array();
//if(!empty($data)){
// foreach($data as $i=>$tbl){
// foreach($tbl as $key=>$v){
// $ent[$key]=$v;
// }
// }
//}
//return $ent;
//DBからエンティティを取得
$ent = $this->find('first',
array(
'conditions' => "id={$ent['Neko']['id']}"
));
$ent=$ent['Neko'];
//SELECT情報
$fields=array(
'id',
'xxx',
'name',
);
//WHERE情報
$conditions=array(
"id = {$id}",
"xxx = '{$xxx}'",
"delete_flg = 0",
);
$dbo = $this->Neko->getDataSource();
//オプション
$option=array(
'table' => $dbo->fullTableName($this->Neko),
'alias' => 'Neko',
'fields'=>$fields,
'conditions'=>$conditions,
);
$sql = $dbo->buildStatement($option,$this->Neko);
//$sql → SELECT ... FROM nekos AS Neko WHERE ...
/**
* カテゴリIDに紐づくアニマルリストを取得する
* @param int $category_id カテゴリID
* @return アニマルリスト
*/
public function getAnimalList($category_id){
if(empty($this->Animal)){
App::uses('Animal','Model');
$this->Animal=ClassRegistry::init('Animal');
}
//SELECT情報
$fields=array(
'id',
'animal_name',
);
//WHERE情報
$conditions=array(
"category_id = {$category_id}",
"delete_flg != 1",
);
//ORDER情報
$order=array('animal_name');
//オプション
$option=array(
'fields'=>$fields,
'conditions'=>$conditions,
'order'=>$order,
);
//DBから取得
$data=$this->Animal->find('all',$option);
//構造変換
$list = array();
if(!empty($data)){
$list=Hash::combine($data, '{n}.Animal.id','{n}.Animal.animal_name');
}
return $list;
}
認証状態と未認証状態を判定
認証状態と未認証状態を判定することもできる。特定のメソッドだけ未認証を許可する
特定のアクションだけ未認証を許可する場合、引数に許可するアクション名(メソッド名)を指定する。$this->Auth->allow('test_action');
class NoAuthController extends AppController {
public $name = 'NoAuth';
public function beforeFilter() {
$this->Auth->allow(); // 認証と未認証の両方に対応したページする。
parent::beforeFilter();//基本クラスのメソッドを呼び出し。
}
public function index() {
$msg="認証されていません。";
if(!empty($this->Auth->user('id'))){
$msg = "認証中です。";
}
$this->set(array('msg'=>$msg));
}
}
<a href="users/login">ログイン</a><br> <a href="users/logout">ログアウト</a><br> <br> <?php echo $msg?>
<a href="users/login">ログイン</a> <a href="users/logout">ログアウト</a>
class DemoController extends AppController {
public $name = 'Demo';
public $components=null;//ログイン認証不要
public function index(){
}
}
Controller/NoAuthController.php
class NoAuthController extends AppController {
public $name = 'NoAuth';
public function beforeFilter() {
$this->Auth->allow(); // 認証と未認証の両方に対応したページする。
parent::beforeFilter();//基本クラスのメソッドを呼び出し。
}
public function ajax_auth(){
}
// AJAXで呼び出されるアクション
public function ajax_auth_test1(){
$this->autoRender = false;//ビュー(ctp)を使わない。
// ★認証状態の確認
if(empty($this->Auth->user('id'))){
return '認証されていません';
}
$json_param=$_POST['key1'];
return $json_param;
}
}
View/NoAuth/ajax_auth.ctp
<input type="button" value="test1" onclick="test1()" /> <div id="xxx"></div>
JavaScript
function test1(){
var data={'neko':'ネコ','same':{'hojiro':'ホオジロザメ','shumoku':'シュモクザメ'},'xxx':111};
var json_str = JSON.stringify(data);
$.ajax({
type: "POST",
url: "/cake_demo/no_auth/ajax_auth_test1",
data: "key1="+json_str,
cache: false,
dataType: "text",
success: function(str_json, type) {
$("#xxx").html(str_json);
},
error: function(xmlHttpRequest, textStatus, errorThrown){
$('#xxx').html(xmlHttpRequest.responseText);//詳細エラーの出力
}
});
}
test1ボタンを押した時の出力
認証中のとき{"neko":"ネコ","same":{"hojiro":"ホオジロザメ","shumoku":"シュモクザメ"},"xxx":111}
認証されていません
echo $this->Form->input('animal', array(
'legend' => false,
'type' => 'radio',
'value'=>'usi',//初期選択値
'options' => array('neko'=>'猫','nezumi'=>'ネズミ','usi'=>'牛','tora'=>'虎',)
));
value属性を省略したり、nullを指定すると、未選択状態になる。
/**
* カテゴリ名をマッピング
* データの指定IDに紐づく名称をカテゴリテーブルからとってきて、データにセットする。
* @param $data データ
* @return データ
*/
public function mapping($data){
//引数データの紐づけ情報
$id_key='category_id1';
$name_key='category_name1';
$model_name1="RecCrud1";
//結合先テーブルの紐づけ情報
$id_key2='id';
$name_key2='name';
$model_name2="Category";
// データからIDリストを取得
$ids=array();
foreach($data as $ent){
$id=$ent[$model_name1][$id_key];
if(!empty($ent[$model_name1][$id_key])){
$ids[]=$ent[$model_name1][$id_key];
}elseif($ent[$model_name1][$id_key]===0 || $ent[$model_name1][$id_key]==='0'){
$ids[]=$ent[$model_name1][$id_key];
}
}
// IDリストから重複するIDリストを削除
$ids=array_unique($ids);
if(empty($ids)){
foreach($data as &$ent){
$ent[$model_name1][$name_key]=null;
}
unset($ent);
return $data;
}
// IN句をIDリストから作成する。
$str_ids=join($ids,',');
//元データをDBから取得
$fields=array($id_key2,$name_key2);
$conditions=array("id IN ({$str_ids})");
$option=array(
'fields'=>$fields,
'conditions'=>$conditions,
'recursive' => -1,
);
$mapData=$this->find('all',$option);
//マッピングデータを作成
$map=array();
//マッピングデータを作成。ついでにサニタイズ
if(!empty($mapData)){
foreach($mapData as &$map_ent){
$map[$map_ent[$model_name2][$id_key2]]=Sanitize::html($map_ent[$model_name2][$name_key2]);
}
unset($ent);
}
// データ件数分ループして、IDに紐づくマッピングのデータをセット
foreach($data as &$ent){
if(!empty($map[$ent[$model_name1][$id_key]])){
$ent[$model_name1][$name_key]=$map[$ent[$model_name1][$id_key]];
}else{
$ent[$model_name1][$name_key]=null;
}
}
unset($ent);
return $data;
}
$str1="→テスト<a href='#' onclick='alert(\"XSS攻撃のテスト\");' > Hello</a>"; echo h($str1);
class AppHelper extends Helper {
//オリジナルヘルパーとなるメソッド
public function test($v){
$v='大きい';
return $v;
}
}
echo $this->Html->test('ネコ');
//出力例 → 大きいネコ
class IrukaHelper extends AppHelper {
public function test(){
echo 'イルカ';
}
}
class SampleController extends AppController {
public $helpers = array('Iruka');
~略~
$this->Iruka->test();
//出力例 → イルカ
$this->FrontA = $this->Helpers->load('FrontA');
$this->FrontA->test();
App::uses('Helper', 'View/Helper');
class FrontAHelper extends Helper {
public function test(){
echo 'テストでござい';
}
}
public function uhtml_entity_decode_ex($v){
$v=html_entity_decode($v);//エスケープされた記号を元に戻す。
$v=str_replace('<','<',$v);//「 < 」記号のみサニタイズ
$v=nl2br($v);//改行コードをbrタグに変換
return $v;
}
アスキーアートなど記号をふんだんに使った文字列を表示させたいが、XSS対策は施したいといった場合の時に使うと便利です。
$cakeDescription = __d('cake_dev', 'CakePHP: the rapid development php framework');
?>
<!DOCTYPE html>
<html>
<head>
<?php echo $this->Html->charset(); ?>
<title>
<?php echo $cakeDescription ?>:
<?php echo $title_for_layout; ?>
</title>
<?php
echo $this->Html->meta('icon');
echo $this->Html->css(array(
'cake.generic', //←これは、bootstrap.min.cssに置き換わる
'http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/ui-lightness/jquery-ui.css'
));
echo $this->fetch('meta');
echo $this->fetch('css');
//echo $this->fetch('script');
echo $this->Html->script(array(
'http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js',
'http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js',
'http://ajax.googleapis.com/ajax/libs/jqueryui/1/i18n/jquery.ui.datepicker-ja.min.js',
));
?>
~ 以下略 ~
修正後 app/View/Layouts/default.ctp
$cakeDescription = __d('cake_dev', 'CakePHP: the rapid development php framework');
?>
<!DOCTYPE html>
<html>
<head>
<?php echo $this->Html->charset(); ?>
<title>
<?php echo $cakeDescription ?>:
<?php echo $title_for_layout; ?>
</title>
<?php
echo $this->Html->meta('icon');
echo $this->Html->css(array(
'bootstrap.min.css',
'http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/ui-lightness/jquery-ui.css'
));
echo $this->fetch('meta');
echo $this->fetch('css');
//echo $this->fetch('script');
echo $this->Html->script(array(
'jquery-1.11.1.min.js',
'http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js',
'bootstrap.min.js',
'http://ajax.googleapis.com/ajax/libs/jqueryui/1/i18n/jquery.ui.datepicker-ja.min.js',
));
?>
<script>
$(function() {
$("#datepicker").datepicker({
dateFormat:'yy-mm-dd'
});
//2つ目の日付入力用
$("#datepicker2").datepicker({
dateFormat:'yy-mm-dd'
});
});
</script>
~ 以下略 ~
$ret=$this->モデル->delete(削除するID);
//モデルクラス内で削除する場合。 $ret=$this->delete(削除するID);
// モデル生成
if(empty($this->TestModel)){
App::uses('TestModel','Model');
$this->TestModel=new TestModel();
}
// トランザクション開始
$dataSource = $this->TestModel->getDataSource ();
$dataSource->begin();
// ★削除処理 id=10000を削除
$ret=$this->TestModel->delete(10000);
if($ret==true){
$dataSource->commit();//コミット
}else{
$dataSource->rollback();//ロールバック
}
$this->Neko->begin();//トランザクション開始
$this->Neko->deleteAll(array('text1'=>'wani'));//複数行をまとめて削除
$this->Neko->commit();
SELECT `Neko`.`id` FROM `cake_smp`.`nekos` AS `Neko` WHERE `text1` = 'wani' GROUP BY `Neko`.`id` DELETE `Neko` FROM `cake_smp`.`nekos` AS `Neko` WHERE `Neko`.`id` IN (16, 17)
| id | val1 | text1 | test_date | test_dt |
|---|---|---|---|---|
| 15 | 3 | yagi | 2014/4/3 | 2014/12/12 0:00 |
| 18 | 3 | wani | 2014/4/3 | 2014/12/12 0:00 |
| 19 | 3 | wani | 2014/4/3 | 2014/12/12 0:00 |