(佐賀→熊本)マークアップエンジニアのググる生活

地方のWEB制作会社で働く、フロントエンドエンジニア。
HTML、CSS、JavaScript(jQuery)、PHP、Smary、EC-CUBE、WordPress、Movable Type等々で解らない時に、Googleで検索したら解決した話や、「閃いた!」などをほとんど自分用にメモとして残すブログです。

※URLがあったら元記事を参照推奨です!
※ほとんどの事は検証はしていますが、あくまでも参考程度にお願い致します!
※記載が不正確であったことにより生じたいかなる損害に関しても、当ブログは責任を負いかねます。自己責任でよろしくおねがいいたします。

元ネタ ( 2.11 ) :
http://xoops.ec-cube.net/modules/newbb/viewtopic.php?viewmode=flat&order=ASC&topic_id=4787&forum=7

上記をそのままだと 2.13 にて動かなかったので getMode() 関数を追ってみると、
mode を $_REQUEST['mode'] で判断していたので、それを追記したら下記ようになりました。


//**
 * Page を初期化する.
 *
 * @return void
 */
function init()
{
    parent::init();

    /**
     * [カスタマイズ] ページ表示時、「この条件で検索する」ボタンと同じ動作をする
     */
    if ( !isset( $_REQUEST['mode'] ) ) : $_REQUEST['mode'] = "search"; endif;
    if ( !isset( $_POST['mode'] ) ) : $_POST['mode'] = "search"; endif;
    if ( !isset( $_POST['search_page_max'] ) ) : $_POST['search_page_max'] = SEARCH_PMAX; endif;
}


この PHP を追記するファイル
  • LC_Page_Admin_Customer_Ex.php
  • LC_Page_Admin_Mail_Ex.php
  • LC_Page_Admin_Order_Ex.php
  • LC_Page_Admin_Products_Ex.php
  • LC_Page_Admin_Products_Review_Ex.php

スマホからMacに立てたgulp-webserverに接続する
http://qiita.com/wamei/items/fe4c4c1b3d68581b42f5

↑の Windows 版がやりたかったけど、
インターネット共有機能ってのがちょっと分からなかったので、
ググりましたがやっぱりイマイチわからず!
(ネットワーク系さっぱりです...)

ついでにパソコンは有線、スマホはwifiなのでちょっと手間取ったのかもしれない。

gulp.js は mac の方と同じでよかったです。
host は localhost だとダメだったので、0,0,0,0 にするとOK。

肝心のスマホからのアドレスは、
  1. ネットワークと共有センター
  2. 接続
  3. 詳細
  4. IPv4 アドレス



から確認出来ました。

確認バージョン 2.12.2

dtb_category の rank が並び順に超影響しているようで、
parent_category_id とか level とか関係なしに
rank の降順で並ぶようです。

管理画面からはちょっと厳しいので、
データベースから rank を整理してあげると正常になりました。

※メモも兼ねて長文です。



言葉は何となく知っていた VPS ですが、
このたびようやく(?)触れる機会がありました。

お仕事にて「さくらVPS」にて構築された EC-CUBE を
VPS の知識が特に無い私に引き継がれました。
社外案件(&担当者が退職)で聞ける人もいなかったので不安でした。

しばらくは管理画面上からの操作で事足りてましたが、
<title> タグの書き換えなど、ファイルを直接書き換える必要がでてきました。
いつも通り FTP クライアントから編集しようかと思いましたが、
ファイル権限が違うとの事で、上書き等ができませんでした。

どうやら さくらVPS の方にて操作をしないといけないと気付き、
挑戦した次第です。



https://secure.sakura.ad.jp/vps/#/login
まずは さくらVPS に WEB からログインしました。

サーバ一覧がでてくるので、対象のサーバーを選択…
するとサーバー情報や、起動・強制再起動・強制停止・コンソールなどの
操作可能なボタンがでてきます。

起動・強制再起動・強制停止などは基本的に押さないようですね。

その後、コンソールをクリックしました。
すると、HTML5版・Java Applet版・β版とさらに分かれてきます。
私は Firefox から試したのですが、 Java Applet版 は起動しなかったので、
HTML5版 を選びました。(β版はなんか敷居が高そうだったのでやめました…)

