ひまわりのリアルタイム画像を取得する

現在時刻をイギリスロンドンのグリニッジ標準時刻(-9時間)にします。

$target = date("Y/m/d Hi", strtotime(date() . '-9hour'));
echo $target. "<br>";

反映に少し時間がかかっているようなので、9時間20分前にします。

$target = date("Y/m/d Hi", strtotime(date() . '-9hour -20 min'));
echo $target. "<br>";

日付と時間をそれぞれ別々に切り出します。

$date = substr($target, 0, 10);
echo $date. "<br>";

$hour = substr($target, -4, 3);
echo $hour."<br>";

時間は、下一桁は0にしたいため、substr($target, -4, 3); で、下一桁以外を切り出します。

切り出した日時をひまわりのURLに代入します。

$target = date("Y/m/d Hi", strtotime(date() . '-9hour -20 min'));
echo $target. "<br>";

$date = substr($target, 0, 10);
echo $date. "<br>";

$hour = substr($target, -4, 3);
echo $hour."<br>";


$base_url = "http://himawari8-dl.nict.go.jp/himawari8/img/D531106/thumbnail/550/".$date."/".$hour."000_0_0.png";
echo $base_url. "<br>";
?>

画像と時刻を表示します。

$target = date("Y/m/d Hi", strtotime(date() . '-9hour -20 min'));
// echo $target. "<br>";

$date = substr($target, 0, 10);
// echo $date. "<br>";

$hour = substr($target, -4, 3);
// echo $hour."<br>";


$base_url = "http://himawari8-dl.nict.go.jp/himawari8/img/D531106/thumbnail/550/".$date."/".$hour."000_0_0.png";
// echo $base_url. "<br>";

echo "<img src=\"".$base_url."\" width=\"200\" >";

$new = substr(date("Y年m月d月 H時i", strtotime(date() . '-20 min')), 0, -1);
echo "ひまわり ". $new ."0分";

20分前だと安定しないので、30分前か40分前の方がいいかもしれません。
cakeのelementに落とし込みます。

Elementのmodule switch文に雪を追加

<?php 

function convert($main){
	switch($main){
			case 'Clear':
				return "晴れ<img src=\"img/icon01.png\">";
				break;
			case 'Clouds':
				return "曇<img src=\"img/icon02.png\">";
				break;
			case 'Rain':
				return "雨<img src=\"img/icon03.png\">";
				break;
			case 'Snow':
				return "雪<img src=\"img/icon08.png\">";
				break;
			default:
				echo $main;
		}
}

function convert2($description){
	switch($description){
			case 'clear sky':
				return "晴天<br>";
				break;
			case 'scattered clouds':
				return "きれぎれに浮かんでいる雲";
				break;
			case 'broken clouds':
				return "ちぎれた雲<br>";
				break;
			case 'few clouds':
				return "少しの雲<br>";
				break;
			case 'light rain':
				return "小雨<br>";
				break;
			case 'light snow':
				return "小雪<br>";
				break;
			default:
				echo $description."<br>";
		}
}

function convert3($main){
	switch($main){
			case 'Clear':
				return "晴れ<img src=\"img/icon04.png\">";
				break;
			case 'Clouds':
				return "曇<img src=\"img/icon02.png\">";
				break;
			case 'Rain':
				return "雨<img src=\"img/icon03.png\">";
				break;
			case 'Snow':
				return "雪<img src=\"img/icon08.png\">";
				break;
			default:
				echo $main;
		}
}
?>

まーいいんじゃないでしょうか。

DBのテーブルとページ数が増えると、確かにフレームワークの方が楽に感じてきました。

全国の都市の緯度経度を設定する

基本的に国鉄の駅のlatitude, longitudeを設定していきます。
半分くらいしか行ったことなですね(照)

