新しい日記

新しい日記

MySQL の now() とタイムゾーンの関係

NOW() した際に UTC になっていたので、JST にしようとしたところはまった。

まず MySQLタイムゾーン複数ある。

mysql> SELECT @@system_time_zone, @@global.time_zone, @@session.time_zone;

をするとわかります。

@@system_time_zone はシステムタイムゾーンと言われるもので、ホストマシンのタイムゾーンを特定して、これを使用してシステム変数で設定しようとする。mysqld を起動した後は変更しない。起動時に明示的に設定することができる。
@@global.time_zone はサーバの現在のタイムゾーンで、サーバが現在動作しているタイムゾーンを示す。初期値は'SYSTEM'で、サーバのタイムゾーンがシステムタイムゾーンと同じことを表す。
@@session.time_zone は接続ごとのタイムゾーン。接続するそれぞれのクライアントごとに設定される。最初はglobal.time_zoneから値を取ってくるけど、後で変えられる。

(引用&参考-MySQL :: MySQL 5.6 リファレンスマニュアル :: 10.6 MySQL Server でのタイムゾーンのサポート)

NOW() がとってくるタイムゾーンは @@session.time_zone っぽいんですが、システムタイムゾーンJST で、他が SYSTEM の値を取っていれば、全部JSTになるっしょと思ってたらそうじゃないみたい。このあたり、よくわかってない…

f:id:tttttahiti:20151130154502p:plain

SYSTEM はシステムタイムゾーンと同じ値を取ると思っていたんですがそうじゃない?あるいは、このシステムタイムゾーンJST が効いていない?
でも、 /etc/localtime は Asia/Tokyo にしてあるので、ホストマシンは JST と同じ時刻設定になってて、

$ date

するとちゃんと JST の時刻で表示されてる && my.cnf にも timezone=JST になってるので、効いてないということはないと思っているんですが…よくわかってない…

とりあえず、日本はサマータイムとかもないし、 UTC からぴったり9時間前ということには変わりないので、my.cnf で default-time-zone を+9時間で設定しておく。

[mysql]
~略~
default-time-zone='+9:00'

f:id:tttttahiti:20151130155311p:plain

一応、 JST で NOW() できたので、今日はこんなかんじで…
タイムゾーン難しいし、世の中の時計全部 UTC だったらいいのでは?(乱暴)

PHP5.6に入れなおすぞ!

前回うまくいかなかった vagrant 上の PHP のアップグレード作業に再チャレンジしました。

結果!
f:id:tttttahiti:20151127115855p:plain
そして!
f:id:tttttahiti:20151127115946p:plain
できた〜!!!

手順!

準備。古い php は消しておく

yum remove php-*

remi リポジトリの追加

まずそもそも(前回から) remi ってなんやねん…って思っていたんですが、どうやら yum のパッケージインストール、アップデート、アンインストールを便利にしてくれるリポジトリらしい。
新しいバージョンのパッケージがダウンロード出来るようになったりする拡張みたいな?イマイチよくわかってないけど、インストール元が増えて便利っぽい。
早速追加してみましょう。の前に! remi をインストールする前に epel というリポジトリも入れなきゃいけないらしい。この epel というのも remi みたいにインストール元が増える便利リポジトリっぽい。全くよくわかってないことが顕著になってきた。すいません。後でもうちょっと調べます
とりあえず epel をダウンロードするぞ!
まずは epel の GPG-key という公開鍵的なものを /etc/pki/rpm-gpg/ にダウンロードする。
epel の GPG-key は riken のサイト内にあるらしい。

cd /etc/pki/rpm-gpg/
wget http://ftp.riken.jp/Linux/fedora/epel/RPM-GPG-KEY-EPEL-6

入手出来たか!?出来たら /etc/yum.repos.d/ に epel.repo という EPEL 用の repo ファイルを作る。
ファイルの中身はこんなかんじです

#Extra Packages for Enterprise Linux (EPEL)
[epel]
name=Extra Packages for Enterprise Linux (EPEL)
baseurl=http://ftp.riken.jp/Linux/fedora/epel/6/$basearch/
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6

baseurl の $basearch というのは、epel を使うときにここにダウンロードしに行くところが自動で入るらしい。頭いい。(雑な感想)
enabled=0 は yum の実行時にデフォルトでは無効になり、指定しないと epel を使わないということです。
gpgcheck=1 はGPGを使用してパッケージの署名を確認するという意味。
gpgkey はさっきダウンロードした鍵の場所を指定している!

