Posted on

本日は曇天なり

前回の僕のブログが(フランス革命歴)時報だったから、電話番号似ているつながりと言うわけでもないですが、今回は天気予報を取ってくるという話があったので、そのときにやったことをメモしておきます。

天気予報情報はここ。OpenWeatherMap.orgを使いました。
https://openweathermap.org/

いろいろ英語で書いてあって苦手な人は大変ですが、とりあえず必要なことは

  • Sign Upから登録
  • API keysから文字列を持ってくる

だいたいこんなところです。Subscribeは今のところ必要ない感じです。(月額ですし)

こちら側でやる必要があることはだいたい、

  • 持ってきた文字列を含むHTTPリクエストをURLに投げる
  • JSONを受け取る

あとはお好きなように使う、といったところです。

/**
* 定数、配列定義
*/

//アクセス用APIキー
define('API_KEY','/*ここに取得したAPIキー*/');
//アクセス用URL
define('API_URL','http://api.openweathermap.org/data/2.5/forecast?units=metric&id=1853908&APPID='.API_KEY);//大阪のcity idを使用

/* HTTPリクエストを投げる感じのクラスHttpRequestも用意しておく */

/*ここから取得*/
$http = new HttpRequest(API_URL,HttpRequest::REQ_HTTP_GET);
$code = $http->sendRequest();

if($code!=200){
    echo 'Error:データの取得に失敗した';
    exit;
}

$rawWeather=$http->getResponseBody();

ここで、$rawWeatherの中身はこんな感じ

{
     "cod":"200",
     "message":0.021,
     "cnt":39,
     "list":[
         {
             "dt":1491793200,
             "main":{
                 "temp":12.43,
                 "temp_min":8.35,
                 "temp_max":12.43,
                 "pressure":892.44,
                 "sea_level":1032.22,
                 "grnd_level":892.44,
                 "humidity":78,
                 "temp_kf":4.08
             },
             "weather":[{
                 "id":500,
                 "main":"Rain",
                 "description":"light rain",
                 "icon":"10d"
             }],
             "clouds":{"all":68},
             "wind":{"speed":1.06,"deg":217.002},
             "rain":{"3h":0.155},
             "snow":{},
             "sys":{"pod":"d"},
             "dt_txt":"2017-04-10 03:00:00"
          },
          { ...以下、3時間ごと5日分の予報... }
     ]
     "city":{
         "id":1853908,
         "name":"Osaka",
         "coord":{"lat":35.95,"lon":137.2667},
         "country":"JP"
     }
 }

天気の内容はlist[n].weather.mainに、気温や気圧はlist[n].mainに出ています。list[n].dt_txtは世界標準時なので、日本時間では4月10日正午の天気ってことになります。URLにunits=metricをつけることで、気温の単位は摂氏として送られてきます。リクエスト文字列をいじると華氏にもできたりするそうです。
月額のないAPIだと1分間に60回までしか呼べないとかあったりしますけど、とりあえず試す分には十分でしょう。天気予報が必要になったら、こういう方法に頼れる、と言う話でした。

Posted on

Adobe Dreamweaver CCを使って爆速でSASS(SCSS)環境を手に入れる

私はCSSを書く際には、主にSCSSを使用しています。

要素を入れ子にできるので、可読性が高く、コンポーネント的な考え方でCSSを組む傾向がある今日では、フロントエンド界隈ではとても重宝されています。

ここ最近までSCSSは、GruntやGulpなどのターミナルやコマンドプロンプトで動くタスクランナーの力を借りて使う事が主でしたが、Adobe Dreamweaver CC (2017)で標準機能として採用されたので、黒い画面とにらめっこする事なく使えるようになりましたので、敷居は随分下がったのではないでしょうか。

とっても簡単に導入できるので、その導入方法をここに記しておきます。

続きを読む Adobe Dreamweaver CCを使って爆速でSASS(SCSS)環境を手に入れる

