ブログ復帰 新年のご挨拶

新年あけましておめでとうございます。

昨年、夏頃にとある案件で、wordpressのテストがてら自分のブログをアップデートしたところ、管理画面のすべてのjavascriptが全滅して投稿が一切出来なくなる状態に陥り、その後は多忙のため、自分のブログに関してはずっと放置していました。

さらに年末にサーバのphpをアップデートしたところ、メールサーバーが死んだので心機一転として新しいサーバーを借り、そこへ環境構築し、新たな年を新たな環境で迎えることにしました。

見た目はそのままですが、中身は新たにこれからまたブログは再開しようと思っています。

本年もどうぞよろしくお願いいたします。

[Concrete5]上級権限モードとは別に、テーマ側でユーザ判別したい時。

昨日Concrete5部で上級権限モードの話をしていたので、僕も何か書こうと思います。

上級権限モードは、ページの編集権限から、個別のエリアの編集や追加権限など、非常に事細かに設定ができるすぐれものなのですが、設定が非常に大変です。権限の設定だけでひと財産築けるんじゃないかなって思うくらい大変です。ジョークです。

そして、今回は上級権限モードとは関係の無い話でした。

一体なにがしたいのか

下記のコードを実際に使っているのですが、一体何をしようとしているのか。
「編集モードだったら+ユーザーがadminだったら、エリアを表示する」
という書き方をしています。

理由は以下の通り

  • スマホ版のテーマが別にある(レスポンシブではない)。
  • スマホ版の編集もPCで行う。
  • PCとスマホで表示する内容が異なる。
  • このエリアが編集できるのは、「admin」さんだけ。

つまり、レスポンシブではなく、モバイル用のテンプレートを別で用意していて、それぞれに別の情報を表示したい、でもエリアを表示できるのはadminさんだけに限定したい、というとてもニッチな状況で下記のコードで対処しました。

PC側のテンプレート

/themes/pc/elements/header.php
<?php
if ($c->isEditMode() && $u->getUserName() == 'admin') {
global $c;
$a = new GlobalArea('sp area');
$a->display($c);
} else {
} ?>

スマホ側のテンプレート

/themes/sp/elements/header.php
<?php
$a = new GlobalArea('sp area');
$a->display($c);
?>

それで、できたあとに気づいたのですが、ブロックテンプレートにmobile_detectを使うとか、そもそもadminさんしか編集できないならテーマにハードコーディングしてしまえばよかったなと思いました。

追記

ツイッターでacliss19xxさんから教えてもらいました!

「admin」さんだけだったら、スーパーユーザーだけって書いた方がいいですね。

PC側のテンプレート

/themes/pc/elements/header.php
<?php
if ($c->isEditMode() && $u->isSuperUser()) {//←ここ
global $c;
$a = new GlobalArea('sp area');
$a->display($c);
} else {
} ?>

[Concrete5]ログイン時のアップデート画面を非表示に

バージョン5.6.x
Concrete5はログイン時に、アップデート画面が表示されますが、お客さんに納品後に消して欲しいという要望をいただきまして。
重要な情報が載っていることもあるので、あまり消さない方がいいんですが、消し方はありまぁす。

/config/site.phpに一行追加するだけ。

define('ENABLE_NEWSFLOW_OVERLAY', false);

こんな感じ。

[Mac]メッセージ.appでFacebookメッセージを使う

Facebookメッセージのあの「ぽろんっ♪」って通知音がきらいです。

いや、冗談はさておき、FacebookのメッセージはブラウザとiOS/Androidで利用できるから便利だよねーって思ってたんですが、集中して仕事しているときに「ぽろんっ♪ぽろんっ♪ぽろんっ♪ぽろんっ♪ぽろんっ♪ぽろんっ♪」って来ると、資料用に開いているブラウザタブを切り替えたり、メッセージ用のタブを別ウインドウに分けて最小化しておいたりして、Facebookページをわざわざ開かなければならない状況に陥って、便利なはずが逆に自分の行動をFacebookメッセンジャーに支配されているようで逆に非効率的なのかと思い始めてきました。