このファイルができたら、もう yum 使うときに epel も使えるぞ!
使い方はこんな感じです!

yum --enable=epel update

今回私の場合は特にエラーも出ずいい感じに epel が使えてるみたいな挙動をしていたので、やっと、 remi をインストールします。

wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
rpm -ivh remi-release-6.rpm

ここでエラーが出る。

警告: remi-release-6.rpm: ヘッダ V3 DSA/SHA1 Signature, key ID 00f97f56: NOKEY
エラー: 依存性の欠如:
	epel-release >= 6 は remi-release-6.6-1.el6.remi.noarch に必要とされています

epel-release が足りないらしいのでインストールしましょう。

yum --enablerepo=epel install epel-release

そしてもう一度、先ほどの rpm のコマンドを試してみると、うまくいくはず!
やっと、 remi リポジトリのインストールができました。
remi でインストール出来るリストのファイルみたいなのが /etc/yum.repos.d/remi.repo に出来ます。
この中を見ると、 remi-php55(PHP5.5), や remi-php56(PHP5.6) などがありますので、これをインストールします。
先ほどの epel を有効にしたのと同じように、 remi もデフォルトでは無効なので有効にするオプションを付けます。

yum install --enablerepo=remi-php56 php

あとは vagrant reload して PHP バージョン確認!ページの表示もちゃんと確認!よかった。

参考

Yum - php5.5とかphp5.6をインストールする - Qiita

Remiリポジトリの追加 | katz+

epelリポジトリの追加 | katz+

ejs で json からデータを取り込む

ejs は embeddedjavascript というテンプレートエンジン。
gulp 用のパッケージもあるよ。

www.npmjs.com

HTML に組み込むような書き方なので、デザイナーさんなどと共有しやすいし、学習コストが低くて気に入っています。
外部ファイルの include や 変数の呼び出し、ループなど、はもちろん js で出来ることは(たぶん)全部出来る。
以下、外部ファイルの head を読み込んで、見出しに変数を入れ、配列をループさせる簡単な例です。

<% var title = "見出し1", array=["hoge","fuga","poyo"] %>
<html>
<head>
  <% include head %>
</head>
<body>
  <h1><%= title %></h1>
  <ul>
    <% for(var i=0;i<array.length;i++){ %>
    <li><%= array[i] %></li>
    <% } %>
  </ul>
</body>
</html>

出力はこんなかんじ

<html>
<head>
  <meta charset="UTF-8">
  <meta name="description" content="ejs のサンプルです。" />
  <link rel="stylesheet" type="text/css" media="all" href="style.css" />
<title>サンプル</title>
</head>
<body>
  <h1>見出し1</h1>
  <ul>
    
    <li>hoge</li>
    
    <li>fuga</li>
    
    <li>poyo</li>
    
  </ul>
</body>
</html>

include とか出来るだけでも十分っていう場合もあるけど、せっかくなんでデータを取り込んでループさせたりとかしたいですね。
今回私は一週間分の違う料理とその材料を記載したデータを作りましたので、それを gulp + ejs + json でテンプレートに取り込むということをしました。

f:id:tttttahiti:20151016155213j:plain

こんなかんじのイメージです。
ポイントとしては、料理の写真、説明文、材料がユニークな値になり、材料の数も可変ということです。

用意するのは

  • gulp
  • template.ejs
  • data.json

説明を容易にするため、各種ファイルは全て gulp の作業ディレクトリ上にあるということで。
gulpfile.js はこんなかんじ。

var gulp = require('gulp');
var ejs = require('gulp-ejs');
var jsonData = require('./data.json');

gulp.task('build', function(){
  return gulp.src('./templates.ejs')
  .pipe(ejs({
    jsonData: jsonData //jsonData に data.json を取り込む
  }))
  .pipe(gulp.dest('./'));
});

シンプル!json で作ったデータはこんなかんじ。

[
  {
    "daynum": "1",
    "dishname": "おいしいカレー",
    "description": "みんな好きなカレーです。甘口です。",
    "item": [
      {
        "name": "にんじん",
        "amount": "中3本",
      },
      {
        "name": "たまねぎ",
        "amount": "中2玉",
      },
      {
        "name": "じゃがいも",
        "amount": "中3個",
      },
      {
        "name": "カレールー",
        "amount": "4切れ",
      }
    ]
  },
  {
    ...
  },
  {
    "daynum": "7",
    ...
  }
]