Posted on

PDF出力で時間がかかる場合に「処理中...」表示する

CAKEPHP2で、PDF作成時にその作成している間だけ、処理中...を表示するサンプルを記入します。
まずDBを追加します。

CREATE TABLE IF NOT EXISTS `sessions` (
  `session_id` text
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

custom.css

・
・
・
div#loading {
    position : absolute;
    top : 20%;
    left : 50%;
}
・
・
・

bootstrap.php

・
・
・
define('ROOT_URL', preg_replace('/index\.php/', '', env('SCRIPT_NAME')));
・
・
・

default.ctp

・
・
・
    
・
・
・


・
・
・


xxxxController.php

    function detail($id, $step){
	if (isset($this->request->data['out'])) {
            $info = PDF出力する情報を取得処理を記述する。
            if (!empty($info)) {
                $this->autoRender = false;
                $this->layout = false;
                $this->set('info', $info);
                $this->render('pdf_out');
            } else {
                $this->モデル名->invalidate('error', "データがありません。");
                $this->autoRender = true;
                $this->layout = 'default';
            }
        }	
    }

    /**
     * セッション保存
     *
     * @note
     */
    function ajax_session_save() {
        Configure::write('debug', 0);
        $this->autoRender = false;

        $id = $this->Session->id();
        $sql = "INSERT INTO sessions (`session_id`) VALUE (:id);";
        $sqlArr['id'] = $id;
        $jsonResult = array();
        if (false === $this->モデル名->query($sql,$sqlArr)) {
            $jsonResult['RES'] = -1;
        } else {
            $jsonResult['RES'] = 0;
        }
        echo json_encode($jsonResult);
        exit;
    }

    /**
     * セッション確認
     *
     * @note
     */
    function ajax_session_get() {
        Configure::write('debug', 0);
        $this->autoRender = false;

        $id = $this->Session->id();
        $sql = "select * from sessions WHERE session_id = :id;";
        $sqlArr['id'] = $id;

        $jsonResult = array();
        $res = $this->モデル名->query($sql,$sqlArr);
        if (!empty($res)) {
            $jsonResult['RES'] = 0;
        } else {
            $jsonResult['RES'] = -1;
        }
        echo json_encode($jsonResult);
        exit;
    }

    /**
     * render直後の処理
     *
     * @note
     */
    public function afterFilter() {
        $id = $this->Session->id();
        $sql = "delete from sessions WHERE session_id = :id;";
        $sqlArr['id'] = $id;
        $res = $this->モデル名->query($sql,$sqlArr);
    }

detail.ctp

・
・
・
    
・
・
・

PDF作成処理はこのブログでは触れませんが、
結論から言うとsession_idがDBに保存されている間は、PDF出力処理中になるようにします。
出力ボタンが押下された時点で、本当に実行してよいかを問い、実行してよい場合は、当該のsession_idをDBに追加します。
renderで呼ばれた処理が終了すると、PDF出力が終わったことになり、CAKEPHP2では、
afterFilter()が呼ばれます。そこで、DBから該当のsession_idを消します。
表示VIEWでは、session_idが存在する間、処理中...を表示としておき、
DBからsession_idが削除されれば、処理中...を消すことで完成となります。

Posted on

cronでシェル登録しているファイルをテストで叩く

cronで動かすプログラムをURLから実行して動作確認をする方法です。
cronを動かす処理を書いて、それを実行して動作検証する時にテスト環境でいちいちcronを動くようにして試すのは面倒くさいのでURLを叩いてcronの結果が正しいのかを見たいという時のメモです。
cronを動かすのはCakePHP2系でCronを動かすのようにしています。
後はコントローラーのアクションで以下のように記述してあげればURLを叩いてcronが実行されます。

class XXXXController extends AppController

    function xxxxxx()
    {
	    App::uses('AppShell','Console/Command');
        App::uses('XXXXShell', 'Console/Command');
        $shell = new XXXXShell();
        $shell->action_name();
    }
}
Posted on

