CakePHP2.xでデバッグキットを使う

CakePHP2.xでデバッグキットを使いたい~

デバッグキットをダウンロードします。

https://github.com/cakephp/debug_kit/tree/2.2

ダウンロードファイルを解凍したら「DebugKit」に名前を変更して、
cakephpのpluginsフォルダに移動させます。

bootstrap.phpに下記を追加


CakePlugin::load('DebugKit');

次に/app/Controller/AppController.phpに下記を追加

public $components = array('DebugKit.Toolbar');

/app/View/Layouts/default.ctp の sql_dump 部分を削除

<?php echo $this->element('sql_dump'); ?>

以上です。

XAMPPでWordPress導入時のhtaccess

XAMPPにWordPressを導入したけど、TOPページ以外にアクセスするとTOPに飛ばされてしまう場合の対処方法

htaccessのRewriteEngineの設定を正しく行うと解消されます。

例えば下記のURLだとすると…
http://localhost/wordpress/

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /wordpress/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wordpress/index.php [L]
</IfModule>

RewriteBase
RewriteRule

上記2箇所の設定を調整する。

以上です。

[JQuery]data属性の取り扱い

HTML5からdataという独自属性が使えるようになりました。
data-* とdata-の後に好きな名前と値を設定が出来ます。

(例)

<div data-no="1" data-val="mokuji">目次</div>
<div data-no="2" data-val="mokuteki">目的について</div>

その独自属性をjqueryで取得する方法。

data()を使って内容を取得する。
取得したデータは連想配列として取得します。

$(this).data();

結果

{"no":"1", "val":"mokuji"}

個別に指定でひとつだけ取得も可

$(this).data("no");

結果

{"no":"1"}

独自に値が設定できるので便利かも~

[EC-CUBE2]複数配送設定を無効にする

EC-CUBE2で「お届け先ごと送料無料プラグイン」と「送料無料対象商品設定」の両方を入れると思った動作をしないパターンがある。

どちらを優先するか悩んだ末、複数配送を使う人が少数ということもあり、複数配送設定をOFFにできるか調査した。

設定は簡単で、管理画面から「システム設定」→「パラメータ設定」の中にある「USE_MULTIPLE_SHIPPING」をfalseに設定する。

これで複数配送の設定が無効になります。

[EC-CUBE2]商品についての問合せ

商品についてのお問合せで本文にどの商品についての問合せなのかを記載する。

商品詳細ページ
問合せフォーム

上記2種類のテンプレートを編集します。

▼商品詳細ページ
/data/Smarty/templates/default/products/detail.tpl

<a href="<!--{$smarty.const.HTTPS_URL}-->contact/?product_id=<!--{$tpl_product_id}-->">このアイテムについて問い合わせる</a>

▼問合せフォーム
/data/Smarty/templates/default/contact/index.tpl

textareaタグの間に下記を追加。

<!--{if $smarty.get.product_id != ''}-->
商品番号:<!--{$smarty.get.product_id|escape}-->についての問合せ
<!--{/if}-->

[EC-CUBE2]隠し商品

隠し商品リンクの依頼がありました。
前回はカテゴリーごとでしたが、今回は商品単体です。

今回のサーバーはjsonが使えるので、jsonで対応します。

■検索処理の修正
修正ファイル
/data/config/config.php
/data/class/pages/products/LC_Page_Products_List.php

修正ファイルはカテゴリーのやつと同じ

▼config.php

ここに非表示の商品IDの値を設定する。
配列をjson_encodeした値を設定する。

define("Special_Item_ids", json_encode(array(14)));

▼LC_Page_Products_List.php

