[hello world 動かない ][検索]

プログラミング関連で自分が調べた事をメモる

php 正規表現 スペース区切り

php正規表現を使用してスペース区切りの文字列を切り出す


PHP: preg_split - Manual

やりたいことは検索用の入力フォームがあり、入力値をスペースで区切った単語を一つずつ取得すること。
単純なスペース区切りなら

explode(' ', $keyword);

で良いのだけど、スペースが連続していたり全角空白が入力されることも考慮すると
正規表現で切り出した方がよさそうだったので preg_split を使うことにした。

foreach (preg_split('/[[:space:] ]+/u', $keyword) as $w) {
  // 処理
}

一行の入力フォームに入れられることは基本ないと思うけど、
一応スペースとして定義されているタブや改行も区切りの対象とするために[:space:]を使用し
日本語も扱うのでパターン修飾子に u を付ける。これでパターン文字列と、対象文字列を
UTF-8として扱ってくれるらしい。

openlayers geojson

OpenLayersでGeoJSONを読み込む


ちょっとソースだけ置いておく

    var createPointStyleFunction = function() {
      return function(feature, resolution) {
        var style = new ol.style.Style({
          image: new ol.style.Circle({
            radius: 5,
            fill: new ol.style.Fill({color: feature.get('color')}),
            stroke: new ol.style.Stroke({color: 'black', width: 1})
          }),
          text: new ol.style.Text({
            font: 'Normal 12px Arial',
            fill: new ol.style.Fill({color: '#000'}),
            offsetY: -10,
            text: feature.get('name')
          })
        });
        return [style];
      };
    };

    var vectorSource = new ol.source.Vector({
      url: 'example.geojson',
      format: new ol.format.GeoJSON({
        defaultDataProjection: 'EPSG:4326'
      })
    });

    var vectorLayer = new ol.layer.Vector({
      source: vectorSource,
      style: createPointStyleFunction()
    });

cakephp zip 作成 ダウンロード

CakePHPでZIPファイルをダウンロードする


PHP:5.6.3
CakePHP: 2.6.4

主にこのクラスを使って処理をするのだけど
PHP: ZipArchive - Manual

ZipArchiveにディレクトリをzipに含めるというメソッドがない。
ディレクトリを指定して、中身を全部追加したい場合は、
空のディレクトリを作るメソッドと、ファイルを追加するというメソッドを組み合わせて
処理を作る必要がある。


<?php

class DownloadController extends AppController {
  public function zip() {
    $zip = new ZipArchive();
    $zip_dir_path = TMP;
    $zip_file_name = $this->Session->id().'.zip';

    if (!$zip->open($zip_dir_path.$zip_file_name, ZipArchive::CREATE | ZIPARCHIVE::OVERWRITE)) {
      throw new InternalErrorException();
    }

    // 文字列をファイルにしてzipに追加する場合
    if (!$zip->addFromString('string.txt', '文字列をファイルにして追加')) {
      throw new InternalErrorException();
    }

    // ファイルをzipに追加する場合
    if (!$zip->addFile(TMP.'kinoko.jpg', 'image.jpg')) {
      throw new InternalErrorException();
    }

    // ディレクトリの中を全てzipに追加する場合
    $this->addDirectoryToZip($zip, TMP.'dirname');

    $zip->close();

    $this->autoRender = false;
    $this->response->type('application/zip');
    $this->response->file($zip_dir_path.$zip_file_name, array('download' => true));
    $this->response->download('test2.zip');
  }

  // ファイル名一覧を取得する
  private function getFiles($dir_path) {
    $files = array();
    if(is_dir($dir_path)) {
      $dh = opendir($dir_path);
      while($file = readdir($dh)) {
        if ($file != '.' && $file != '..') {
          array_push($files, $file);
        }
      }
      closedir($dh);
    }
    var_dump($files);
    return $files;
  }


  // ディレクトリをzipに追加する
  private function addDirectoryToZip($zip, $src_dir_path, $tar_dir_path = '') {
    // zip 内にディレクトリを作成する
    if (strlen($tar_dir_path) > 0) {
      if (!$zip->addEmptyDir($tar_dir_path)) {
        throw new InternalErrorException();
      }
    }

    // ディレクトリ内のファイルを取得する
    foreach ($this->getFiles($src_dir_path) as $file) {
      $src_file_path = $src_dir_path.'/'.$file;
      $tar_file_path = strlen($tar_dir_path) > 0 ? $tar_dir_path.'/'.$file : $file;

      if (is_dir($src_file_path)) {
        // ディレクトリの場合、中のファイルをzipに追加する
        $this->addDirectoryToZip($zip, $src_file_path, $tar_file_path);
      } else {
        // ファイルをzipに追加する
        if(!$zip->addFile($src_file_path, $tar_file_path)) {
          throw new InternalErrorException();
        }
      }
    }
  }
}

CakePHPの方は

$this->autoRender = false;
$this->response->type('application/zip');
$this->response->file($zip_dir_path.$zip_file_name, array('download' => true));
$this->response->download('test2.zip');

Viewを使用しない
Responseがzipであること宣言する
Responseにzipファイルを追加する
ダウンロードさせるファイル名を設定する

という感じで設定しているらしい。

zipを作成するディレクトリとか、削除するタイミングとかを別途考えないといけない。

php 拡張子 取得

php拡張子を取得する

$ext = pathinfo($file_path, PATHINFO_EXTENSION);

// または

$info = new SplFileInfo($file_path);
$ext = $info->getExtension();


PHP: pathinfo - Manual
PHP: SplFileInfo::getExtension - Manual


PHP: 5.6.3 で確認