使いどころは知らない

フランス革命歴CCXXIV年フリミエール(3月)25日(五曜日)3時81分。
このブログを書き始めた日本標準時を(いくつかの前提をつけて)フランス革命歴に計算しなおしてみました。

ええ、今年9月に入社して3か月半、このブログのためにネタを探した結果がこのざまです。

そもそも、そんな計算をしようと考えたのはphpにjdtofrenchなる関数が存在しているのを知ったからです。
ユリウス積算日をフランス革命歴に変換するという関数で…

http://php.net/manual/ja/function.jdtofrench.php

フランス革命歴が実際に使用された、わずか14年足らずの間は
この関数でフランス革命歴に変換できるそうなのです。

世間には西暦だけじゃなくて、皇紀だったり、他の紀元年も存在すれば、
和暦でもあえて今年を昭和から数えて91年と言ってみたり、ときとして”あえて使われていない暦年で言及する”
なんていうネタがありますけれど、さすがにjdtofrenchではそのネタに使えない。
たった14年足らずしか使われていなかったから、関数もその範囲で計算を打ち切ってます。
(当然といえば当然)
だから、自分で現在時刻をフランス革命歴に換算するのを組んでみたというわけです。

フランス革命歴は…詳しいことはご自分で調べてください。とりあえず、要点は

  • 1792年9月22日(秋分)が紀元
  • 30日12か月+年末に追加日5~6日
  • 曜日は日付の下一桁(10日周期) 追加日は曜日無し
  • うるう年に明確なルールはなかった(年始を秋分に合わせようとしていたらしい)
  • 1日=10時間, 1時間=100分 1分=100秒

jdtofrenchが1806年以降に対応していないのは、フランス革命歴が実際に使われていた時期だけに対応するほか、
XX年以降のうるう年が決まっていないから、ということによるものだそうです。
なので、今回換算するにあたって、グレゴリオ暦の秋分を常に年始に合わせることにしました。
おおむね、グレゴリオ暦と同じ周期でうるう年が出る計算になります。

秋分の日の計算はこちらを使わせていただきました。
http://php.o0o0.jp/article/php-equinox_day

//グレゴリオ暦$year年秋分の日00:00:00のタイムスタンプ
function autumn_equinox($year){
    $aeqday = floor(23.2488 + 0.242194 * ($year - 1980)) - floor(($year - 1980)/4);
    $aeqdate=mktime(0,0,0,9,$aeqday,$year);
    return $aeqdate;
}
$nowdate=strtotime("today");
$nowdatetime=strtotime("now");
//現在日時から日付(00:00:00)を引いて今日の経過秒数を求める 【1】
$nowclock=$nowdatetime-$nowdate;

//グレゴリオ暦1970年秋分=革命歴CDXXIX年ヴェンデミエール1日
$year = date('Y',time());
$fy=$year-1970+179;
//今年の秋分
$aeqdate = autumn_equinox($year);

//秋分前なら前年、秋分以降なら今年の秋分の日が革命歴の年始
if($nowdate<$aeqdate){
	$fy--;
	$ffirst=autumn_equinox($year-1);
}else{
	$ffirst=$aeqdate;
}

//革命歴年始からの日数
$ftdays=($nowdate-$ffirst)/(60*60*24);

//革命歴は30日x12か月+うるう日5~6日、よって30で割れば解決
$fm=floor($ftdays/30)+1;
$fd=($ftdays%30)+1;
//曜日は10日周期
$dn=$fd%10;

//1日=革命歴10時間=革命歴1000分=革命歴100000秒
//革命歴1秒=1/100000日=グレゴリオ暦0.864秒
//革命歴経過秒数を求める
$ftsecond=floor($nowclock/0.864);