いわゆる黒い画面が別ウィンドウで立ち上がります。
とりあえずログインをしないといけないみたいなのでログインします。
最初なので root でログインしました。

当初はなるほど~ここからパス移動して編集していくのかな?と思い、
ググった情報を基に vi コマンドで目的のファイルを編集モードにするところまでは行けました。
しかし、困ったことに日本語の入力がさっぱりわからず、
ついでにコピペもできない様で…お手上げてしまいました。



やり方を再度ググったところ、
SSH クライアントでログインしなければならないという情報にたどり着きました。

私は Windows ユーザーなので、さっそく Teraterm を起動し、
公式マニュアルやググった情報通りに SSH 接続を試みましたが、
接続が拒否されました(だったかな?)とアラートが出て、失敗しました。

エラーを基にググってみると、
SSH の設定ファイルを確認してみる必要があるとのことでした。

さっそく vi /etc/ssh/sshd_config とコマンドを入力すると
AuthorizedLeysFile や Port などなどの情報がでてきました。

ここでポート番号が 通常は 22 らしいのですが、
セキュリティ対策で独自に変更されていることがわかりました。
得た情報を基に再度 SSH クライアントを設定して接続を試みました。

ところが、これでも接続ができませんでした。
しばらくこの症状ではまり…、

こちらもセキュリティで root ユーザーでは SSH クライアントからの
接続ができない事が分かりました…。



どうやら先にユーザーを追加しなければいけないという状況がわかりました。

ユーザーの追加の仕方は、公式マニュアルに載っていました。
https://help.sakura.ad.jp/app/answers/detail/a_id/2428/~/%E4%B8%80%E8%88%AC%E3%83%A6%E3%83%BC%E3%82%B6%E3%81%AE%E8%BF%BD%E5%8A%A0%E6%96%B9%E6%B3%95

# useradd ***
# passwd ***
※「***」は、お客様が追加するユーザ名のため任意の文字列です。

と記載があり、
なるほど~ useradd には admin、 passwd には password と入れるのかな?
(※入力値の admin password は例です)
と思いこみ入力したのですが、 マニュアル通りに先へ進まず、ちょっと考え込んでしまいました。

するとなんと useradd と passwd は追加したいユーザ名を入力するとのことで、
useradd admin
passwd admin
とする必要がありました orz

その後、New password: と聞かれるので、ここで初めてパスワードを入力できます。
all authentication tokens updated successfully.
と表示されると成功の様で、一安心。

確認の為にユーザーを切り替えてみます。
切り替えコマンドがわからなかったので、ググりました。
http://linux.just4fun.biz/%E9%80%86%E5%BC%95%E3%81%8DUNIX%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89/%E3%83%A6%E3%83%BC%E3%82%B6%E3%81%AE%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88%E3%82%92%E8%A1%8C%E3%81%86%E6%96%B9%E6%B3%95%E3%83%BBsu%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89.html

どうやら、 su または su - を使うようですね。
su - admin
とすると、Password: と聞かれたので、入力すると、
[root] だったのが [admin] と切り替わったので、成功のようです!



さて再度 admin ユーザーにて SSH クライアントで接続を試みます。
しかし今回もまたダメでした orz

しばらくいろいろな情報をにらめっこしていると
/etc/ssh/sshd_config の際に、
passwordAuthentication という項目が目に留まりました。

passwordAuthentication をそのままググってみると、
パスワード認証 をするか?しないか?の設定のようです。

ここが no になっており、接続できなかったようです。

ユーザーが admin のままだったら、root でログインしなおして、
vi /etc/ssh/sshd_config
を実行し、 passwordAuthentication no を passwordAuthentication yes に書き換え、
:qw コマンドで上書き保存します。
書き換えた設定を認識させるには SSH を再スタートさせないといけないならしく、
/etc/init.d/sshd restart
とコマンドを実行します。成功すると OK がでます。



これでやっと admin ユーザーにて SSH クライアントからの接続ができるようになりました…。
さっそく vi コマンドで目的のファイルを編集します。

コピペできる!!日本語入力できる!!いいですね~…

:wq で上書き保存、、、と思ったのですが、
書き込み用にファイルを開けませんなどと怒られてしまいました。