excel データを渡されたりなどした場合、これとかで変換するとラクチンです。
次、 template.ejsはこんなかんじ。

<%
var data = jsonData;
%>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" type="text/css" media="all" href="./styles.css" />
  <title>一週間の料理</title>
</head>
<body>
<h1>一週間の料理</h1>
<% data.forEach(function(day){ %>
<section class="dish">
  <h2 class="dish__heading"><%= day.daynum %>日目の料理</h2>
  <div class="dish__image">
    <img src="./img/day<%= day.daynum %>.jpg" alt="<%= day.dishname %>">
  </div>
  <div class="dish__body">
    <p class="dish__name"><%= day.dishname %></p>
    <p class="dish__description"><%= day.description %></p>
    <ul class="ingredients">
      <% day.item.forEach(function(item){ %>
      <li class="ingredients__item">
        <p class="ingredients__name"><%= item.name %></p>
        <p class="ingredients__amount"><%= item.amount %></p>
      </li>
      <% }) %>
    </ul>
  </div>
</section>
<% }) %>
</body>
</html>

ポイントは、 forEach 文で各配列 or オブジェクトを操作する形にするっていうところです。

for(var i=0;data.length;i++){
...
}

のような記法だと、なぜだか data[i].description などが読み込めません…!
出力すると以下のようになるはずです。

<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" type="text/css" media="all" href="./styles.css" />
  <title>一週間の料理</title>
</head>
<body>
<h1>一週間の料理</h1>

<section class="dish">
  <h2 class="dish__heading">1日目の料理</h2>
  <div class="dish__image">
    <img src="./img/day1.jpg" alt="おいしいカレー">
  </div>
  <div class="dish__body">
    <p class="dish__name">おいしいカレー</p>
    <p class="dish__description">みんな好きなカレーです。甘口です。</p>
    <ul class="ingredients">

      <li class="ingredients__item">
        <p class="ingredients__name">にんじん</p>
        <p class="ingredients__amount">中3本</p>
      </li>

      <li class="ingredients__item">
        <p class="ingredients__name">たまねぎ</p>
        <p class="ingredients__amount">中2玉</p>
      </li>

      <li class="ingredients__item">
        <p class="ingredients__name">じゃがいも</p>
        <p class="ingredients__amount">中3個</p>
      </li>

      <li class="ingredients__item">
        <p class="ingredients__name">カレールー</p>
        <p class="ingredients__amount">4切れ</p>
      </li>

    </ul>
  </div>
</section>

<section class="dish">
  <h2 class="dish__heading">2日目の料理</h2>
  ...


</body>
</html>

参考記事

qiita.com

qiita.com

aircolor.hatenablog.com

sass 3.3 以上で使えるようになった map について

今更ってかんじですが… css 風の書き方で json みたいなデータを作れるようです。
書き方のサンプルはこんなかんじ

$map: (
  key1: value1,
  key2: value2,
  key3: value3,
);
<||

以下はマップを使ったカラーパレットの管理の例です。

>||
$colors: (
  black: #000,
  gray: #888,
  white: #fff,
);

中の値を取り出すには、map-get()を使います。

@function colors($key){
  @return map-get($colors,$key)
};

.hoge{
  color: colors(black); // #000
}

また、データは入れ子にすることも出来ます。
これを使って、色をトーンにわけて管理したり出来ます。

$colors: (
  black: (
    default: #1a1a1a,
    dark: #000,
  ),
  gray: (
    default: #4c4c4c,
    light: #d8d8d8,
  ),
  white: (
    default: #fff,
    dark: #fafafa
  ),
  green: (
    default: #22d3c7
  ),
);

ネストされた中の値を取り出すには、map-get()をネストして使います。

@function colors($key,$tone: default){
  @return map-get(map-get($colors,$key),$tone)
};

.fuga{
  color: colors(black,dark); // #000
}

引用・参考qiita.com

マップ用の関数は、 map-get も含めて5つ。

  • map-get($map, $key)................キーの値を取得する
  • map-merge($map1, $map2)......マップを結合する
  • map-keys($map).......................マップのキーをカンマ区切りで返す
  • map-values($map)....................マップの値をカンマ区切りで返す
  • map-has-key($map, $key)........マップにキーが含まれているか調べ真偽値を返す