//革命歴10000秒ごとに革命歴1時間【2】
$fhour=floor($ftsecond/10000);
//革命歴1時~10時になるように調整
if($fhour<1) $fhour=10;
//革命歴1時間未満の革命歴100秒ごとに革命歴1分
$fminute=floor(($ftsecond%10000)/100);
//革命歴1分未満の革命歴秒を求める
$fsecond=$ftsecond%100;

あとは$fyから$fsecondを適当に整形する感じです。

【1】において、strtotime(“now”)が現在時刻、strtotime(“today”)が今日の00:00:00を意味しているから、
単純に引いてその日の経過秒数を使えるようにするというひと手間が要りました。
フランス革命歴下では、1秒の長さすら変化するゆえの策でした。
タイムスタンプが累計秒数だからできる荒業、でしょうか。これで、
【2】の剰余演算は%演算子を使う方向に統一しました。(fmodで計算する方法もあった。どちらが良かったのだろう)

暦年換算は、1秒の長さすら変わる暦年でもなければこれほど大掛かりなものにはならないかとは思います。
逆に、これほど大掛かりなものをわざわざ作ってみたことで、タイムスタンプは結局”ただの秒数”だと
再発見できたわけですし…

現在時刻をフランス革命歴に変換できる、という奇特なネタを身に着けることができた、というわけです。

現在時刻、(フランス革命歴)4時23分!

Posted on

ページを更新する度に背景の色が変わるキャッチコピー領域を作成してみました

ページのキャッチコピーの背景をどうしようかなと考えていた時に、ランダムで生成される四角形にしてみたらかわいいんじゃないかなと思ったので、作ってみました。モダンブラウザ用です。

サンプル

※表示を見たい場合は Result をクリック

四角形は可変なのでウインドウ幅を伸ばしたり、縮めたりすると動きがあります。

HTML

Walk on.

You have to learn to walk before you run.

四角形はli要素をJavaScriptで生成して、list_containerのul要素内に並べます。

CSS(抜粋)

// 外枠
#mosaic {
  position: relative;
  width: 100%;
  height: 300px;
  overflow: hidden;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  -ms-border-radius: 3px;
  -o-border-radius: 3px;
  border-radius: 3px;
}

// ul要素
#mosaic #list_container {
  position: absolute;
  width: 120%;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
  display: -webkit-flex;
  display: -moz-flex;
  display: -ms-flex;
  display: -o-flex;
  display: flex;
  -webkit-justify-content: flex-start;
  -moz-justify-content: flex-start;
  -ms-justify-content: flex-start;
  -o-justify-content: flex-start;
  justify-content: flex-start;
  -webkit-align-content: stretch;
  -moz-align-content: stretch;
  -ms-align-content: stretch;
  -o-align-content: stretch;
  align-content: stretch;
  -webkit-flex-wrap: wrap;
  -moz-flex-wrap: wrap;
  -ms-flex-wrap: wrap;
  -o-flex-wrap: wrap;
  flex-wrap: wrap;
  margin: auto;
  padding: 0;
  -webkit-filter: blur(3px);
  -moz-filter: blur(3px);
  -ms-filter: blur(3px);
  -o-filter: blur(3px);
  filter: blur(3px);
}

// li要素(四角形)
#mosaic #list_container li {
  -webkit-flex: 0 0 100px;
  -moz-flex: 0 0 100px;
  -ms-flex: 0 0 100px;
  -o-flex: 0 0 100px;
  flex: 0 0 100px;
  list-style: none;
  height: 100px;
}

外枠の高さをli要素の3つ分を設定し、li要素の生成数が多くてはみ出るものはoverflow:hiddenで隠して見えないようにしています。

ul要素は、親要素のサイズピッタリにしてるとウインドウ幅を伸縮していると右端で段落ちが発生して四角形がなくなってしまいますので、幅を120%程度に広げておいて空白を防ぐようにしています。

