February 21, 2014

Vagrant + Ubuntu13.10でChefのレシピが実行できない

久々に、Vagrant + Ubuntu13.04なオレオレ開発環境を再構築しようとしてみたら、Chefのレシピが実行できませんでした。一見、ハングアップしているような状態になりました。使っていたVirtualBoxのバージョンは4.3.6です。

以下を参考にして、"vagrant-vbguest"というプラグインをインストールしたら、実行できるようになりました。感謝ですm(_ _)m
http://stackoverflow.com/questions/20022110/chef-fails-to-run-because-cookbooks-folder-is-not-accessible
http://yosiwo.lowtech.ne.jp/?p=1429

$ vagrant plugin install vagrant-vbguest

February 16, 2014

FuelPHP & CodeIgniter ユーザの集い #3 で発表予定だったスライドをGitHubにアップしてあります

FuelPHP & CodeIgniter ユーザの集い #3
http://atnd.org/events/46859

FuelPHPをRocketeerで簡単にデプロイする
http://mamor.github.io/reveal-fuel-rocketeer

大雪の影響で、申し訳ありませんがキャンセルさせて頂きました。スライドはせっかく作ったので、別の機会に発表できれば良いなと思います。

February 9, 2014

AngularJSで、Ajaxで取得したデータをng-repeatする

追記:
外部APIとの通信は $resource を使ったほうが良いかもしれません。
http://docs.angularjs.org/api/ngResource/service/$resource

--

気になっていたAngularJSを、少し触ってみました。試しに、このブログのフィード情報をAjaxで取得して、その結果をng-repeatして表示してみました。

以下、動作サンプルです。(AngularJSとしての書き方には、まだまだ自信が有りません。。。)
http://jsfiddle.net/mamor/wuwgr/1/

クロスドメイン問題を解決する為に、jQueryを併用しています。(AngularJSの$httpからだとどうにも解決できなかったので。)
あと、 $scope.$apply() 無しに angular.copy(entries, $scope.entries) すると上手くいきませんでした。
参考: http://stackoverflow.com/questions/17901391/when-i-update-my-model-in-ng-repeat-the-directive-ng-show-does-not-change

ところどころでハマりつつも、初日にしてはわりとスムーズに動かせたので、AngularJS好きかも。

February 8, 2014

PHPExcelでOpenOfficeの表計算ドキュメントを読み込んでみる

PHPExcelという、PHPでエクセルやOpenOfficeの表計算ドキュメントを読み込めるライブラリがありました。
https://github.com/PHPOffice/PHPExcel
https://packagist.org/packages/phpoffice/phpexcel

試しに、OpenOfficeの表計算ドキュメントを読み込んでみました。

1. PHPExcelをインストールします。以下はcomposer.jsonの例です。
{
    "require": {
        "phpoffice/phpexcel": "1.*"
    }
}


2. 1シートのみを前提で読み込んでます。

シートはこんな感じです。
* 面倒なので直しませんが"テストB5"じゃなくて"テストB6"でしたね。。。

ソースです。
<?php

require_once('vendor/autoload.php');

$ods = PHPExcel_IOFactory::load("test.ods");

$ods->setActiveSheetIndex(0);
$sheet = $ods->getActiveSheet();

$highestRowIndex = $sheet->getHighestRow();
$highestColumnIndex = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn());

$data = [];
for ($i = 1; $i <= $highestRowIndex; $i++) {
    $values = [];
    for ($j = 0; $j < $highestColumnIndex; $j++) {
        $values[] = $sheet->getCellByColumnAndRow($j, $i)->getValue();
    }
    $data[] = $values;
}