375行目あたりのlfGetSearchConditionメソッドに処理を追加します。
下記の処理に追加します。
・$searchCondition[‘where’] = SC_Product_Ex::getProductDispConditions(‘alldtl’);の位置を移動させます。
・}else{の処理を追加します。

        // ▼対象商品IDの抽出
        // 商品検索条件の作成(未削除、表示)
        $searchCondition['where'] = SC_Product_Ex::getProductDispConditions('alldtl');

        // カテゴリからのWHERE文字列取得
        if ($arrSearchData['category_id'] != 0) {
            list($searchCondition['where_category'], $searchCondition['arrvalCategory']) = SC_Helper_DB_Ex::sfGetCatWhere($arrSearchData['category_id']);

		// 商品一覧で検索の場合対象product_idは検索にかからないようにする Yuiworks.Maeda 2018-05-30
		} else {
			$searchCondition['where'] .= " AND product_id NOT IN (?)";
			$searchCondition['arrval'][] = implode(",", json_decode(Special_Item_ids));
		}

CakePHP2で認証処理

CakePHP2で認証処理を追加する方法

AppContorller.php

public $components = array(
	'Auth' => array(
		'loginAction' => array(
			"controller"=>"login",
			"action"=>"index"
		),
		'loginRedirect' => array(
			'controller' => 'posts',
			'action' => 'index'
		),
		'authenticate' => array(
			'Form' => array(
				'passwordHasher' => 'Blowfish',
				'hashType' => 'sha1',
				'userModel' => 'Users',
				"fields"=>array(
					"username"=>"account",
					"password"=>"password"
				)
			)
		)
	)
);

loginAction: ログインフォームのページを指定
loginRedirect: ログイン処理後に移動するページを師弟
authenticate: 認証処理の種類を指定

User.php(モデル)

App::uses('BlowfishPasswordHasher', 'Controller/Component/Auth');
class User extends AppModel {
	// ハッシュ処理
	public function beforeSave($options = array()) {
		if (isset($this->data[$this->alias]['password'])) {
			$passwordHasher = new BlowfishPasswordHasher();
			$this->data[$this->alias]['password'] = $passwordHasher->hash(
				$this->data[$this->alias]['password']
			);
		}
		return true;
	}
}

パスワードをハッシュ化する処理

ログイン処理をします。

LoginController.php

class LoginController extends AppController{
	public function initialize() {
		parent::initialize();
	}	

	//コントローラー
	public function index() {
		$this->loadModel("Users");

		if($this->request->is('post')){//POST送信なら
            if($this->Auth->login($this->data["Users"])){//ログイン成功なら
                return $this->redirect($this->Auth->redirectUrl()); //Auth指定のログインページへ移動
            }else{ //ログイン失敗なら
                $this->Flash->error(__('ユーザ名かパスワードが違います'));
            }
        }
	}
}

AppControllerでAuthの処理を指定しているので、認証をしたくないページにはコントローラーに下記の処理を追加します。
actionを指定すると認証の処理を省けます。

	/**
	 *  Controller内共通設定
	 */
	public function beforeFilter(){
        $this->Auth->allow('index', "view", "edit", "add");
	}

CakePHP3でログイン認証を構築

CakePHP3でログイン認証を構築

細かいところは公式マニュアルをチェック
https://book.cakephp.org/3.0/ja/controllers/components/authentication.html

AppController.php – コントローラー全体の認証設定を行う
LoginController.php – ログインフォーム、ログイン処理など
TUsersController.php – ユーザー表示、登録、編集など

■認証設定(AppController.php)

initializeに認証処理を追記します。

public function initialize()
{
	parent::initialize();

	$this->loadComponent('RequestHandler');
	$this->loadComponent('Flash');
	# 認証
	$this->loadComponent('Auth', [
		'loginAction' => [
			'controller' => 'Login',
			'action' => 'index'
		],
		'loginRedirect' => [
			'controller' => 'TUsers',
			'action' => 'index'
		],
		'logoutRedirect' => [
			'controller' => 'Login',
			'action' => 'index'
		],
		'authenticate' => [
			'Form' => [
				'userModel' => 'TUsers',
				'fields' => [
					'username' => 'account',
					'password' => 'password'
				]
			]
		]
	]);
}

loginAction – ログイン処理を行うコントローラーとアクションを指定
loginRedirect – ログイン後に移動するコントローラーとアクションを指定
logoutRedirect – ログアウト後に移動するコントローラーとアクションを指定
authenticate – 認証の詳細設定
 Form:ユーザーID、パスワードを入力するフォームを作成して認証処理をさせるタイプ。他にはBasicやDigestがあります。
  userModel:認証に使用するモデルを指定(デフォルトはUsers)
   fields:認証に使用するカラムを指定(デフォルトはusernameとpassword)

■ログインフォーム(index.ctp)、認証処理(LoginController.php)

LoginController.php

	public function initialize() {
		// AppControllerのAuthを継承
		parent::initialize();
	}	

	// ログインフォームとログイン処理
	public function index() {
		$this->loadModel("TUsers");
		$users = $this->TUsers->newEntity();
		if($this->request->is('post')) {
			$users = $this->TUsers->patchEntity($users, $this->request->data);
			$user = $this->Auth->identify();

			if($user) {
				$this->Auth->setUser($user);
				$this->redirect($this->Auth->redirectUrl());
			} else {
				echo "ログインエラーだよ";
			}
		}
	}

index.ctp

<?= $this->Flash->render() ?>
<?= $this->Form->create('Users') ?>
User<?= $this->Form->text('account') ?>
Password<?= $this->Form->password('password') ?>
<?= $this->Form->button('login') ?>
<?= $this->Form->end() ?>

■ユーザーの表示、追加、編集など
コントローラーに継承用の一文を追記します。
これがないとログイン後でもログインフォームに飛ばされちゃいます。

TUsersController.php

	public function initialize(){
		// AppControllerのAuthを継承
		parent::initialize();
	}

ユーザ作成、編集時にパスワードをハッシュ化させる。

Model/Entity/TUser.php

namespace App\Model\Entity;

use Cake\ORM\Entity;
use Cake\Auth\DefaultPasswordHasher;// ハッシャー
class TUser extends Entity
{
	protected function _setPassword($password){
		if (strlen($password) > 0) {
			return (new DefaultPasswordHasher)->hash($password);
		}
	}
}

こうやって書くと単純だけど結構苦戦しました。
AppControllerに書きましたけど、コントローラー単位でやる方法は分かりません(w

XAMPPでCakePHP3

XAMPPでCakePHP3

ポータブルタイプだとパスの問題でなんかうまくいかない。
うちはUSBにポータブルタイプのXAMPPを入れてたのでそれにCakePHP3を入れようとしたけど駄目だった。
(各モジュールがあるのに読み込めないエラーが大量発生)

ということで別ドライブにXAMPPを入れてそこで実行

ブラウザからアクセスするとエラー

Fatal error: You must enable the intl extension to use CakePHP ~~~

PHPの設定でintlを使用する設定になっていないかも。

php.iniを開いて下記を修正

;extension=php_intl.dll
↓↓↓↓↓↓↓↓↓↓↓↓
extension=php_intl.dll

これでApachを再起動

これで直るかな。

タイムゾーン変更でエラー

config/app.php
config/bootstrap.php

上記のtimezoneを変更するとMySQLでエラーが発生

Error: SQLSTATE[HY000]: General error: 1298 Unknown or incorrect time zone: ‘Asia/Tokyo’

下記の公式サイトよりtimezoneのファイルをダウンロードします。
http://downloads.mysql.com/general/timezone_2016a_posix.zip

/xampp/mysql/data/mysql にファイルを上書きします。
その後MySQLを再起動

これでCakePHP3も動くようになったかな。

【EC-CUBE2】非公開カテゴリーの作成

一部カテゴリーを非表示としたい(特別会員専用ページのようなもの)

要件は下記のような感じ
・カテゴリーID指定であれば一覧を表示
・全商品一覧には表示しない
・キーワード検索では表示しない
・対象カテゴリーの一覧、商品にはmetaタグで検索エンジンにindexされないようにする。
・カテゴリー一覧に表示されないようにする

■検索処理の修正
修正ファイル
/data/config/config.php
/data/class/pages/products/LC_Page_Products_List.php

▼config.php

ここに会員専用カテゴリーの値を設定する。
配列をsirialize化した値を設定する。

# 非公開カテゴリ(sirializeで指定)
define("Special_Category_ids", 'a:1:{i:0;i:37;}');

カテゴリーIDが10の場合は下記の配列になる。
array(0=>10);
これをsirialize化すると上記のような値になります。

▼LC_Page_Products_List.php

404行目のlfGetSearchConditionメソッドに処理を追加します。
下記の処理に追加します。

list($searchCondition['where_category'], $searchCondition['arrvalCategory']) = SC_Helper_DB_Ex::sfGetCatWhere($arrSearchData['category_id']);


// カテゴリからのWHERE文字列取得
if ($arrSearchData['category_id'] != 0) {
	list($searchCondition['where_category'], $searchCondition['arrvalCategory']) = SC_Helper_DB_Ex::sfGetCatWhere($arrSearchData['category_id']);
// 全商品一覧の場合、特定カテゴリーを表示しない
} else {
	$searchCondition['where_category'] = "category_id NOT IN (?)";
	$searchCondition['arrvalCategory'] = unserialize(Special_Category_ids);
}

これで全商品一覧、キーワード検索で対象商品が出てこなくなります。

■カテゴリー一覧の修正
カテゴリが自動生成されるので生成されないように処理を追加
/data/Smarty/templates/default/frontparts/bloc/category.tpl
/data/Smarty/templates/sphone/frontparts/bloc/category.tpl

必要あればガラケーのテンプレートも修正
/data/Smarty/templates/mobile/frontparts/bloc/category.tpl

まずはconfig.phpに設定したカテゴリーIDの値をテンプレートに渡します。
* 29行目付近の</script>の後に追記

<!--{php}--> 
	$this->assign("Special_Category_ids", unserialize(Special_Category_ids)); 
<!--{/php}-->

指定カテゴリーでなければ表示という処理を追加

<!--{if $arrTree[cnt].display == 1}-->の後ろにifを追加

<!--{if !in_array($arrTree[cnt].category_id, $Special_Category_ids)}-->
<!--{/if}-->の後ろに<!--{/if}-->で閉じる

下記のような感じ

<!--{* 表示フラグがTRUEなら表示 *}-->
<!--{if $arrTree[cnt].display == 1}-->
	<!--{*非表示カテゴリ以外であれば表示*}-->
	<!--{if !in_array($arrTree[cnt].category_id, $Special_Category_ids)}-->
		<!--{assign var=level value=`$arrTree[cnt].level`}-->
		<!--{assign var=levdiff value=`$level-$preLev`}-->
			<!--{if $levdiff > 0}-->
				<ul>
			<!--{elseif $levdiff == 0 && $firstdone == 1}-->
				</li>
			<!--{elseif $levdiff < 0}-->
				<!--{section name=d loop=`$levdiff*-1`}-->
						</li>
					</ul>
				<!--{/section}-->
				</li>
			<!--{/if}-->
		<li class="level<!--{$level}--><!--{if in_array($arrTree[cnt].category_id, $tpl_category_id)}--> onmark<!--{/if}-->">
			<p>
				<a href="<!--{$smarty.const.ROOT_URLPATH}-->products/list.php?category_id=<!--{$arrTree[cnt].category_id}-->"<!--{if in_array($arrTree[cnt].category_id, $tpl_category_id)}--> class="onlink"<!--{/if}-->><!--{$arrTree[cnt].category_name|h}-->(<!--{$arrTree[cnt].product_count|default:0}-->)</a>
			</p>
		<!--{if $firstdone == 0}--><!--{assign var=firstdone value=1}--><!--{/if}-->
		<!--{assign var=preLev value=`$level`}-->
	<!--{/if}-->
<!--{/if}-->

■metaタグの埋め込み
/data/Smarty/templates/default/site_frame.tpl

以下のコードを埋め込み

<!--{*非表示カテゴリの配列を取得&設定 *}-->
<!--{php}--> 
	$this->assign("Special_Category_ids", unserialize(Special_Category_ids)); 
<!--{/php}-->

<!--{if $arrSearchData}-->
	<!--{if in_array($arrSearchData.category_id, $Special_Category_ids)}-->

		<meta name="robots" content="noindex,nofollow">

	<!--{/if}-->
<!--{/if}-->

<!--{if $arrRelativeCat}-->
	<!--{section name=r loop=$arrRelativeCat}-->
		<!--{section name=s loop=$arrRelativeCat[r]}-->
			<!--{if in_array($arrRelativeCat[r][s].category_id, $Special_Category_ids)}-->

				<meta name="robots" content="noindex,nofollow">

			<!--{/if}-->
		<!--{/section}-->
	<!--{/section}-->
<!--{/if}-->

以上です。