JavaScript

    //ランダムな数を生成する関数式
    var randFnc = function(min, max) {
      return Math.floor(Math.random() * max + 1 - min) + min;
    };
    //出力先の指定
    var target = document.getElementById("list_container");

    //ブロック生成
    for (var i = 0; i < 200; i += 1) {

      var li = document.createElement("li");
      //ランダム色を生成 hslは色相, 明度, 彩度で指定する
      li.style.backgroundColor = 'hsl(' + randFnc(20, 186) + ', 100%, 86%)';
      //生成したリストを追加
      target.appendChild(li);
    }

    //背景を動かす
    setInterval(function(){
    	//はじめのli要素を変数に入れる
    	var changeItem = target.childNodes[1];
    	//要素の削除
    	target.removeChild(changeItem);
    	//要素の追加
    	target.appendChild(changeItem);

    },400);

色は生成時に全自動で作成しています。RGB指定だと色の彩度や明度もバラバラになってしまうので、HSL指定で明度と彩度は固定して極力黒が強い色を出さないように調整して、あとは色相の好きな範囲をランダムな値で出るようにして表示することにしました。

ブロックの生成数は 画面幅 / 100px * 3列でフルHDでだいたい60個くらいあれば大丈夫ですが、高解像度が進んでいるので、200個くらいにしておきました。多めにしていても溢れないので大丈夫です。

背景を動かすは遊びで入れてみました。無くても可愛いですよ。

Posted on

便利に使えるdate関数

「10日後の日付を求めたい」「来月の最後の日付を求めたい」「日付の曜日を求めたい」・・
PHPを実務で使い始めて1年の間、date関数に馴染んでなかった僕としては、こんなことですごく困ったものでした。
今日の日付の取得はさすがにわかったのですが、そこから10日後を求めようとすると、月によって次月になる日が変わる。結構書かないといけないな。。と思っていたら先輩から「date使ったら一発ですよ」と言われ、そんな簡単にできてしまうのか、、とびっくりしました。
今回はそんなときに使った便利なdate関数について、忘備録としてまとめておきたいと思います。

date('Y-m-d H:i:s') //現在時刻
date('Y-m-d', strtotime("tomorrow")) // 明日
date('Y-m-d', strtotime("+ 10 day")) // 10日後
date('Y-m-d', strtotime("+ 2 weeks")) // 2週間後
date('Y-m-d', strtotime("- 1 month")) // 一ヶ月前
date('Y-m-d', strtotime("first day of - 1 month")) // 先月の最初の日
date('Y-m-d', strtotime("last day of next month")) // 来月の最後の日
date('Y-m-d H:i:s', strtotime("yesterday 15:00:00")) //昨日の15時0分0秒
date("Y-m-d",strtotime("last Sunday")) // 一番最近の日曜日

ここで勉強になったことを2点書いておきます。
last day of の指定は非常に便利で、strtotime(“2013-08-31 +1 month”)だと、2013/10/01になってしまうが、strtotime( “last day of 2013-08 +1 month” )と書くと2013/09/30と次の月の最終日になるみたいです。

date('Y-m-d', strtotime("2013-08-31 +1 month")) // 結果⇒2013/10/01
date('Y-m-d', strtotime("last day of 2013-08 +1 month")) // 結果⇒2013/09/30

strtotimeに「tomorrow」をしてした場合は明日の0時0分0秒に、「+ 1 day」を指定した場合は、明日のちょうど24時間後の時間になるみたいです。strtotime(“tomorrow”)=strtotime(“+ 1 day”)ではないので注意とのことでした。

date('Y-m-d H:i:s', strtotime("tomorrow")) // 明日の0時0分0秒
date('Y-m-d H:i:s', strtotime("+ 1 day")) // 24時間後の日時

(参考) http://kihon-no-ki.com/php-use-date-and-strtotime

Posted on

カレンダーの表示サンプル

