webプロダクトいんふぉ

webの気になった情報を発信中!!

HTMLが絡んだPHPのコードをコメントアウト

コメントアウトの仕方

PHPコメントアウトの仕方には3つあります

//を用いる

<?php
  echo "hello world!"; // hello worldを出力
?>

コメント範囲を/**/で囲う

<?php
  $a = "hello world!";
  if(!$a.empty) {
    echo $a;
  }
  /*else {
    echo "$aが空です";
  }
  elseは実行しない*/
?>

#を用いる(非推奨)

//と同じような意味なのでこちらは使用しない

<?php
  echo "hello world!"; # hello worldを出力
?>

本題のHTMLが絡んだPHPのコードをコメントアウト

以下のコードをテキストエディタのショートカット(Ctrl or Command + / )を利用してコメントアウトしてみます。

<?php
  <option value="2016年9月10日 18時~ 東京"
    <?php echo (isset($post['日時']) == '2016年9月10日 18時~ 東京' && $post['日時'] == '2016年9月10日 18時~ 東京') ? 'selected="select"' : '' ; ?>>東京 9月10日 18時~
  </option>
?>

コメントアウトした結果は以下のようになり、HTMLだけがコメントアウトされPHPコメントアウトされていないためにエラーの原因になります。

<?php
  <!-- <option value="2016年9月10日 18時~ 東京"
    <?php echo (isset($post['日時']) == '2016年9月10日 18時~ 東京' && $post['日時'] == '2016年9月10日 18時~ 東京') ? 'selected="select"' : '' ; ?>>東京 9月10日 18時~
  </option> -->
?>

エラーを起こさないためにはHTMLを含んだコードをPHPの一部とみなして、PHPの複数行コメントアウトを使用すれば両方のコードがコメントアウトされます。

<?php
  /*
  <option value="2016年9月10日 18時~ 東京"
    <?php echo (isset($post['日時']) == '2016年9月10日 18時~ 東京' && $post['日時'] == '2016年9月10日 18時~ 東京') ? 'selected="select"' : '' ; ?>>東京 9月10日 18時~
  </option>
  */
?>

一行だけであれば、//で対応しても問題ありません。HTMLが絡んだPHPのコードをコメントアウトをするときには、PHPコメントアウトを使用するように意識すれば戸惑うこともなくなるはずです。

MacBook Proの2016モデル

iPhone7

iPhone7の予約開始から2日経ちましたが、皆さんは既に予約しているのでしょうか。自分は今回見送っています。felica対応は嬉しいけれども、Apple Payに対応しているモノが所有しているやつと合わなかったのが主な理由(Suicaのみ対応とか)

現代モデルから16Gが廃止になってaplle製品が色々と値下がりしましたね。iPadProとか最上位モデルだと3万円安くなってるし、iPadProも春くらいに新型モデルが出るとか言われてますけど、我慢するか買うかは人それぞれ何で個人の采配に任せるってことで

MacBook Pro

そんなこんなで自分が期待しているのは、macOS Sierraのリリースは現地時間9月21日ということで、MacBook Proの発売日は10月に来るのかなぁ〜と予想を立てながら待っています。今使っているMacBook Proが悲鳴をあげていて、そろそろ出てくれないときついので、Appleには切にお願いしたいと思っています!今の現行モデルを買うのは負けた気がするので、それだけは選択肢としてありえない。

先日のスペシャルイベントでも期待していたので、かなり残念でした!iPhone7の発表の後MVが流れた時の絶望感は今でも思い出せます(つい先日ですが)

MacBook Proが出れば、IT界隈であればiPhone7の発表よりも盛り上がることは間違いなしと思っているので、続報を待ちましょう!!

Rails標準のO/RマッパーであるActive Recordとは?

O/Rマッパー

Object/Relatinalの略で、リレーショナルデータベースとオブジェクト指向言語との橋渡しを受け持つライブラリです。

そもそも、アプリケーション(フロント)側で使用するオブジェクトモデルと、データベースが利用するリレーショナルモデルは決定的に構造が異なるため、フォームから受け取った値などをオブジェクトから一つ一つ取り出したりといった手順が必要でした。

単純な作業ではあるが、上記の手順などがアプリケーションコードの半分以上を占めていたと言われています。

このようなコードの冗長化を解消するために、オブジェクトモデルとリレーショナルモデルのミスマッチを解消するためのツールです。