スマホアプリみたいな、ブラウザを使用しないものはないのか

AppStoreを覗いたら、いくつかアプリはありました。

これらのアプリを購入して使用すればブラウザのリソースをFacebookに割く必要がなくなるのでこの記事は終了なんですが、個人的にはすでにSkypeとメッセージ.appを常駐起動させているので、さらにもう一つメッセージアプリを起動させるのもなんだかなーって気分です。

Skypeかメッセージ.appで使えないか

正直なところ、いつも使ってるSkypeかメッセージ.appで使えたら楽です。使い慣れているのもあるし。

SkypeはFacebook

最近のSkypeはデフォでFacebook連携機能がついているので、Facebookアカウントのメアドとパスワードを入れればすぐに使えるようになります。

うーん広告が邪魔だなぁ。。

メッセージ.appで使う

Skypeは簡単に使えるけど、タイムラインにかなり大きいバナー広告が出てきて創作意欲が萎えるので、Macのデフォルトでついているメッセージ.appを使おうと思います。
メッセージも結構簡単に設定できます。

1.メッセージの環境設定をひらいて、「アカウント」を選択します。

2.アカウントを追加(左下にある「+」をクリック)

3.アカウントの種類を、「その他のメッセージアカウント」を選択

4.「Jabber」を選択

5.アカウント名にFacebookアカウント名に「@chat.facebook.com」をくっつけたアドレスを入力。パスワードはFacebookのパスワードを入力。サーバやポートはそのままで大丈夫みたいです。

以上。これで、Facebookメッセージがメッセージ.appで使用できるようになりました。

ただ、通常のMMS(iMessage)のように画像ファイルを送る事はできないようです。

[追記]
ちょっと使ってみてわかったのですが、facebookのメッセンジャーでやり取りしたチャットの自分の投稿はメッセージ.appに反映しないようです。もう諦めて専用アプリ買ったほうがいいかもしれません…。

[Concrete5]ログイン時や編集モード時で表示を切り替えよう[メモ]

バージョン:5.6.3.1

自分用メモ的な。

ログインしている or していない

ログインして”いる”時だけ表示

ログインは登録ユーザーしかできないので、クライアントへのメモ的な扱いで残しておくような用途で使えます。

<?php
$u = new User();
if ($u->isRegistered()) { ?>
ここに書いたものはログインして"いる"時だけ表示されます
<?php } ?>

ログインして”いない”時だけ表示

ログインしていない時なので、一般のユーザーが閲覧する際にだけ表示するものを指定できます。
あんまり意味がないと思われますが、最近使いました。

<?php
$u = new User();
if (!$u->isRegistered()) { ?>
ここに書いたものはログインして"いない"時だけ表示されます
<?php } ?>

編集モード or 非編集モード

編集モード時だけ表示

以前、[Concrete5]エリア内にブロックがある時にだけ表示する[メモ]でも使用しました。
編集モード時だけに表示したいものは結構あります。編集時にはヘッダーにメニューバーが表示されるので、メニューバー分の余白を開けるのにもデフォルトのテーマで設定されていますよね。

<?php if ($c->isEditMode()) { ?>
ここに書いたものは編集モード時だけ表示されます
<?php } ?>

非編集モード時だけ表示

編集モードで見えず非編集モードで見えるということは、編集モードでどう頑張っても消したりできないという、クライアントの混乱の元になるのでやめましょう。

<?php if (!$c->isEditMode()) { ?>
ここに書いたものは非編集モード時だけ表示されます
<?php } ?>

[EC-CUBE + Concrete5] ECキューブの商品情報をConcrete5で利用する

タイトル通りですが、もうちょっと詳しく説明しますと、
「ECキューブに商品登録されている商品情報をxmlで取得してきて、Concrete5の編集でブロックに個別の商品IDを入力すると表示する」といった感じでしょうか。
ECキューブのページ作成機能がお客さんには使いづらいという感想だったので、Concrete5で編集・商品リストの作成は任意で行ってもらうようにしました。