var_dump($data);
結果です。
array(6) {
  [0]=>
  array(4) {
    [0]=>
    string(11) "テストA1"
    [1]=>
    string(11) "テストB1"
    [2]=>
    NULL
    [3]=>
    string(11) "テストD1"
  }
  [1]=>
  array(4) {
    [0]=>
    string(11) "テストA2"
    [1]=>
    string(11) "テストB2"
    [2]=>
    NULL
    [3]=>
    NULL
  }
  [2]=>
  array(4) {
    [0]=>
    NULL
    [1]=>
    NULL
    [2]=>
    string(11) "テストC3"
    [3]=>
    NULL
  }
  [3]=>
  array(4) {
    [0]=>
    NULL
    [1]=>
    NULL
    [2]=>
    NULL
    [3]=>
    NULL
  }
  [4]=>
  array(4) {
    [0]=>
    NULL
    [1]=>
    NULL
    [2]=>
    NULL
    [3]=>
    NULL
  }
  [5]=>
  array(4) {
    [0]=>
    NULL
    [1]=>
    string(11) "テストB5"
    [2]=>
    NULL
    [3]=>
    NULL
  }
}


3. 複数シートの場合もやってみました。

シート構成は意地悪な感じで
  • 1シート目は先程と同様
  • 2シート目は空
  • 3シート目は空
  • 4シート目はこんな感じです

  • 5シート目は空

です。

ソースです。
<?php

require_once('vendor/autoload.php');

$ods = PHPExcel_IOFactory::load("test.ods");

$allData = [];
$sheets = $ods->getAllSheets();
foreach ($sheets as $sheet) {
    /** @var PHPExcel_Worksheet $sheet */

    $highestRowIndex = $sheet->getHighestRow();
    $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn());

    $data = [];
    for ($i = 1; $i <= $highestRowIndex; $i++) {
        $values = [];
        for ($j = 0; $j < $highestColumnIndex; $j++) {
            $values[] = $sheet->getCellByColumnAndRow($j, $i)->getValue();
        }
        $data[] = $values;
    }

    $allData[] = $data;
}

var_dump($allData);
結果です。
array(6) {
  [0]=>
  array(6) {
    [0]=>
    array(4) {
      [0]=>
      string(11) "テストA1"
      [1]=>
      string(11) "テストB1"
      [2]=>
      NULL
      [3]=>
      string(11) "テストD1"
    }
    [1]=>
    array(4) {
      [0]=>
      string(11) "テストA2"
      [1]=>
      string(11) "テストB2"
      [2]=>
      NULL
      [3]=>
      NULL
    }
    [2]=>
    array(4) {
      [0]=>
      NULL
      [1]=>
      NULL
      [2]=>
      string(11) "テストC3"
      [3]=>
      NULL
    }
    [3]=>
    array(4) {
      [0]=>
      NULL
      [1]=>
      NULL
      [2]=>
      NULL
      [3]=>
      NULL
    }
    [4]=>
    array(4) {
      [0]=>
      NULL
      [1]=>
      NULL
      [2]=>
      NULL
      [3]=>
      NULL
    }
    [5]=>
    array(4) {
      [0]=>
      NULL
      [1]=>
      string(11) "テストB5"
      [2]=>
      NULL
      [3]=>
      NULL
    }
  }
  [1]=>
  array(1) {
    [0]=>
    array(1) {
      [0]=>
      NULL
    }
  }
  [2]=>
  array(1) {
    [0]=>
    array(1) {
      [0]=>
      NULL
    }
  }
  [3]=>
  array(6) {
    [0]=>
    array(4) {
      [0]=>
      NULL
      [1]=>
      string(11) "テストB1"
      [2]=>
      string(11) "テストC1"
      [3]=>
      NULL
    }
    [1]=>
    array(4) {
      [0]=>
      string(11) "テストA2"
      [1]=>
      string(11) "テストB2"
      [2]=>
      string(11) "テストC2"
      [3]=>
      NULL
    }
    [2]=>
    array(4) {
      [0]=>
      NULL
      [1]=>
      NULL
      [2]=>
      NULL
      [3]=>
      string(11) "テストD3"
    }
    [3]=>
    array(4) {
      [0]=>
      NULL
      [1]=>
      NULL
      [2]=>
      NULL
      [3]=>
      NULL
    }
    [4]=>
    array(4) {
      [0]=>
      NULL
      [1]=>
      NULL
      [2]=>
      NULL
      [3]=>
      NULL
    }
    [5]=>
    array(4) {
      [0]=>
      NULL
      [1]=>
      NULL
      [2]=>
      string(11) "テストC6"
      [3]=>
      NULL
    }
  }
  [4]=>
  array(1) {
    [0]=>
    array(1) {
      [0]=>
      NULL
    }
  }
  [5]=>
  array(1) {
    [0]=>
    array(1) {
      [0]=>
      NULL
    }
  }
}
簡単ですね。複数シートの場合、どうも1シート分余計なデータが有りますが、まあどうにでもなるかなと思います。