これもググってみると、 admin ユーザーの力では、
root で制作したファイルに対して上書き等ができないようでした。

そこで、 SSH クライアントには admin で接続し、
su - コマンドで root に切り替え後、
vi コマンドで目的のファイルを編集するという手順が必要でした。

以上で、無事上書き保存ができ、更新ができました。



最後に、passwordAuthentication yes
のままだとセキュリティ的によろしくないらしく、
鍵認証を作った後に no にしておくとよいとのことだったので、次はそうしてみます。

バージョン 2.13.5
にて確認しました。TOP_URL などの定数が使えるバージョンならば他でも大丈夫だと思います。

<meta property="og:url" content="http://www.yahoo.co.jp/">
<link rel="canonical" href="http://www.yahoo.co.jp/">

これを自動で出したい。




LC_Page_Ex.php

修正 [2016/02/25] - strpos で調べる値が空だったら PHP の Warning が出ないようにいたしましたm(_ _)m

/**
 * URLを返却
 *
 * @param string 分岐したい mode を入力 ( 'canonical' | 'ogp' )
 * @return string パラメーターが整理された URL を返却
 */
public function customPublishUrl($mode)
{
    $protocol    = ( empty($_SERVER['HTTPS']) ? 'http://' : 'https://');
    $http_host   = $_SERVER['HTTP_HOST'];
    $request_uri = $_SERVER['REQUEST_URI'];
    $script_name = $_SERVER['SCRIPT_NAME'];
    $top_url     = TOP_URL;
    $dynamic_url = $protocol . $http_host . $request_uri;
    $static_url  = $protocol . $http_host . $script_name;

    // 出力用
    $publish_url = $static_url;
    $param_all   = '';

    // URL から 不要なファイル名を調査
    if (
           strpos( $script_name, 'index.php' ) !== false
        || strpos( $script_name, 'confirm.php' ) !== false
        || strpos( $script_name, 'complete.php' ) !== false
       ) :

        // トップページならば
        if ( $static_url === $top_url || $static_url === $top_url . 'index.php' ) :
            $publish_replace = '';
            $publish_search  = '/\/index.php/u';

        // それ以外のページ
        else :
            $publish_replace = '';
            $publish_search  = '/index.php|confirm.php|complete.php/u';
        endif;

        // 不要なファイル名を削除する
        $publish_url = preg_replace($publish_search, $publish_replace, $publish_url);

    endif;

    // パラメーター算出用の URL を綺麗にする
    $clean_url     = $dynamic_url;
    $clean_search  = '/\"(.*)\"|\'(.*)\'|%22(.*)%22/u';
    $clean_replace = '';
    $clean_url     = preg_replace($clean_search, $clean_replace, $clean_url);

    // パラメーターを配列化
    $hatena = explode('?', $clean_url);
    $and = explode('&', $hatena[1]);

    // チェックするパラメーター
    switch ( $mode ) :

        // $check_pattern
        // 'only'   -&gt; URL に含まれるパラメーターを配列だけにする
        // 'remove' -&gt; 配列のパラメーターは不要なので URL から必ず除外する

        case 'canonical' :
            $check_pattern = 'only';
            $check_array   = array('category_id', 'maker_id', 'name', 'product_id');
            break;

        case 'ogp' :
            $check_pattern = 'remove';
            $check_array   = array('transactionid', 'admin');
            break;

    endswitch;

    // $hatena が空で無ければ
    if ( $hatena[1] !== '' ) :

        // パラメーター配列の数だけループ
        foreach ( $and as $each ) :

            $each_split = explode('=', $each);
            $param = $each_split[0];
            $value = $each_split[1];
            $flag = ( $check_pattern === 'only' ) ? false : true;

            // $check_array の数だけループ
            foreach ( $check_array as $each2 ) :

                // strpos で調べる値が空だったら PHP の Warning が出るので事前に $param_all をチェック
                if ( $param_all !== '' ) :

                    // 値の重複を調査( $param_all が $param を含んでいたら フラグを無くす )
                    if ( strpos( $param_all, $param ) !== false ) :
                        $flag = false;
                    endif;

                endif;

            endforeach;

            // 値の重複を調査( $param_all が $param を含んでいたら フラグを無くす )
            if ( strpos( $param_all, $param ) !== false ) :
                $flag = false;
            endif;

            // $flag が true なら $param_all に $each を追加
            if ( $flag ) :
                $param_all .= ( $param_all === '' ) ? '?' . $each : '&' . $each;
            endif;

        endforeach;

    endif;

    // もし $param_all の値が ? だけだったら $param_all を空にする
    $param_all = ( $param_all === '?' ) ? '' : $param_all;

    // ただし $mode が canonical かつ パラメーターに pageno を含んでいたら $publish_url と $param_all を空にする
    if ( $mode === 'canonical' && strpos( $clean_url, 'pageno=' ) !== false ) :
        $publish_url = '';
        $param_all = '';
    endif;

    return $publish_url . $param_all;
}