例えば、usersテーブルみたいなのがあり、下記のようなカラムを用意してあげます。

  • id
  • email
  • tel
  • password

そうしたら、上記のカラムに対応するオブジェクトを用意すれば、

{id: 1

email: aaaa@aaa.com

tel: 000-0000-000

password: password}

このままデータベースに登録することができます。つまり、オブジェクトを分解してidはidカラムに対応しているというような設定が必要なくなります。

Acrive Record

Active Recordを利用することで、リレーショナルデータベース(Excelのような表形式のデータ)をあたかもオブジェクトであるかのように操作ができるようになります。

その上、基本的にはsqlコマンドを記述する必要がありません。sqlにはMySQLPostgreSQL毎に一部書き方が違いますが、O/Rマッパーは内部的にその差異を吸収してくれるので、接続先のデータベースを変更してもアプリケーションへの影響が最小限に抑えられます。

 

カルーセルスライダーを条件別にスライド位置を変える

ルーセルスライダーとは?

画像やコンテンツがスライドして別のコンテンツを切り替えて表示する方法
DEMO
Download

ライブラリとしては、良くslick.jsbxslider.jsが使われる
個人的にはslick.jsが使いやすい。カスタマイズする際、bxsliderはハマりやすい。その代わり、高機能。

今回はslick.jsを使用する。

slick-theme.cssは必須ではないですが、公式のdemoみたいな見た目にしたいのであれば入れた方がいいです。一応jQueryも読み込んでいます。

<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/jquery.slick/1.6.0/slick.css"/>
<link rel="stylesheet" type="text/css" href="css/slick-theme.css">
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<script type="text/javascript" src="//cdn.jsdelivr.net/jquery.slick/1.6.0/slick.min.js"></script>

適当にヘッダー部分と、スライドコンテンツを作ります。

注意点としては、スライドさせたいコンテンツはdivタグで括ってあげることです。ulタグなどで括るとうまく動作しません。

<header id="header">
  <div id="header-inner">
    <h1>SlickSample</h1>
    <ul class="flR">
      <li><a href="#one">one</a></li>
      <li><a href="#two">two</a></li>
      <li><a href="#three">three</a></li>
    </ul>
  </div>
</header>

<div class="slide-wrapper slider">
  <div>
    <img src="img/slide_01.jpg" alt="">
  </div>
  <div>
    <img src="img/slide_02.jpg" alt="">
  </div>
  <div>
    <img src="img/slide_03.jpg" alt="">
  </div>
</div>

jsでslick.jsのメソッドを呼んでいます。中に書いている「accessibility」、「dots」などはオプションです。見た目や動きなどを変えたいときには、ここ(自分で書くjs)とslick-theme.cssをカスタムすることになります。

オプション一覧

オプション名 デフォルト 説明
accessibility bool true 左右のナビゲーションの有効/無効
autoplay bool false オートプレイの有効/無効
autoplaySpeed int 3000 スライドが切り替わる時間(ms)
dots bool false カレント表示のナビゲーション
arrows bool true 前へ/次へナビゲーションの有効/無効
initialSlide int 0 最初のスライド位置

オプションは他にも多々あるので、興味がある方は公式サイトを参考にしてみてください。settingsが該当箇所です。

$('.slide-wrapper').slick({
  accessibility: false,
  dots: true,
  arrows: false,
  autoplay: true,
  initialSlide: slide_int
});

先程、書いたjsの前に追記してあげます。ヘッダーメニューをクリックした時に、URLに付与された#***で条件判定してあげて、どのスライドを最初に出すかを選択してあげるjsです。

これで、メニューごとにスライドの初期位置を出しわけることが可能です。

var slide_int = 0;
$('.flR a').on('click', function(){
  location.reload()
});

var href = location.href.substr( location.href.indexOf("#") );
if(href == "#one") {
  slide_int = 0;
} else if(href == "#two") {
  slide_int = 1;
} else if(href == "#three") {
  slide_int = 2;
}

$('.slide-wrapper').slick({
  accessibility: false,
  dots: true,
  arrows: false,
  autoplay: true,
  initialSlide: slide_int
});

ES6で提供された主な仕様

ECMAScript6とは?

そもそもECMAScriptとは、標準化団体によって標準化された言語仕様で、JavaScriptが動作する際に、元となっている仕様です。

ES6で提供された新たな仕様(1部抜粋)

・class命令によるJava/C#ライクなクラス定義が可能に

