Web的な何か

JavaとかPHPとかやってます。最近はAndroidばっかやってます。

【Android】アラートダイアログからレイアウトXMLの要素にアクセスするとNullPointerExceptionになった時の対処法

簡単な伝言アプリを作っている時に、伝言内容を入力させるためアラートダイアログにEditTextをセットした後、
getTextで入力された内容を取得する時にNullPointerExceptionが飛んできて悩んでしまった。

色々調べてみて試していたら以下のサイトで紹介されている記事で解決した。

http://d.hatena.ne.jp/language_and_engineering/20110908/p1

http://d.hatena.ne.jp/language_and_engineering/20110908/p1

今回の自分の場合はLayoutInflaterで読み込んでViewにレイアウトXMLをセットしたまではいいけど、入力内容を読み込む時にViewの変数からgetTextしていなかったのが原因らしかった。

インポートしてきたAndroidのプロジェクトを実行するとNoClassDefFoundErrorが出てきてしまう。

またハマりそうなのでメモ

Androidアプリを勉強してみたかったのでこんなサンプル本を買ってみた。
http://www.amazon.co.jp/dp/4883377806

早速サンプルをインポートしてみると、まず早速コンパイルエラーが出てきた。
これの対処はプロジェクト名を右クリック→Javaコンパイラーの中の「プロジェクト固有の設定を可能にする」にチェックを入れてから、コンパイラー準拠レベルを1.7から1.6へ下げればOK。


これで正常に通ったと思ったら今度は「NoClassDefFoundError」というエラーが出てきて、アプリが正常な動作をしなかった。
eclipseはエラー吐かないのになんでだろうと心が折れつつも調べていたらこれを見つけた。

http://blog.2maru.com/2012/03/22/%E3%80%90%E7%B7%8A%E6%80%A5%E3%80%91android-sdk-r16%E2%86%92r17%E3%81%AB%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%83%E3%83%97%E3%81%99%E3%82%8B%E3%81%A8eclipse%E3%81%A7%E3%82%A2/

この方法を試したら無事動作するようになった!
まさかこんあ落とし穴があったなんてー!

楽天商品検索API で商品情報を取得してみるプログラムを書いてみた

割と久しぶりな投稿になりそう。
以前記事では商品をデータベースに登録する際に関数を掲載していたけれど、今回は処理全体を作ってみた。
ソースはGitHubにあげたので詳しくはそちらを確認して欲しい。

https://github.com/chuchuross/rakutenAPI


大まかな処理の流れとして、取得してきた情報のidからデータベースに参照して、登録されていないものをデータベースに登録していく。
登録された商品の最新10件の中から、名前が似ている商品があれば関連商品として商品どうしをリンクさせる。
商品のカテゴリが登録されていなければ新規カテゴリとして追加する。

因みに類似商品を参照する10件という数字は20件や30件といった数値にかえても特に問題はないはず。
まだ書き直せるところはありぞうなのでちょっとずつ直していく予定。

MavenをEclipseで使う方法をまとめてみた

Mavenの設定の仕方を忘れないために、今回はほとんど完全自分用に書いてみる。

Mavenってどんなもの?
ソフトウェアプロジェクト管理ツールで、POMを使って大量のプラグインを扱うことができる便利なもの。
このツールについての詳しい内容はTECHSCORE(テックスコア)さんの方で紹介されていたのでこちらの方を確認してみよう!


Mavenのインストール方法
※今回はWindowsでのインストール方法を書く
コマンドからインストールを行うので「msysGit」等があると良い


1.以下のURLからダウンロードすることができる。
現在の最新バージョンは3.0.4
http://maven.apache.org/download.html
f:id:chuchuross:20120310224105p:plain


2.ダウンロードしてきたファイルを解凍してきたあと適当なフォルダに置く
ここらへんは特に問題ないので画像は割愛


3.環境変数を設定する
環境変数は「コントロールパネル」→「システム」→「詳細設定タブの環境変数」から設定する事ができる。
環境変数のところまできたら以下の二つを設定する。

・「JAVA_HOME」に JDK のインストールされているディレクトリのパスを追加
・「PATH」に Maven の実行ファイルのあるディレクトリを追加する(Mavenフォルダのbinフォルダまで)

ここまで設定したらコンソールを開いて「mvn」を実行した時に色々出てくればOK


Mavenでのプロジェクト作成

cd {プロジェクトを作成したいディレクトリ}
mvn archetype:generate

上のようにコンソールを実行させると色々聞かれるので「groupId」にはパッケージ名、「artifactId」にはプロジェクト名を書いていく。
一通り書けたらcdしたディレクトリにプロジェクトのフォルダが生成されている。