呼び出し
LC_Page_Ex.php

修正 [2016/02/24] - init() から process() に変更しましたm(_ _)m

/**
 * Page のプロセス.
 *
 * @return void
 */
public function process()
{
    parent::process();

    /**
     * 下記はシステムエラー時無視されるので、
     * ・LC_Page_Error.php
     * ・LC_Page_Error_DispError_Ex.php
     * ・LC_Page_Error_SystemError_Ex.php
     * にて再取得する
     */
    
    // og:url
    $this->custom_ogurl = $this->customPublishUrl('ogp');

    // カノニカルURL
    $this->custom_canonical = $this->customPublishUrl('canonical');
}




LC_Page_Ex.php
だけだとエラー時に空になっちゃうので、
・LC_Page_Error.php
・LC_Page_Error_DispError_Ex.php
・LC_Page_Error_SystemError_Ex.php
でも呼び出す

/**
 * Page のアクション.
 *
 * @return void
 */
function action()
{
    parent::action();

    /**
     * LC_Page_Ex.php にて定義
     */

    // og:url
    $this->custom_ogurl = LC_PAGE_Ex::customPublishUrl('ogp');

    // カノニカルURL
    $this->custom_canonical = LC_PAGE_Ex::customPublishUrl('canonical');
}




出力
site_frame.tpl

<!--{if $custom_canonical|strlen <= 1}--><meta name="robots" content="noindex, follow"><!--{/if}-->
<meta property="og:url" content="<!--{$custom_ogurl|h}-->">
<!--{if $custom_canonical|strlen >= 1}--><link rel="canonical" href="<!--{$custom_canonical|h}-->"><!--{/if}--><!--{strip}-->



最近の SEO 系のブログ記事の傾向を見て、
canonical を出さないようにしているページがあります(ページネーションが発生するページ)。
そこでは、代わりに noindex follow を入れるようにしています。



※ここまで書きましたが、
独自ロジックを EC-CUBE 全体に反映させるにはどこで呼び出したらいいんだろう。
反映箇所が多いと漏れがあると思うし、決済モジュールなどでは、モジュールごとに追記が必要になるので...。
ググっても個々のページ用の情報ばかりなので、よくわかりませんでした。勉強します。

min-height - CSS | MDN
https://developer.mozilla.org/ja/docs/Web/CSS/min-height

min-height の初期値は「0」ですが、
最近のブラウザでは「auto」でもなるようです。

私のwindows10のfirefox、chrome、IE11、Microsoft Edgeでは、
「auto」でも有効でしたが、
iPadで確認したときに値が認めてもらえず無効になっていました。

やはりきちんと仕様通りに書かねばなりませんね。

ボクは boxer という jQuery プラグインが好きで、よく利用させてもらってます。

便利でクールですが、

閉じる動作が PC だとESCキーか、×ボタンしかありません!
タッチデバイスだとそれこそ×ボタンのみ…。

追記(2015/11/27)
オプションで mobile: true を付けると、
画像外クリックで閉じるが効かないだけ…ということでした…!

なので、 mobile: true を付与した用に追記致しました。

それだけだとちょっと面倒な感じがするので、
画像とテキストと他のボタン以外をクリック or タップした時に閉じるように追加してみました。

ミニファイ化されていないプラグインjsを編集します。