var markerData = [ 
  {
       name: '札幌',
       lat: 43.065381,
        lng: 141.334961,
        icon: icon[0]
 }, {
 	name: '釧路',
       lat: 42.990412,
        lng: 144.381878,
        icon: icon[1]
 }, {
 	name: '仙台',
       lat: 38.268215,
        lng: 140.869356,
        icon: icon[2]
 }, {
 	name: '新潟',
       lat: 37.916192,
        lng: 139.036413,
        icon: icon[3]
 }, {
 	name: '金沢',
       lat: 36.561325,
        lng: 136.656205,
        icon: icon[4]
 }, {
 	name: '東京',
       lat: 35.681167,
        lng: 139.767052,
        icon: icon[5]
 }, {
        name: '横浜',
     	lat: 35.469716,
        lng: 139.629184,
        icon: icon[6]
 }, {
 	name: '名古屋',
       lat: 35.181446,
        lng: 136.906398,
        icon: icon[7]
 }, {
 	name: '大阪',
       lat: 34.702485,
        lng: 135.495951,
        icon: icon[8]
 }, {
 	name: '広島',
       lat: 34.39779,
        lng: 132.47534,
        icon: icon[9]
 }, {
 	name: '高知',
       lat: 33.567697,
        lng: 133.546985,
        icon: icon[10]
 }, {
 	name: '福岡',
       lat: 33.590355,
        lng: 130.401716,
        icon: icon[11]
 }, {
 	name: '鹿児島',
       lat: 31.601456,
        lng: 130.563018,
        icon: icon[12]
 }, {
        name: '那覇',
     lat: 26.212312,
      lng: 127.679157,
      icon: icon[13]
 }
];

綺麗に反映されているようです。

Controllerで全国の都市のテーブルを引っ張る

NationwidesController.phpを作ります。

<?php

namespace App\Controller;

use Cake\ORM\TableRegistry;  

class NationwidesController extends AppController
{	
	public function initialize()
    {
         parent::initialize();
         $this->Sapporos = TableRegistry::get('sapporos');
         $this->Kushiros = TableRegistry::get('kushiros');
         $this->Sendais = TableRegistry::get('sendais');
         $this->Niigatas = TableRegistry::get('niigatas');
         $this->Kanazawas = TableRegistry::get('kanazawas');
         $this->Yokohamas = TableRegistry::get('Yokohamas');
         $this->Marunouchis = TableRegistry::get('Marunouchis');
         $this->Nagoyas = TableRegistry::get('nagoyas');
         $this->Osakas = TableRegistry::get('osakas');
         $this->Hiroshimas = TableRegistry::get('hiroshimas');
         $this->Kochis = TableRegistry::get('kochis');
         $this->Fukuokas = TableRegistry::get('fukuokas');
         $this->Kagoshimas = TableRegistry::get('kagoshimas');
         $this->Nahas = TableRegistry::get('nahas');
    }

	public function index()
	{
		$this->viewBuilder()->layout('my_layout');
		$now = date("Y-m-d H:i:s");
		$params = array(
		    'conditions' => array(
		        'forecast >' => $now, 
		    ),
		);
		$sapporos = $this->Sapporos->find('all', $params)->limit(8);
		$kushiros = $this->Kushiros->find('all', $params)->limit(8);
		$sendais = $this->Sendais->find('all', $params)->limit(8);
		$niigatas = $this->Niigatas->find('all', $params)->limit(8);
		$kanazawas = $this->Kanazawas->find('all', $params)->limit(8);
		$marunouchis = $this->Marunouchis->find('all', $params)->limit(8);
		$yokohamas = $this->Yokohamas->find('all', $params)->limit(8);
		$nagoyas = $this->Nagoyas->find('all', $params)->limit(8);
		$osakas = $this->Osakas->find('all', $params)->limit(8);
		$hiroshimas = $this->Hiroshimas->find('all', $params)->limit(8);
		$kochis = $this->Kochis->find('all', $params)->limit(8);
		$fukuokas = $this->Fukuokas->find('all', $params)->limit(8);
		$kagoshimas = $this->Kagoshimas->find('all', $params)->limit(8);
		$nahas = $this->Nahas->find('all', $params)->limit(8);
		$this->set(compact('sapporos'));
		$this->set(compact('kushiros'));
		$this->set(compact('sendais'));
		$this->set(compact('niigatas'));
		$this->set(compact('kanazawas'));	
		$this->set(compact('marunouchis'));
		$this->set(compact('yokohamas'));
		$this->set(compact('nagoyas'));
		$this->set(compact('osakas'));
		$this->set(compact('hiroshimas'));
		$this->set(compact('kochis'));
		$this->set(compact('fukuokas'));
		$this->set(compact('kagoshimas'));
		$this->set(compact('nahas'));
	}
}
?>

viewにちゃんとデータが入っているようです。
釧路-7.5°C って本当でしょうか? ん?

全国の都市のテーブルをつくる

city.list.jsonから、都市名を抽出します。
Sapporo-shi, Kushiro, Sendai-shi, Niigata-shi,Kanazawa-shi
Nagoya-shi, Osaka-shi, Hiroshima-shi, Kochi-shi, Fukuoka-shi
Kagoshima-shi, Naha-shi

それぞれ、cake用に、sをつけてテーブルをつくります。