eclipseにプロジェクトをインポート
eclipseの「ファイル」から「インポート」で生成したフォルダをインポートさせると完了

eclipseで"Maven Integration for Eclipse JDK Warning"とエラーが表示された時の対処法

Mavenを導入してeclipseに『m2eclipse』というプラグインを入れて再起動した時に"Maven Integration for Eclipse JDK Warning"とかこんな画面が出てくることがある。

f:id:chuchuross:20120222194716g:plain

起動する度に毎回こういった表示がでてきて困っていたので色々調べているとこういったサイトがあった。
http://d.hatena.ne.jp/paz3/20101001/1285928205

大まかに説明すると、Mavenを使うにはJava仮想マシンJREからJDKに変える必要があって、eclipse.iniの内容にJavaの実行ファイルのパスを付け加えると大丈夫みたい。
気を付けなければならないのがeclipse.iniに情報を付け加える際、必ず「-vmargs」オプションより上に記述しないと認識されない点。

今回はこの方法で対処するとエラーが出なくなった。

CSSの角丸を楽して実装!『CSS Boarder Radius』

CSS3の角丸は覚えればそんなに難しくないのだろうけど、つい忘れてしまう。
そんな事を思ってた矢先にこんなWEBサービスを見つけた。


CSS Boarder Radius
http://border-radius.com/
http://border-radius.com/

使い方は簡単で、角にある"0"の部分の数値を変更していくことで自動的にCSSが生成されるようになっている。あとは自分のファイルにコピペするだけなので特にこれといった作業はない。

生成されたデータはこんな感じ

-webkit-border-radius: 20px;
-moz-border-radius: 20px;
border-radius: 20px;


実装例はこんな感じ

PHPUnit 覚え書き その2

引き続きPHPUnitについての覚え書き。
assertにはいくつかあるようなので試してみた。

assertArrayHasKey()
配列のキーが存在しているかどうかをチェックできる。
assertArrayHasKey({存在しているか調べたいキー}, {対象の配列});

class hogeTest extends PHPUnit_Framework_TestCase
{
    
    //テスト前に行う処理
    protected $object;
    
    protected function setUp() {
        $this->object = new hoge;
    }


    //ここからテスト開始
    public function testTrial() {
        $this->assertArrayHasKey("hoge", array("hoge"=>TRUE));
    $this->assertArrayHasKey("hoge", array("huga"=>TRUE));//指定されたキーと違う場合にエラーが出る
    }
}


assertContains()
配列の値が存在しているかどうかをチェックできる。
assertContains({存在しているか調べたい値}, {対象の配列});

class hogeTest extends PHPUnit_Framework_TestCase
{
    
    //テスト前に行う処理
    protected $object;
    
    protected function setUp() {
        $this->object = new hoge;
    }


    //ここからテスト開始
    public function testTrial() {
        $this->assertContains(3, array(1, 2, 3));
    $this->assertContains(4, array(1, 2, 3));//指定された数が含まれていない場合にエラーが出る
    }
}


assertContainsOnly()
配列の中身が全て指定された型で格納されているかチェックできる。
assertContainsOnly({調べたい型}, {対象の配列});

class hogeTest extends PHPUnit_Framework_TestCase
{
    
    //テスト前に行う処理
    protected $object;
    
    protected function setUp() {
        $this->object = new hoge;
    }


    //ここからテスト開始
    public function testTrial() {
        $this->assertContainsOnly("int", array(1, 2, 3));
    $this->assertContainsOnly("string", array(1, 2, 3));//指定された型と違うとエラーが出る
    }
}


assertCount()
配列の個数が指定された数かどうかをチェックできる。
assertCount({調べたい要素数}, {対象の配列});

class hogeTest extends PHPUnit_Framework_TestCase
{
    
    //テスト前に行う処理
    protected $object;
    
    protected function setUp() {
        $this->object = new hoge;
    }


    //ここからテスト開始
    public function testTrial() {
        $this->assertCount(3, array(1, 2, 3));
    $this->assertCount(1, array(1, 2, 3));//指定された数と違うとエラーが出る
    }
}


assertEquals()
引数に入れられた変数二つが等しいかどうかをチェックできる。
assertEquals({比べたい変数1}, {比べたい変数2});

class hogeTest extends PHPUnit_Framework_TestCase
{
    
    //テスト前に行う処理
    protected $object;
    
    protected function setUp() {
        $this->object = new hoge;
    }


    //ここからテスト開始
    public function testTrial() {
        $this->assertEquals("hoge", "hoge"));
        $this->assertEquals("hoge", "huga"));//内容が違うとエラーが出る
    }
}