ページいっぱいにカレンダーを表示するサンプルを作成しました。
参考になればご活用ください。
わたしの環境では、bootstrap.cssや社内で整備したcssを使っているのですが、
本サンプルでは、それらcssをこのサンプル内に記述しているため、すこし長くなっていますがお許しください。
サンプルの内容
初回表示は、今日の日付を元に今月のカレンダーを表示します。前月、次月は背景をグレーに、今日は背景を黄色にしています。
年、月を選択して、確認を押下すると、その月のカレンダーを表示します。
表示している内容は、スケジュールの件数とスケジュール内容(これはサンプルなので、使用される場合は、ここに表示したい
内容を設定してください)になります。
下記サンプル「index.html」ソースです。

2015,2016=>2016,2017=>2017);
$monthArr = array(1=>1,2=>2,3=>3,4=>4,5=>5,6=>6,7=>7,8=>8,9=>9,10=>10,11=>11,12=>12);
?>

  
    
    calender
    
  
  

カレンダー表示画面 

$val) { if ($key == 0) { echo ''; } if ($key != 0 && ($key % 7) == 0) { echo ''; } $classTd = ''; if ($val['gray']) { $classTd = 'class="bg-gray"'; } if ($val['today']) { $classTd = 'class="today"'; } ?> ' ?>
>
' . h("件数:{$cnt}") . ''; } ?>
$cadataVal) { echo '
' . h($cadataVal['schedule']) . '
'; $i++; // 4件まで if ($i >= 4) { break; } } ?>
データがありません。'; } ?>
Posted on

EC-CUBEでカートに商品を入れすぎるとエラー発生

EC-CUBE2.13(たぶん2系全て?)で商品を100個とか沢山カートに入れるとなぜかエラーが出てしまいます。

MySQLで、dtb_session.sess_dataにカートの内容を保持しており、このフィールドはTEXT型になっているんですが、調べてみるとどうもこのTEXT型ではサイズ(容量)が足りないようです。

結局、TEXT型を使ってたのをMEDIUMTEXT型に変更したらいけたのですが、まあ、通常のBtoC取引では100種類の商品も買うこと想定してなかったんでしょうね。

今回調べたTEXT型について以下にまとめます。
TEXT型には4つのタイプTINYTEXT、TEXT、MEDIUMTEXT、LONGTEXTがあります。

・TINYTEXT 最長255 バイト
・TEXT 最長65,535 バイト(64KB)
・MEDIUMTEXT 最長16,777,215 バイト(約1.6MB)
・LONGTEXT 最長4,294,967,295 バイト(約4.3GB)

カートのセッション情報を保存する、といった最長サイズで引っかかりそうなフィールドは、MEDIUMTEXTにしておいた方がよさそうですね。

(参考)http://webrescue.net/archives/4030

Posted on

CakePHP2系でCronを動かす

今までCakePHP1系ではCronを動かした事はあったのですが
CakePHP2系でCronを動かすのが初めてで動くようにするのに
つまづいたので備忘録として残しておきます。

シェルファイルを作るのはCakePHP1系と同じなのですが内容は次のようになります。
(ファイルへのパスは今回設置した環境用になっていますので適時ご自身の環境に合わせて下さい)
1系だと

#!/bin/sh
/var/www/cakephp/cake/console/cake cron action_name -app /var/www/cakephp/app

2系だと

#!/bin/sh
/usr/bin/php /var/www/cakephp/lib/Cake/Console/cake.php Cron action_name -app /var/www/cakephp/app

/usr/bin/phpがPHPの実行ファイルを指定
作ったシェルファイルをパーミッション755にしておきます。
/var/www/cakephp/lib/Cake/Console/cake.phpをパーミッション755にします。

次に実際の処理内容なのですが
1系の場合は/cakephp/app/vendors/shells/cron.phpに書いていたのを
2系の場合は/cakephp/app/Console/Command/にXXXXShell.phpというファイルを作ります。

内容は

Staff->find('all'); // コントローラーから呼ぶようにModelを呼べる
    }
}
?>