バージョン:
ECキューブ 2.13.3
Concrete5 5.6.3.1

ECキューブAPIの取得方法については、下記のサイトを参考にさせていただきました。
EC-CUBEのAjax APIを使う(2) −−− 商品情報取得

なお、今回は同一サーバー、同一ドメイン内にECキューブとConcrete5をインストールしています。

ECキューブのAPIを使う

ECキューブには最近のバージョンでAPI機能が追加されたので、APIを利用して商品情報を取得できるようにします。

管理画面の「システム設定>パラメーター設定」にある「API_ENABLE_FLAG」を「true」にします。

xml.php

ECキューブのAPIは以下のURLでリクエストが送れます。

https://ドメイン/api/出力フォーマット.php

出力フォーマットは、JSONとxmlとphpの三種類あります。
今回はxmlを使用しました。

https://ドメイン/api/xml.php

これだけだと、下記のようにFalseが返ってきてなにも表示することができませんので、パラメータを設定する必要があります。

パラメータを含めたリクエストURL

https://ドメイン/api/xml.php?Operation=ItemLookup&Service=abc&ItemId=商品ID

Operation オペレーションの種類を指定します
Service 指定しないとエラーになります。ただし何も使われていないので適当な値を入力すれば大丈夫

Operationの種類は多数あるのですが、今回は「ItemLookup」を使用しました。
ItemLookupは、商品IDをキーに、商品詳細情報を取得します。商品IDは「ItemId」へ入力します。

これで商品情報の取得が可能です

Concrete5での設定 Desginer content

Concrete5側では、お客さんに商品IDを入れてもらうだけにするために、「Designer content」アドオンを利用します。
インストール方法などは省きます。

Designer contentで、新しいブロックを作成します。

Block Handleとブロック名は任意で、Add Fieldから「Text Box」を選択し、「Editor Label」に「商品ID」と入力。ダッシュボードでのDesigner contentで行う作業はこれだけです。

作成したブロックをカスタマイズ

Designer contentで作成したブロックのフロントテンプレートは、コンクリインストールフォルダの「/blocks/」ディレクトリ内に作成されます。
上記の例だと「/blocks/product_item」というディレクトリができているかと思います。
この中にあるview.phpがフロントテンプレートになります。

view.phpには以下のphpが書かれていますので、これをどうにかして商品情報を表示するように設定します

<?php  defined('C5_EXECUTE') or die("Access Denied.");
?>

<?php  if (!empty($field_1_textbox_text)): ?>
	<?php  echo htmlentities($field_1_textbox_text, ENT_QUOTES, APP_CHARSET); ?>
<?php  endif; ?>

「echo htmlentities($field_1_textbox_text, ENT_QUOTES, APP_CHARSET);」が、ブロックに入力された文字を表示するので、ここに商品IDを入力してもらっていれば、phpからxmlへリクエストを送る際の必要な商品IDをそのまま利用できるということになります。

<?php
$productID = htmlentities($field_1_textbox_text, ENT_QUOTES, APP_CHARSET); //編集画面で入力された商品ID
$xml = simplexml_load_file('/api/xml.php?Operation=ItemLookup&Service=abc&ItemId=' . $productID); //APIへのリクエスト


xmlから必要な情報を取り出して変数に入れる

<?php
$productURL = $xml->Item->DetailPageURL;
$productName = $xml->Item->Title;
$productThumb = $xml->Item->ItemAttributes->main_list_image;
$productPrice = $xml->Item->ItemAttributes->price02_max;
?>


htmlのマークアップはお好みでどうぞ。

<p class="item_image"><a href="<?php echo $productURL;?>"><img src="/upload/save_image/<?php echo $productThumb;?>" alt="<?php echo $productName;?>"></a></p>
<p class="checkItemname"><a href="<?php echo $productURL;?>"><?php echo $productName;?></a></p>
<p class="price"><em><?php echo $productPrice;?></em>円</p>

補足

ちなみに、同一ドメインでも、apiへのリクエストが「/api〜〜」になっていると「I/O warning : failed to load external entity」が出る事があったので、apiリクエストを「http〜〜」になるようにしました。