・import/export命令によるコードのモジュール化に対応

・関数構文の改善

・let/const命令によるブロックスコープの導入

・for...of命令による値の列挙

イテレーター/ジェネレーターによる列挙可能なオブジェクトの操作が可能に

・promise、コレクション(Map/Set)/Proxyなどの組み込みオブジェクトを追加

・string/Number/Array/Objectなどの既存組み込みオブジェクトの拡充など

ブロックスコープを有効にする ー let命令

これまでのJavaScriptには、ブロックレベルのスコープはありませんでした。

※ES6を試してみたい方は、https://babeljs.io/repl/を利用ください

if (true) {
  var i = 1;
}
conosole.log(i); // 結果:1

ブロックスコープが有効であれば、結果は未定義エラーとなるはずですが、JavaScriptではブロックスコープの概念がないので、変数iはブロック外でも有効となり、結果は1です。そこで、ES6のlet命令を利用することでブロックスコープで有効な変数を宣言できます。

if (true) {
  let i = 1;
}
conosole.log(i); // 結果:エラー(i is not defined)

今度は、結果はエラーになります。let命令で宣言された変数はブロック外では無効になったためです。

let命令はスコープ内での変数の重複を認めていない(var命令は可)

ES6でもvar命令は宣言できますが、「スコープは最大限限定すべき」「重複チェックコンパイラーに任せられる」などの理由から、基本はlet命令を優先して利用することになると思います。

「let命令はスコープ内での変数の重複を認めていない」と書きましたが、どういうことかというと

switch(i) {
  case 0:
  let value = 'i:0';
  break;
  case 1:
  let value = 'i:1'; // 重複エラー
  break;
}

case1の時にも同じ変数名を定義しているので、エラーになってしまいます。

即時関数は利用しない

即時関数は、関数ブロックで疑似的にスコープを形成し、グローバルスコープの汚染を防ぐテクニックです。

(function(){
  // 関数の中身
})();

ES5までは当然の仕組みですが、ES6ではコード全体をブロックで括り、配下の変数をlet命令で宣言すれば、即時関数と同じ効果が得られるので、利用する必要がなくなります。

定数を宣言する ー const命令

const命令は、定数を宣言できます。PHPのfinalと同じです。

const data = 100;
data = 150; // エラー

ただし、const命令の定数は正しくは「再代入できない」であって、「変更できない」ではない点に注意です。

const data = [1, 2, 3];
data[0] = 10;
console.log(data); // 結果:[10,2,3]

配列は参照型なので、dataの参照先に再代入しているわけではなく、中身の要素だけを書き換えているため、constの制約にはかかりません。

const data = [1, 2, 3];
data = [10, 2, 3]; // エラー

配列そのもを変更した場合にはエラーになります。

文字列リテラルへの変数/改行の埋め込みを可能にする ー テンプレート文字列

テンプレート文字列を利用することでエスケープシーケンスで表現していた文字を、文字リテラルの中でそのまま表現できます。テンプレート文字列はクォート「'」「"」の代わりに、「`」(バッククォート)で括ります。

let str = `Hello
World`;
console.log(str); //Hello「改行」World

これまでであればエスケープシーケンスで表現していた改行文字を、文字列リテラルの中でそのまま表現できます。

また、${}の形式で、変数を文字列に埋め込むことも可能です。今までは、変数と文字は「+」演算子を使って連結する必要がありました。

let name = 'Tom';
console.log(`Hello,${name}!`); // Hello,Tom!

新たなデータ型Symbol

従来のNumber、String、Objectなどの型に加えて、新たにSymbolという型が追加されました。これは下手な説明より見た方がはやいです。

let hoge = Symbol('hoge');
let hoge2 = Symbol('hoge');
console.log(typeof hoge); // 結果:symbol
console.log(hoge.toString()); // 結果:symbol(hoge)
console.log(hoge === hoge2); // 結果:false

ここで注意するのは一点だけです。Symbolで生成したものは中身が同じであろうと、別物とみなされます。

また、シンボルでは文字列や数値への暗黙的な変換はできません。つまり、Symbolの型と文字列・数値の連結はできません。

ただし、boolean型、object型への変換は可能です。

これって実際どんな場面で活用するの?となると思います。

具体的な利用例をいくつか下記に挙げます。

①定数の値として利用する
var JAVASCRIPT = 0;
var RUBY = 1;
var PERL = 2;
var PYTHON = 3;