No. $file_path pafhinfo SplFileInfo
1 'abc.def.ghi' 'ghi' 'ghi'
2 'abc.def.' '' ''
3 'abc.def' 'def' 'def
4 'abc.' '' ''
5 'abc' '' ''
6 '' '' ''

pathinfo と SplFileInfo で結果に差はなかった
pathinfo のマニュアルにはNo.5のような場合NULLになると書いてあるけど、空文字列返ってきた
http://php.net/manual/ja/function.pathinfo.php#example-2606

OpenLayers 3 の使い方を調べている

OpenLayers 3 を使ってみる


とりあえずポイントデータを表示させるところまで使えるようになりたい。

公式サイト
http://openlayers.org/

公式の Quick Start のソースを表示する

OpenLayers 3 - Quick Start

<!doctype html>
<html lang="en">
  <head>
    <link rel="stylesheet" href="http://openlayers.org/en/v3.5.0/css/ol.css" type="text/css">
    <style>
      .map {
        height: 400px;
        width: 100%;
      }
    </style>
    <script src="http://openlayers.org/en/v3.5.0/build/ol.js" type="text/javascript"></script>
    <title>OpenLayers 3 example</title>
  </head>
  <body>
    <h2>My Map</h2>
    <div id="map" class="map"></div>
    <script type="text/javascript">
      var map = new ol.Map({
        target: 'map',
        layers: [
          new ol.layer.Tile({
            source: new ol.source.MapQuest({layer: 'sat'})
          })
        ],
        view: new ol.View({
          center: ol.proj.transform([37.41, 8.82], 'EPSG:4326', 'EPSG:3857'),
          zoom: 4
        })
      });
    </script>
  </body>
</html>

f:id:shim0111:20150531163504j:plain

OpenStreetMapで日本を表示する

<script type="text/javascript">
  var map = new ol.Map({
    target: 'map',
    layers: [
      new ol.layer.Tile({
        source: new ol.source.OSM()
      })
    ],
    view: new ol.View({
      center: ol.proj.transform([139.5, 35.8], 'EPSG:4326', 'EPSG:3857'),
      zoom: 8
    })
  });
</script>

layersに指定できるのはImage、Tile、Vectorでこの中から選んでくれ的なことが書かれていたのでOSMを指定する。
http://openlayers.org/en/v3.5.0/apidoc/ol.source.html

表示位置の指定はview.centerで指定する。
ol.proj.transformの第1引数に[経度、緯度]で指定すればよい。
OpenStreetMapも球面メルカトル図法を使用しているので第2,3引数はこのままで良い。
詳しく知りたい場合は[空間参照 座標系 測地系 投影法 ][検索]

とりあえず現時点でこうなった
f:id:shim0111:20150531172139j:plain

ポイントを地図に追加する

少し回りくどい書き方をしているが経緯度から地図にポイントを置くまでの流れを一行ずつ

<script type="text/javascript">
  var map = new ol.Map({
    target: 'map',
    layers: [
      new ol.layer.Tile({
        source: new ol.source.OSM()
      })
    ],
    view: new ol.View({
      center: ol.proj.transform([139.5, 35.8], 'EPSG:4326', 'EPSG:3857'),
      zoom: 8
    })
  });

  // ポイントの位置(経緯度)
  var pos = [139.55, 35.85];

  // ポイントの位置(xy)
  var coord = ol.proj.transform(pos, 'EPSG:4326', 'EPSG:3857');

  // ポイントを作成する
  var point = new ol.geom.Point(coord, 'XY');

  // フィーチャを作成する
  var feature = new ol.Feature(point);

  // ソースを作成する
  var vectorSource = new ol.source.Vector();

  // ソースにフィーチャを追加する
  vectorSource.addFeature(feature);

  // レイヤを作成する
  var vectorLayer = new ol.layer.Vector();

  // レイヤにソースを追加する
  vectorLayer.setSource(vectorSource);

  // レイヤをマップに追加する
  map.addLayer(vectorLayer);

</script>

青い丸が表示された
f:id:shim0111:20150531211650j:plain

スタイルの設定や地図のコントロール等に関してはまた今度調べる。

php string isnullorempty

phpC#のString.IsNullOrEmpty()と同じ条件判断をしたい


丁寧に書けば

is_null($str) || $str == ''

で良いのだけど両方を判断するための関数はないかと調べてみたら
phpではこのようにするらしい

strlen($str) == 0

empty()という関数もあるのだけど '0' に対して true を返してしまうので注意
http://php.net/manual/ja/function.empty.php

cakephp 複数 パラメータ 値 空

引数が複数のActionに空の値を渡したい


カテゴリが一致するデータのnページ目を取得する場合、アクションをこのように作って

public function list($category, $page) {
  // 処理
}

下記のURLで野菜に関する投稿のリストの2ページ目を取得するようにした
http://nanntokakanntoka.com/appname/posts/list/yasai/2

カテゴリの指定がない(空文字列の)場合はすべての投稿のリストを取得して、さらにその4ページ目を取得したい場合
http://nanntokakanntoka.com/appname/posts/list/ココどうすればいいんだろう?/4
となって調べた

URLの指定は下記のようにする
http://nanntokakanntoka.com/appname/posts/list/category:/page:4

Viewに書く場合

echo $this->Html->link('All List', array(
  'controller' => 'posts',
  'action' => 'view',
  'category' => '',
  'page' => 4
));

このように書いておくと上記のURLへのリンクを作成してくれる

Controllerで値を受け取るのは関数の引数からではなくて
$this->request->params['named'] の中に入っているのでそこから取得する

public function list() {
  $category = $this->request->params['named']['category'];
  $page     = $this->request->params['named']['page'];
  // 処理
}