<?php
$domain = (empty($_SERVER["HTTPS"]) ? "https://" : "https://") . $_SERVER["HTTP_HOST"] ; //ドメイン取得
$productID = htmlentities($field_1_textbox_text, ENT_QUOTES, APP_CHARSET); //編集画面で入力された商品ID

$xml = simplexml_load_file($domain . '/api/xml.php?Operation=ItemLookup&Service=abc&ItemId=' . $productID); //APIへのリクエスト

[Concrete5 5.6.3.1]タイトルタグの表示を変えたい[メモ]

前回。ECキューブのタイトルタグの記事を書いてから気づいたのですが、このブログはConcreteg5が主な趣旨のブログでしたので、一応このブログを見る方は既にご存知かと思いますがタイトルタグの表示の変更方法を記載しておきます。

Concrete5のデフォルトだと「サイト名::ページ名」という形で表示されます。
やはり、昔だとそれでも問題なかったんですが、最近のブラウザはタブ表示でサイト名が先に表示されるとタブを見てもどこのページを開いているかわかりませんので、特別な理由(宗教上の理由とか)がない限り、ページ名を先に表示させた方が明らかにユーザビリティに優れていますよね。

バージョン:5.6.3.1

Concrete5のタイトルタグはsite.phpに記述することで変更が可能です。
※インストール直後だとデータベースの設定しか書いてないので、その下にdefine(‘PAGE_TITLE_FORMAT’, ”);を追記します。
/config/site.php

デフォルト

<?php
define('DB_SERVER', '*******');
define('DB_USERNAME', '******');
define('DB_PASSWORD', '******');
define('DB_DATABASE', '******');

「ページ名|サイト名」

<?php
define('DB_SERVER', '*******');
define('DB_USERNAME', '******');
define('DB_PASSWORD', '******');
define('DB_DATABASE', '******');

define('PAGE_TITLE_FORMAT', '%2$s|%1$s'); //←ここ

「ページ名」のみ

<?php
define('DB_SERVER', '*******');
define('DB_USERNAME', '******');
define('DB_PASSWORD', '******');
define('DB_DATABASE', '******');

define('PAGE_TITLE_FORMAT', '%2$s'); //←ここ

%1$sがサイト名、%2$sがページ名となります。

また、個別にタイトルタグを変えたい場合は、ページ設定の「カスタム属性」にある、「Metaタグタイトル」に入力することで変更可能です

ただし、カスタム属性の Metaタグタイトルに入力をした場合には、%1$sで出力されるサイト名も丸ごと置き換わりますのでご注意ください。

[ECキューブ 2.13.3]タイトルタグの表示を変えたい[メモ]

ECキューブのタイトルタグは、デフォルトだと「サイト名 / ページ名」という形で表示されます。
昔だとそれでも問題なかったんですが、最近のブラウザはタブ表示でサイト名が先に表示されるとタブを見てもどこのページを開いているかわかりませんので、特別な理由(宗教上の理由とか)がない限り、ページ名を先に表示させた方が明らかにユーザビリティに優れていますよね。

バージョン:2.13.3

ECキューブのタイトルタグは基本、テンプレートのsite_frame.tplに書かれています。
/data/Smarty/templates/default/site_frame.tpl

その中の27行目あたりにタイトルタグがありますので、中身をちょちょいといじれば大丈夫
※一行だとみづらいので改行しています

「サイト名 / ページ名」

<title>
<!--{$arrSiteInfo.shop_name|h}-->
<!--{if $tpl_subtitle|strlen >= 1}--> / <!--{$tpl_subtitle|h}-->
<!--{elseif $tpl_title|strlen >= 1}--> / <!--{$tpl_title|h}-->
<!--{/if}-->
</title>

「ページ名|サイト名」にしました。

<title>
<!--{if $tpl_subtitle|strlen >= 1}-->
<!--{$tpl_subtitle|h}-->|
<!--{elseif $tpl_title|strlen >= 1}-->
<!--{$tpl_title|h}-->|
<!--{/if}--><!--{$arrSiteInfo.shop_name|h}-->
</title>