一般的に、このような定数は、JAVASCRIPTRUBYPERLなどを識別するための定数であって、割り当てられた0、1、2...といった値には意味がありません。ただ、これらの定数を利用するコードでは、定数、数値を利用してもエラーにはなりません。

コードの可読性を考えれば「0」で比較するのは望ましい状態ではありませんし、そもそも「var HOGE = 0;」のような定数が現れた時に、同じ値の定数が混在してしまうのはバグが混入する元です(枠割が似ていれば尚更)

そこで定数の値としてSymbolを利用します。

const JAVASCRIPT = Symbol();
const RUBY = Symbol();
const PERL = Symbol();
const PYTHON = Symbol();

Symbol命令で生成されたシンボルは、同名であってもユニークになります。つまり、定数JAVASCRIPTと等しいのは定数JAVASCRIPTのみです。

②非公開なプロパティを定義する

たとえば以下は、MyClassクラスの中で、privateなSECRETプロパティを定義する例です。

// SECRETプロパティの名前でシンボルで準備
const SECRET = Symbol();
class Myclass {
  constructor(secret) {
    this.data1 = 1;
    this.data2 = 2;
    // SECRETプロパティに値を設定
    this[SECRET] = secret;
  }
  // SECRETプロパティを利用したメソッド
  checkSecret(secret) {
    return this[SECRET] === secret;
  }
}
let c = new Myclass(12345);
// メソッド経由ではSECRETプロパティにアクセスできる
console.log(c.checkSecret(12345)); // true
// SECRETプロパティへの直接アクセスは不可
console.log(c.secret); // undifined
// オブジェクトのキー(プロパティ)を列挙
console.log(Object.keys(c)); // ["data1","data2"];
// オブジェクトのキー(プロパティ)を列挙
for (let k in c) {
  console.log(k); // data1、data2
}
// オブジェクトをJSON文字列に変換
console.log(JSON.stringify(c)); // {"data":1,"data2":2}

SECRETプロパティの名前をシンボルとして準備し、「this[SECRET]=~」でプロパティとして定義

シンボルSECRETの値は他からは判別できませんので、SECRETプロパティに直接アクセスすることはできません。for...in命令による列挙、JSON.stringifyメソッドで生成されたJSON文字列にも、シンボルで生成されたプロパティは現れてこない点に注目してください。

ただし、完全に隠ぺいできるわけではなく、getOwnPropertySymbolsメソッドを利用すると、シンボルプロパティにアクセスすることは可能です。

let idsym = Object.getOwngetOwnPropertySymbols(c)[0];
console.log(c[idsym]);

配列/オブジェクトから個々の要素を抽出する ー 分割代入

分割代入(destrucruting assignment)は、配列/オブジェクトを分解し、その要素/プロパティを個々の変数に展開するための構文

let [hoge, foo] = [15, 21];
console.log(hoge); // 15

「...」演算子を利用することで、残りの要素をまとめて配列として取り出すこともできます。

let [hoge, foo, ...other] = [10, 20, 30, 40, 50];
console.log(hoge); // 10
console.log(other); // [30,40,50]

オブジェクトのプロパティに割り当てることもできます。

let {hoge, foo} = {hoge:'ほげ', foo:"ふ~"};
console.log(hoge); // ほげ

入れ子になったプロパティに割り当てる

let data = {hoge: 'ほげ', foo: {piyo: 'ぴよ', goo: 'ぐう'}};
let {hoge, foo, foo: {piyo, goo}} = data;
console.log(hoge); // ほげ
console.log(foo); // {"piyo":"ぴよ","goo":"ぐう"}

指定されたプロパティが存在しなかった場合の為に、デフォルト値を用意も可能です。

let {hoge = 'ほげ', foo} = {foo: 'ふ~'};
console.log(hoge); // ほげ
宣言のない代入

今までは、宣言と代入をまとめて行っていますが、当たり前なんですけど変数宣言と代入は別々に行えます。

let hoge, foo;
[hoge, foo] = [15, 21];

ただし、オブジェクトの分割代入では、前後に()が必須です。なぜなら、左辺の{...}はブロックと見なされ、それ単体で文とすることができないからです。

let hoge, foo;
({hoge, foo} = {hoge:'ほげ', foo: 'ふ~'});

長くなってきたので、今回はここまで区切ります。

次回もES6について書いていきます。
(関数あたりのところを)