create table weather.nahas(
	id int unsigned auto_increment primary key,
	forecast datetime,
	main varchar(255),
	description varchar(255),
	temp float,
	humidity int,
	cloud int,
	speed float,
	created datetime default null
);

sapporos, kushiros, sendais, niigatas, kanazawas, nagoyas,
osakas, hiroshimas, kochis, fukuokas, kagoshimas, nahas

kushiroは二つあるので注意が必要ですね。longitudeが144の方が北海度の釧路です。

{
    "id": 2129376,
    "name": "Kushiro",
    "country": "JP",
    "coord": {
      "lon": 144.374725,
      "lat": 42.974998
    }

{
    "id": 1858025,
    "name": "Kushiro",
    "country": "JP",
    "coord": {
      "lon": 135.416672,
      "lat": 34.799999
    }

テーブルが出来たので、データをDBに入れていきます。
まず、sapporoから。

問題なく入ってますね。

問題なさそうなので、一気に入れます。と思ったら、早速レコードに重複が出たのでやり直しのようです。(涙)
forecast datetime unique 修正にして、改めて一気にいれます。

<?php
require "sapporos.php";
require "kushiros.php";
require "sendais.php";
require "niigatas.php";
require "kanazawas.php";
require "marunouchis.php";
require "yokohamas.php";
require "nagoyas.php";
require "osakas.php";
require "hiroshimas.php";
require "kochis.php";
require "fukuokas.php";
require "kagoshimas.php";
require "nahas.php";
?>

面倒そうでしたが、やってみると案外サクサクいきましたね。

controllerのlimitの使い方

findの後に->limit(n)で繋げます。

public function index()
	{
		$this->viewBuilder()->layout('my_layout');
		$now = date("Y-m-d H:i:s");
		$params = array(
		    'conditions' => array(
		        'forecast >' => $now, 
		    ),
		);
		$marunouchis = $this->Marunouchis->find('all', $params)->limit(3);
		$yokohamas = $this->Yokohamas->find('all', $params);	
		$this->set(compact('marunouchis'));
		$this->set(compact('yokohamas'));
	}
}

$paramのconditionsに追記するとエラーになりますね。

weather mapの情報を元に、google mapのアイコンを変える

埼玉のテーブルはまだ作っていませんが、暫定として、

<style>
#map {
		height: 250px;
		width: 100%;
        font-size:small;
        margin-bottom:10px;
	}
</style>

<?php
	$this->assign('title', '首都圏の天気予報');
?>
<?= $this->element('module'); ?>

<h1>首都圏の今日明日の天気予報</h1>
<div id="map"></div>
<b><a href="marunouchis">東京</a></b>
<table class="table1">
	<tr>
	<?php 
	$i = 1;
	foreach ($marunouchis as $marunouchi){
	if($i < 9){
	echo "<td width=\"150px\">";
	echo h($marunouchi->forecast)."<br>";
	$date = h($marunouchi->forecast);
	$result = substr($date, -8);
	if($result == ' 9:00 PM' or $result == '12:00 AM' or $result == ' 3:00 AM'){
	echo convert3(($marunouchi->main))."<br>";
	} else {
	echo convert(($marunouchi->main))."<br>";
	}
	echo convert2(($marunouchi->description))."<br>";
	echo "気温".h($marunouchi->temp)."°C<br>";
	echo "湿度". h($marunouchi->humidity)."%<br>";
	echo "雲の量".h($marunouchi->cloud)."<br>";
	echo "風速".h($marunouchi->speed)."m<br>";
	echo "<td>";
	if($result == '12:00 PM'){
		$mmain = json_encode(h($marunouchi->main));
	}
	}
	$i++;
	}
	?>
	</tr>
</table>

<b><a href="yokohamas">横浜</a></b>
<table class="table1">
	<tr>
	<?php 
	$i = 1;
	foreach ($yokohamas as $yokohama){
	if($i < 9){
		echo "<td width=\"150px\">";
		echo h($yokohama->forecast)."<br>";
		$date = h($yokohama->forecast);
		$result = substr($date, -8);
		if($result == ' 9:00 PM' or $result == '12:00 AM' or $result == ' 3:00 AM'){
		$value = convert3(($yokohama->main))."<br>";
		} else {
		$value = convert(($yokohama->main))."<br>";
		}
		echo $value;
		echo convert2(($yokohama->description))."<br>";
		echo "気温".h($yokohama->temp)."°C<br>";
		echo "湿度". h($yokohama->humidity)."%<br>";
		echo "雲の量".h($yokohama->cloud)."<br>";
		echo "風速".h($yokohama->speed)."m<br>";
		echo "<td>";
		if($result == '12:00 PM'){
		$ymain = json_encode(h($yokohama->main));
		}
	  }
	$i++;
	}
	?>
	</tr>