中身のif文は管理画面でサブタイトルが設定されているときにページ名の代わりに表示するものです。
<!–{$arrSiteInfo.shop_name|h}–>がサイト名です。

[CSS]ブロックを上下左右中央に配置したい

ECサイトなんかだと、よくあるパターンなんですが、商品画像のトリミングが縦長だったり、横長だったりして、余白が気になるってお客さんに言われます。
トリミングが正方形だったらなんの問題もないんですが、ウェブに関わる全ての人が画像を正方形にトリミングできるはずもないので、それがどんなトリミングであっても美しく表示させるのがウェブデザイナーの仕事だと思います。

左右のセンタリングは簡単

text-align: centerを使って、左右中央は簡単にできます

<style>
div.LRbox {
  text-align: center;
  border: 1px solid #cacaca;
  width: 200px;
  height: 200px;
}
</style>

<div class="LRbox">
<img src="https://wordpress.go-designing.com/wp-content/uploads/2015/02/LR1.gif" alt="縦長の画像" width="150" height="200" />
</div>

縦長の画像

上下のセンタリングがめんどい

ダメな例

<style>
div.TBbox {
  vertical-align: middle;
  border: 1px solid #cacaca;
  width: 200px;
  height: 200px;
}
</style>
<div class="TBbox">
<img src="https://wordpress.go-designing.com/wp-content/uploads/2015/02/TB.gif" alt="横長の画像" width="200" height="150" />
</div>

横長の画像

上下の場合、vertical-align:middleを使っても中央によってはくれませんね。
要素名のせいで勘違いしやすいのですがvertical-alignは、ボックス内のインライン要素の高さ位置を揃えるのであって、ボックスの内部の位置を中央にするわけではないのです。

解決策

<style>
div.TBboxTrue {
  border: 1px solid #cacaca;
  width: 200px;
  height: 200px;
  position: relative; /* 親のボックスのpositionをrelativeに */
}
div.TBboxTrue img {
  position: absolute;  /* 上下中央にしたい要素のpositionをabsoluteに */
  top: 0; /* top位置を0 */
  bottom: 0; /* bottom位置も0 */
  margin: auto; /* marginをautoに */
}
</style>
<div class="TBboxTrue">
<img src="https://wordpress.go-designing.com/wp-content/uploads/2015/02/TB.gif" alt="横長の画像" width="200" height="150" />
</div>

横長の画像

応用

これを応用して、上下左右中央に指定しておくことができます。
たとえば、ボックスより大きい画像の場合は、max-widthやmax-heightを100%にしておくことで、ボックスから画像がはみ出てしまうことを回避できますが、そもそもボックスより画像が小さい場合は、上下左右中央に寄せることで対応するといいでしょう。

<style>
div.TBLRbox {
  border: 1px solid #cacaca;
  width: 200px;
  height: 200px;
  position: relative;
margin-bottom: 20px;
}
div.TBLRbox img {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
}
</style>
<div class="TBLRbox">
<img src="https://wordpress.go-designing.com/wp-content/uploads/2015/02/TBLR.gif" alt="ボックスより小さい画像" width="150" height="150" />
</div>

ボックスより小さい画像

[CSS] 〜戒め〜 display: inline-blockのブロック直下に、floatが掛かっているブロックを置いてはいけない

今週ずっと徹夜が続いておりまして、体力的にも精神的にも限界でした。
そのおかげで脳みそが全く働いていない状態でハマってしまった、いや、これは完全に油断ですね。
きっともうちょっと気を引き締めよとのお告げなのです。

デザイン的にタイトルにinline-blockを使いたかったんです。
で、その直下に画像と説明文をfloatしたかったんです。

下記の画像をごらんください。

赤のブロック、これがタイトルで、その下に左右のfloatブロックがある。
タイトルの幅は100%ではなくて、中途半端な感じにしたかったんですよ。デザイン的事情で。