@each を使って、複数クラスを自動生成するという使い方も。

.box {
    $config: (
        warn: red,
        info: blue,
    );
 
    @each $class, $bg-color in $config {
        @at-root #{&}-#{$class} {
            background-color: $bg-color;
        }
    }
}
<||

コンパイルすると以下のようになります。
>||
.box-warn {
  background-color: red;
}
.box-info {
  background-color: blue;
}

引用・参考html5experts.jp

@each ってグリッド作るときくらいしか使ったことなかったけど、マップと合わせて使うとすごい強力そう。

javascript reduce(), reduceRight()

隣り合う 2 つの配列要素に対して(左から右へ)同時に関数を適用し、単一の値にします。

by MDN

以下の様な感じで、 配列の総計を出したりするのに使えます

var sum =function(arr){
  var value = arr.reduce(function(a,b){
    return a+b;
  });
  return value;
};
var arr = [0,1,2,3,4];
sum(arr); //10
}

for を使って書くよりもずっと少ない記述で済みます!

イメージとしては、

1. 配列の最初の値と次の値を足し、
a=0, b=1
total=a+b=1

2. 先ほどの total を a として、さらに次の値を足し、
a=total=1, b=2
total=a+b=3

3.配列の要素数だけ同じ手順を繰り返し
a=total=3, b=3
total=a+b=6

4.最後に残った値を返します(単一の値になった!)
a=total=6, b=4
total=a+b=10

大事なのは、現在の値と次の値を参照しているのではなくて、累積値(=total)と次の値を参照しているというところのようです。

また、この累積値の初期値を第二引数に入れておくこともできます。
例えば、配列に100以上の数があればその数字を返して、なければ100を返す関数。

var hundred = function(arr){
  var value = arr.reduce(function(a,b){
    if(a>b){return a;}
    return b;
  },100);
  return value;
};
var small = [10,20,30,40,50];
var large = [10,20,300,400,500];
hundred(small); //100
hundred(large); //500

要素の高さを揃えるのに使えそうですね。

reduceRight()は配列を右から左にやるっていう違いのようです。
またブラウザ対応は IE9 以上なので、 IE8 切ってもいい案件から使っちゃうといいでしょう!

参考

developer.mozilla.org
taiju.hatenablog.com

git でローカル環境外で管理したくないファイルを指定する

普通に作った .gitignore はリポジトリ内で共有されてしまいます。
自分専用の環境設定ファイルなど、ローカル環境では使いたいけど、 リポジトリ全体では共有したくないものなどは .git/info/exclude に記述することで、管理から除外されます。
ただし、 sourcetree でクローンしたリポジトリなどではそもそも .git/info が作られないようです。
そんなときは普通に作っちゃえばオールオッケーです。

$ cd .git;mkdir info && cd info;touch exclude

あとはお好きなエディタで .git/info/exclude を .gitignore と同じように記述するだけ。

また、いちいち全部のリポジトリで記述するのはめんどくさいようなものであれば、 config をいじって設定できます。

$ git config --global core.excludesfile $HOME/.gitignore

この $HOME/.gitignore 内にローカル環境全体で無視したいファイルを記述すれば、どのリポジトリでも無視されます。

config ファイルを直接いじる場合はこんなかんじで

[core]
	excludesfile = /Users/hoge/.gitignore

vagrant に php 5.5 をインストール

以前の記事の通り、

$ sudo yum -y install php

と、 yum で 引っ張ってくると php 5.3系がインストールされてしまいますね。

これを参考にして5.5系をインストールしてみようとしたところ、どうもうまくいかない。

$ php --version

するとちゃんと5.5系が入っていることが確認できるのですが、例えば phpinfo.php が動作せずダウンロードされてしまう。
5.3系が入っていたときにはそんなことはなかったので、 httpd.conf などの設定を再度確認。すると、

LoadModule php5_module modules/libphp5.so

がなかったのでこれを書き足した!

そこで、httpd 再起動したら libphp5.so がありません!と怒られて httpd 起動しなかった…。
modules/の中身確認したけど やっぱり libphp5.so ない。
libphp5.so どうやったらできるのか〜と思って早速ggってみたら これがトップにヒットしたけどよくわからんぞ。
あとでこれも試す…

時間かかってしまったので結局 5.3 系入れなおしてとりあえずやれる作業はやっておく…