February 6, 2014

composer initコマンドを使ってみる

composer initコマンドってあるのかなーと思って試しに打ってみたらあったので使ってみました。パッケージ名で検索して、バージョン指定しつつcomposer.jsonを作れるのが良いなーと思いました。

以下は、FacebookのPHP SDKを検索して3.2.*指定しています。
$ composer init


  Welcome to the Composer config generator



This command will guide you through creating your composer.json config.

Package name (<vendor>/<name>) [admin/facebook]: xxx/yyy
Description []: desc
Author [mamor <mamor@example.com>]:
Minimum Stability []:
License []:

Define your dependencies.

Would you like to define your dependencies (require) interactively [yes]?
Search for a package []: facebook

Found 15 packages matching facebook

   [0] facebook/webdriver
   [1] facebook/xhprof
   [2] kdyby/facebook
   [3] opauth/facebook
   [4] facebook/php-sdk
   [5] friendsofsymfony/facebook-bundle
   [6] euskadi31/facebook
   [7] boparaiamrit/facebook
   [8] playground/facebook
   [9] thomaswelton/facebook-php-sdk
  [10] grom/facebook-service-provider
  [11] thomaswelton/laravel-facebook
  [12] eden/facebook
  [13] culshaw/facebook
  [14] tobiassjosten/facebook-service-provider

Enter package # to add, or the complete package name if it is not listed []: 4
Enter the version constraint to require []: 3.2.*
Search for a package []:
Would you like to define your dev dependencies (require-dev) interactively [yes]? no

{
    "name": "xxx/yyy",
    "description": "desc",
    "require": {
        "facebook/php-sdk": "3.2.*"
    },
    "authors": [
        {
            "name": "mamor",
            "email": "mamor@example.com"
        }
    ]
}

Do you confirm generation [yes]?

February 2, 2014

Jasmine 1.xを2.xにしたら色々エラーになったので対応メモ

JSのテスティングフレームワークにはJasmineを使っていて、実行はgrunt-contrib-jasmineでやってます。
https://github.com/gruntjs/grunt-contrib-jasmine

grunt-contrib-jasmineはv0.6から、Jasmine 2.xを使用するようになったようです。
https://github.com/gruntjs/grunt-contrib-jasmine/blob/master/CHANGELOG

その関係で、ポツポツとエラーになったので、対応をメモしておきます。(単なる比較メモですが。)

先に、Jasmineの 1.x と 2.x のドキュメントは以下です。
http://jasmine.github.io/


1. spyOnでN回目の呼び出しのコンテキストを取得
// 1.x
spyOn($.fn, 'xxx')
expect($.fn.xxx.calls[0].args[0]).toEqual('yyy')

// 2.x
spyOn($.fn, 'xxx')
expect($.fn.xxx.calls.all()[0].args[0]).toEqual('yyy')
2. callCount
// 1.x
expect(object.method.callCount).toEqual(3)

// 2.x
expect(object.method.calls.count()).toEqual(3)
3. createSpy()のandReturn()
// 1.x
jasmine.createSpy().andReturn('xxx')

// 2.x
jasmine.createSpy().and.returnValue('xxx')
4. createSpy()のandCallThrough()
// 1.x
spyOn(Object.prototype, 'xxx').andCallThrough()

// 2.x
spyOn(Object.prototype, 'xxx').and.callThrough()
5. createSpy()のandCallFake()
// 1.x
spyOn(Object.prototype, 'xxx').andCallFake ->

// 2.x
spyOn(Object.prototype, 'xxx').and.callFake ->
P.S.
ホントは一通り2.xな書き方を理解して書きなおしたほうが良いんだろうけど。。。あと、一部、CoffeeScriptな書き方が混じっています。