そしたら、float: leftをかけたブロックがinline-blockの左に回り込むという事態に。
多分これは仕様通りの動きなんだろうけど、ちょっと納得いかないすね。

安易にinline-blockを使うなという戒めである。

ちなみにソースコードは以下。

<style>
body {
	background: #ededed;
	font-size: 14px;
}
div#column {
	width: 600px;
	margin: 0 auto;
	padding: 10px;
	background: #fff;
}

div#column h2.inline-block {
	display: inline-block;
	width: 300px;
	background: #FFBCBD;
	margin: 0 0 10px;
	font-size: 14px;
}

div#column h2.block {
	display: block;
	width: 300px;
	background: #FFBCBD;
	margin: 0 0 10px;
	font-size: 14px;
}

div#column h2.block span {
	font-weight: normal;
	font-size: 12px;
}

section {
	clear: both;

}

p {
	margin: 0;
}

div.boxL {
	display: block;
	width: 240px;
	float: left;
	background: #AFECFF;
}

div.boxR {
	display: block;
	width: 240px;
	float: left;
	background: #BFFFBD;
}

.clear {
	clear: both;
}

</style>


<div id="column">

<section>
<h1>想像していた表示</h1>
<h2 class="block">inline-blockでタイトル
<pre>
div#column h2.inline-block {
	display: inline-block;
	width: 300px;
	background: #FFBCBD;
	margin: 0 0 15px;
}
</pre>
<span>※表示のために、実際はdisplay: blockと書いています。</span>
</h2>

<div class="boxL">floatLボックス
<pre>
div.boxL {
	display: block;
	width: 240px;
	float: left;
	background: #AFECFF;
}
</pre>
</div>


<div class="boxR">floatRボックス
<pre>
div.boxR {
	display: block;
	width: 240px;
	float: left;
	background: #BFFFBD;
}
</pre>
</div>

</section>

<p class="clear">↓</p>


<section>
<h1>実際の表示</h1>
<h2 class="inline-block">inline-blockでタイトル
<pre>
div#column h2.inline-block {
	display: inline-block;
	width: 300px;
	background: #FFBCBD;
	margin: 0 0 15px;
}
</pre>
</h2>

<div class="boxL">floatLボックス
<pre>
div.boxL {
	display: block;
	width: 240px;
	float: left;
	background: #AFECFF;
}
</pre>
</div>


<div class="boxR">floatRボックス
<pre>
div.boxR {
	display: block;
	width: 240px;
	float: left;
	background: #BFFFBD;
}
</pre>
</div>
</section>


</div>

解決策は?

ちょっとあんまり良い方法ではないんだけれど、inline-blockがかかってる要素か、floatの要素どちらかを別のボックスで囲ってやればおk。
下記の例だとdivを余計にひとつ追加してます。

<section>
<h1>解決策1</h1>

<h2 class="inline-block">inline-blockでタイトル
<pre>
div#column h2.inline-block {
	display: inline-block;
	width: 300px;
	background: #FFBCBD;
	margin: 0 0 15px;
}
</pre>
</h2>

<div>
<div class="boxL">floatLボックス
<pre>
div.boxL {
	display: block;
	width: 240px;
	float: left;
	background: #AFECFF;
}
</pre>
</div>


<div class="boxR">floatRボックス
<pre>
div.boxR {
	display: block;
	width: 240px;
	float: right;
	background: #BFFFBD;
}
</pre>
</div>
</div>

</section>

 
 <section>
<h1>解決策2</h1>

<div>
<h2 class="inline-block">inline-blockでタイトル
<pre>
div#column h2.inline-block {
	display: inline-block;
	width: 300px;
	background: #FFBCBD;
	margin: 0 0 15px;
}
</pre>
</h2>
</div>

<div class="boxL">floatLボックス
<pre>
div.boxL {
	display: block;
	width: 240px;
	float: left;
	background: #AFECFF;
}
</pre>
</div>


<div class="boxR">floatRボックス
<pre>
div.boxR {
	display: block;
	width: 240px;
	float: right;
	background: #BFFFBD;
}
</pre>
</div>


</section>