下記の関数を追加します。
どこでもいいと思いますが、
ボクは @name onKeypress のあとに追加しました。

  /**
   * @method private
   * @name onClickbody
   * @description #boxer or .boxer-container or .boxer-content Click for .boxer-close click trigger
   * @param e [object] "Event data"
   */
  function onClickbody(e) {
    var boxer_class = $('#boxer').attr('class');
    var target = $(e.target);
    var target_id = target.attr('id');
    var target_class = target.attr('class');
    if ( 
        boxer_class === 'mobile' &&
        (
             target_id === 'boxer'
          || target_class === 'boxer-container'
          || target_class === 'boxer-content'
        )
       ) {
      data.$boxer.find(".boxer-close").trigger("click");
    }
  }


そのあとに上記関数を動作させるために、
下記のイベントハンドルを追加します。
data.$body.on("touchstart.boxer click.boxer", "#boxer-overlay, #boxer .boxer-close", onClose)
の下あたりがいいかなーとは思います。

      data.$body.on("touchstart.boxer click.boxer", onClickbody);


これで完了です!

ミニファイ化はGoogleお手製のsimpleモードなら大丈夫でした。
プラグインのライセンスコメントをお忘れなく!

http://closure-compiler.appspot.com/home

register_post_type の supports にて、

'editor' => true,

という記述をしていたら wp_footer() で生成される管理バーが表示されなくなった
エラー等がさっぱり出なかったので全く分からず悩んでしまいました。

 => true, を消すと正常になりました。

バージョン 2.13.4

/data/Smarty/templates/default/frontparts/bloc/category_tree_fork.tpl

kaihei






















<ul class="js-menu-slide" <!--{if $treeID != ""}-->id="<!--{$treeID}-->"<!--{/if}--> style="<!--{if !$display}-->display: none;<!--{/if}-->">
    <!--{if isset($child.children|smarty:nodefaults)}-->
        <li class="level<!--{math equation="1 + level" level=$child.level}--><!--{if in_array($child.category_id, $tpl_category_id)}--> onmark<!--{/if}-->">
            <a href="<!--{$smarty.const.ROOT_URLPATH}-->products/list.php?category_id=<!--{$child.category_id}-->"<!--{if in_array($child.category_id, $tpl_category_id)}--> class="onlink"<!--{/if}-->><!--{$child.category_name|h}-->のすべて<span class="u-n">(<!--{$child.product_count|default:0}-->)</span></a>
        </li>
    <!--{/if}-->
    <!--{foreach from=$children item=child}-->
        <li class="level<!--{$child.level}--><!--{if in_array($child.category_id, $tpl_category_id)}--> onmark<!--{/if}-->">
            <a href="<!--{$smarty.const.ROOT_URLPATH}-->products/list.php?category_id=<!--{$child.category_id}-->"<!--{if in_array($child.category_id, $tpl_category_id)}--> class="onlink"<!--{/if}-->><!--{$child.category_name|h}--><span class="u-n">(<!--{$child.product_count|default:0}-->)</span></a>
            <!--{if in_array($child.category_id, $arrParentID)}-->
                <!--{assign var=disp_child value=1}-->
            <!--{else}-->
                <!--{assign var=disp_child value=0}-->
            <!--{/if}-->
            <!--{if isset($child.children|smarty:nodefaults)}-->
                <!--{include file="`$smarty.const.TEMPLATE_REALDIR`frontparts/bloc/category_tree_fork.tpl" children=$child.children display=$disp_child}-->
            <!--{/if}-->
        </li>
    <!--{/foreach}-->
</ul>

開閉用のボタンを設置するといいのですが、
リンクエリアが限定されると操作性が悪くなると思うので、
「カテゴリーのすべて」というリンクをもう一つ生成してあげることによって、
解決してみました。

バージョン 2.13.4

http://blog.livedoor.jp/mokuhen/archives/51608775.html
に続いてECCUBEの管理画面ネタ


ページ詳細設定とレイアウト設定の画面のテーブルにて、
名称|レイアウト|ページ編集|削除 と
項目がありますが、その中に確認という項目を追加しました。



<h2>編集可能ページ一覧</h2>
<div class="btn addnew">
    <a class="btn-normal" href="?device_type_id=<!--{$device_type_id|u}-->"><span>ページを新規入力</span></a>