PHPUnit 覚え書き

PHPUnitを使う機会ができたのでまずPHPUnitについて調べてみた。


PHPUnitって何だろう
PHPのテスト用ツールで単体テストを行うことができる。
作成したクラスからPHPUnit内のクラスを通してテストフォルダにテスト用のクラスを作成し、それを実行することで正常に動作できているかどうかを確認することができる。

単体テスト:
クラスやメソッド単位で動作を確認していく作業のこと。


インストール自体は簡単で以下の2行記述するだけで可能。

pear config-set auto_discover 1
pear install pear.phpunit.de/PHPUnit

インストール処理が終了したら以下のコマンドでバージョンを確認して、表示されていたらインストール完了。

phpunit --version


テスト用スクリプトの作成
今回作ってみたスクリプトはこんな感じ

<?php
class hoge{
    /**
     * @assert ("あ-い-う") == "あ, い, う"
     * @assert ("あ-い-う") == "あいう"
     * @assert ("a-b") == "a, b"
     */
    public function trial($str)
    {
        //ハイフンで区切られた文字をカンマで区切る
        $str = str_replace("-", ", ", $str);
        return $str;
    }
}
?>

動作は"trial"という名前の関数を用意して、-(ハイフン)で区切られた文字をカンマに変換する処理が書かれている。

"@assert"と書かれている部分はテストする項目で、例えば関数trialの$strの引数に"あ-い-う"が入った時に、出力が"あ, い, う"と表示されるかどうか、といった処理がテストの時に行われる。


assertの記述を二通りほど見つけた

  1. /* プログラムのコメント内 @assert {テスト内容} */
  2. assertEquals()


PHPUnitを通して作成されたテスト用スクリプトはこんな感じ。

<?php

require_once dirname(__FILE__) . '/../index.php';

/**
 * Test class for hoge.
 * Generated by PHPUnit on 2012-02-14 at 17:30:53.
 */
class hogeTest extends PHPUnit_Framework_TestCase {

    /**
     * @var hoge
     */
    protected $object;

    /**
     * Sets up the fixture, for example, opens a network connection.
     * This method is called before a test is executed.
     */
    protected function setUp() {
        $this->object = new hoge;
    }

    /**
     * Tears down the fixture, for example, closes a network connection.
     * This method is called after a test is executed.
     */
    protected function tearDown() {
        
    }

    /**
     * Generated from @assert ("あ-い-う") == "あ, い, う".
     *
     * @covers hoge::trial
     */
    public function testTrial() {
        $this->assertEquals(
                "あ, い, う", $this->object->trial("あ-い-う")
        );
    }

    /**
     * Generated from @assert ("あ-い-う") == "あいう".
     *
     * @covers hoge::trial
     */
    public function testTrial2() {
        $this->assertEquals(
                "あいう", $this->object->trial("あ-い-う")
        );
    }

    /**
     * Generated from @assert ("a-b") == "a, b".
     *
     * @covers hoge::trial
     */
    public function testTrial3() {
        $this->assertEquals(
                "a, b", $this->object->trial("a-b")
        );
    }

}

?>

これをNetbeansなどで動作させると二番目に書かれた「@assert ("あ-い-う") == "あいう"」の項目だけエラーが表示される。思ったよりも便利そう。

classとか気づいたこと

今までclassについて深く勉強していなかったので、改めて確認してみることにした。
今回簡単に作ってみたclassは以下の通り。
動作は"createArray"で作られた列をforeachで一覧に出力している。

//classのテスト
class Test
{
    public static $staticTest = "staticの動作テスト\n";

    public function createArray()
    {
        $res = array(
            "列一個目",
            "列二個目",
            "列三個目",
            "列四個目"
        );
        return $res;
    }

  public function testEcho()
    {
        $array = $this->createArray();
        foreach ($array as $val){
            echo $val, "\n";
        }
    }
}


作ったclassをこのように呼び出してみた。

echo Test::$staticTest;//staticのテスト
$class = new Test();//オブジェクトの読み込み
$class->testEcho();//class内関数の呼出

一行目はスコープ演算子を利用して変数を出力させていて、二行目は$classにインスタンスを生成してオブジェクトとして読み込ませており、三行目でアロー演算子を利用してclass内の関数を呼び出している。

これらを動作させると、このように表示される。

staticの動作テスト
列一個目
列二個目
列三個目
列四個目

"Test::$staticTest"の部分はスコープ定義演算子というものらしく、staticや定義されたメソッドなどをインスタンスの生成をしなくても呼び出すことができるそうだ。
もちろん、staticなどが含まれていないメソッドを呼び出すとエラーが出る。