</table>

<script>
var mmain = JSON.parse('<?php echo $mmain; ?>');
if(mmain =='Clear'){
 var micon = '/img/icon05.png'
}else if(ymain =='Clouds'){
 var micon = '/img/icon06.png'
} else{
 var micon = '/img/icon07.png'
}
var ymain = JSON.parse('<?php echo $ymain; ?>');
if(ymain =='Clear'){
 var yicon = '/img/icon05.png'
}else if(ymain =='Clouds'){
 var yicon = '/img/icon06.png'
} else{
 var yicon = '/img/icon07.png'
}

var map;
var marker = [];
var infoWindow = [];
var markerData = [ 
  {
       name: '東京',
       lat: 35.681167,
        lng: 139.767052,
        icon: micon
 }, {
        name: '横浜',
     	lat: 35.469716,
        lng: 139.629184,
        icon: yicon
 }, {
        name: '埼玉',
     lat: 35.861729,
      lng: 139.645482,
      icon: '/img/icon06.png'
 }
];
 
function initMap() {
    var mapLatLng = new google.maps.LatLng({lat: 35.681167, lng: 139.767052}); 
   map = new google.maps.Map(document.getElementById('map'), { 
     center: mapLatLng, 
      zoom: 9
   });
 
 // マーカー毎の処理
 for (var i = 0; i < markerData.length; i++) {
        markerLatLng = new google.maps.LatLng({lat: markerData&#91;i&#93;&#91;'lat'&#93;, lng: markerData&#91;i&#93;&#91;'lng'&#93;});
        marker&#91;i&#93; = new google.maps.Marker({ 
         position: markerLatLng, 
            map: map
       });
 
     infoWindow&#91;i&#93; = new google.maps.InfoWindow({ 
         content: '<div class="map">' + markerData[i]['name'] + '</div>' 
       });
 
     markerEvent(i);
 }
   for (var i = 0; i < markerData.length; i++) {
   marker&#91;i&#93;.setOptions({
        icon: {
         url: markerData&#91;i&#93;&#91;'icon'&#93;
       }
   });
   }
}
 
function markerEvent(i) {
    marker&#91;i&#93;.addListener('click', function() {
      infoWindow&#91;i&#93;.open(map, marker&#91;i&#93;);
  });
}
</script>
<script async defer
src = "https:maps.googleapis.com/maps/api/js?key=not watch&callback=initMap">
</script>

大分できてきました。

あとは全国の天気ですね。

cakeのviewでjavascript

scriptタグで書けば、普通に表示されます。

<script>
var map;
    function initMap(){
        map = new google.maps.Map(document.getElementById('map'),{
            center:{lat: 35.681167, lng: 139.767052},
            zoom: 8
        });
    }
</script>
<script async defer
src = "https:maps.googleapis.com/maps/api/js?key=&callback=initMap">
</script>

天気のラベルを渡したいですね。

cakeで複数のテーブルを参照するページをつくる

例えば、丸の内と横浜のデータを引っ張て来て、首都圏の天気として表示させてたいとする。
その場合は、controllerで “use Cake\ORM\TableRegistry;” を使って、テーブルを定義する。

<?php

namespace App\Controller;

use Cake\ORM\TableRegistry;  

class TestsController extends AppController
{	
	public function initialize()
    {
         parent::initialize();
         $this->Yokohamas = TableRegistry::get('Yokohamas');
         $this->Marunouchis = TableRegistry::get('Marunouchis');
    }

	public function index()
	{
		$this->viewBuilder()->layout('my_layout');
		$now = date("Y-m-d H:i:s");
		$params = array(
		    'conditions' => array(
		        'id' => '1', 
		    ),
		);
		$marunouchis = $this->Marunouchis->find('all', $params);
		$yokohamas = $this->Yokohamas->find('all', $params);	
		$this->set(compact('marunouchis'));
		$this->set(compact('yokohamas'));
	}
}
?>

viewでは、marunouchisとyokohamasを呼び出せる。

cakeでデータベースを参照しないページをつくる

src/Templateに対象フォルダとindex.ctpをつくります。

controllerをつくります。

<?php
namespace App\Controller;
class TestsController extends AppController
{	
	var $name = 'Tests';
	var $useTable = false;
	public function index()
	{
		$this->viewBuilder()->layout('my_layout');		
	}
}
?>

表示されました。modelはつくらなくても、エラーは表示されません。