</div>
<table class="list">
    <col width="60%" />
    <col width="10%" />
    <col width="10%" />
    <col width="10%" />
    <col width="10%" />
    <tr>
        <th>名称</th>
        <th>レイアウト</th>
        <th>ページ詳細</th>
        <th>確認</th>
        <th>削除</th>
    </tr>
    <!--{foreach key=key item=item from=$arrPageList}-->
        <tr style="<!--{if $item.page_id == $page_id}-->background-color: <!--{$smarty.const.SELECT_RGB}-->;<!--{/if}-->">
            <td>
                <!--{$item.page_name}-->
            </td>
            <td class="center">
                <a href="./<!--{$smarty.const.DIR_INDEX_PATH}-->?page_id=<!--{$item.page_id}-->&device_type_id=<!--{$item.device_type_id}-->" >編集</a>
            </td>
            <td class="center">
                <!--{if $item.filename|strlen >= 1}-->
                    <a href="?page_id=<!--{$item.page_id}-->&device_type_id=<!--{$item.device_type_id}-->">編集</a>
                <!--{/if}-->
            </td>
            <td class="center">
                <a href="<!--{$smarty.const.ROOT_URLPATH}--><!--{$item.filename}-->.php" target="_blank">確認</a>
            </td>
            <td class="center">
                <!--{if $item.edit_flg == 1}-->
                    <a href="javascript:;" onclick="fnTargetSelf(); eccube.fnFormModeSubmit('form_edit','delete','page_id','<!--{$item.page_id|escape:'javascript'|h}-->'); return false;">削除</a>
                <!--{/if}-->
            </td>
        </tr>
    <!--{/foreach}-->
</table>


/data/Smarty/templates/admin/design/index.tpl
/data/Smarty/templates/admin/design/main_edit.tpl

ページ詳細設定とレイアウト設定では微妙にコードが違いますが、
赤色のところを適用するとOKです。
レイアウト設定には <col> が無かったです。





続いてレイアウト設定画面のブロックUI。



ここからブロック編集画面へのリンクを貼れればいいなーと思ったのですが、
楽ちんで出来たので紹介。


<!-- ★☆★ HEADタグ内テーブル ☆★☆ -->
<td colspan="3" id="<!--{$arrTarget[$smarty.const.TARGET_ID_HEAD]}-->" class="ui-sortable">
    <!--{assign var="firstflg" value=false}-->
    <!--{foreach key=key item=item from=$arrBlocs name="bloc_loop"}-->
        <!--{if $item.target_id == $arrTarget[$smarty.const.TARGET_ID_HEAD]}-->
            <div class="sort<!--{if !$firstflg}--> first<!--{/if}-->">
                <input type="hidden" class="name" name="name_<!--{$smarty.foreach.bloc_loop.iteration}-->" value="<!--{$item.name}-->" />
                <input type="hidden" class="id" name="id_<!--{$smarty.foreach.bloc_loop.iteration}-->" value="<!--{$item.bloc_id}-->" />
                <input type="hidden" class="target-id" name="target_id_<!--{$smarty.foreach.bloc_loop.iteration}-->" value="<!--{$item.target_id}-->" />
                <input type="hidden" class="top" name="top_<!--{$smarty.foreach.bloc_loop.iteration}-->" value="<!--{$item.bloc_row}-->" />
                <!--{$item.name}-->
                <label class="anywherecheck">(<input type="checkbox" class="anywhere" name="anywhere_<!--{$smarty.foreach.bloc_loop.iteration}-->" value="1" <!--{if $item.anywhere == 1}-->checked="checked"<!--{/if}--> />全ページ)</label>
                <a href="bloc.php?bloc_id=<!--{$item.bloc_id|h}-->&device_type_id=<!--{$device_type_id|h}-->" >編集</a>
            </div>
            <!--{assign var="firstflg" value=true}-->
        <!--{/if}-->
    <!--{/foreach}-->
</td>
<!-- ★☆★ Headタグ内テーブル ☆★☆ -->


/data/Smarty/templates/admin/design/index.tpl

似たような記述が13箇所ありますが、赤色のところを1個1個適用するとOKでした!

このページのトップヘ