クラスの継承
次にclassの継承についても学習してみた。
今回は先ほど作った"Test"classを継承して以下のclassを作る。

//class 継承
class TestEX extends Test
{
    public function createArray()
    {
        $res = array(
          "EX1個目",
          "EX2個目",  
          "EX3個目",
          "EX4個目"
        );
        
        return $res;
    }
}

内容は簡単で、先ほどのclass内に存在している"createArray"をオーバーライドしている。

オーバーライド:
継承する親classのメソッドを上書きすること


継承したclassを以下のように利用してみた。

echo TestEx::$staticTest//コメント受けて追加してみました
$exTest = new TestEx();
echo $exTest->testEcho();

一行目でインスタンスを生成し、二行目でオーバーライドした関数を呼び出している。
出力は以下に変化する。

EX1個目
EX2個目
EX3個目
EX4個目

楽天商品検索API (楽天ウェブサービス)で商品情報を取得してみる

現在制作しているサイトで楽天ウェブサービスを使用する事になったので、作った関数などを張り付けてみる。

検索にヒットさせやすくするために色々調べてみた結果、全文検索というものが気になったけれどレンタルサーバーでは導入できなさそうだったので簡易的な処理を加えてみた。

//検索文字作成(カナに変換)

 

function kana($str){

//削除する条件を設定

$a = array(

'!', '”', '#', '$', '%', '&', '’', '(', ')', '=', '〜', '|', '-', '^', '¥','`', '{', '@', '[', '+', '*', '}', ';', ':', ']', '<', '>', '?', '_', ',', '.', '/', '「', '」', '・',

'!', '"', '#', '\$', '%', '&', "'", '\(', '\)', '=', '~', '\|', '-', '\^', '\\\\','`', '\{', '@' , '\[', '\+', '\*', '}', ';', ':', ']', '<', '>', '\?', '_', ',', '\.', '/', '「', '」', '・',

'♪', '☆', '★'

);

$str = str_replace($a, " ", $str);

 

//かな→カナ, 全角英数→半角英数変換

return mb_convert_kana( $str, "asKC", "UTF-8" );

}

■使用法

kana( [ここに取得した商品名を入れる] )例:うたの☆プリンスさまっ♪Debut

       ↓

ウタノ プリンスサマッ Debut

発売日を取得するとYYYY年MM月DD日といった形で取得されるので、データベースにDATE型(YYYY-MM-DD)で格納するための変換処理。

上旬・中旬・下旬・未定などの商品を判別させるためにそれぞれ98、97、96、99と番号を振っている。

//年月日→YYYY-MM-DD変換

function changeDate($str){

$a = str_replace(array("年", "月", "日"), array("-", "-", ""), $str);

$a = explode("-", $a);

switch( count($a) ):

case 1://年内発売予定の商品

$relDate = "99-99-99";

break;

 

case 2://月内発売予定の商品

$relDate = sprintf("%4d-99-99", $a[0]);//YYYY年未定

break;

 

case 3://発売日が決まっている商品

if($a[2] == ""){

$relDate = sprintf("%04d-%02d-99", $a[0], $a[1]);//YYYY年mm月予定

}elseif($a[2] == "上旬" || $a[2] == "頃"){

$relDate = sprintf("%04d-%02d-98", $a[0], $a[1]);//YYYY年mm月上旬 or 頃

}elseif($a[2] == "中旬"){

$relDate = sprintf("%04d-%02d-97", $a[0], $a[1]);//YYYY年mm月中旬

}elseif($a[2] == "下旬"){

$relDate = sprintf("%04d-%02d-96", $a[0], $a[1]);//YYYY年mm月下旬

}else{

$relDate = sprintf("%04d-%02d-%02d", $a[0], $a[1], $a[2]);//YYYY年mm月dd日

}

break;

endswitch;

return $relDate;

}

商品の取得自体はXMLなのでsimplexml_load_stringを使用する事で読み込めるのだが、楽天商品検索APIが出力するXMLはそのままでは読み込めない。

理由はフィールド名の所に":(コロン)"が入っているためで、もし関数を用いてパースする場合は文字の置換をする必要がある。

楽天ブックスのDVDサーチを例にとると、置き換えする箇所は以下の通り

header:Header → Header

booksDVDSearch:BooksDVDSearch → BooksDVDSearch

処理の流れはこのような感じになった

$contents = file_get_contents( [楽天APIに投げるリクエストURL] );

$val = array("header:Header", "booksDVDSearch:BooksDVDSearch");

$replace = array("Header", "BooksDVDSearch");

$res = str_replace($val, $replace, $contents);

$xml = simplexml_load_string($res);