Hatena::ブログ(Diary)

Awesome Rapid Service

2011-11-02

パーフェクトPHP 2〜5章自作問題集

今更ですがパーフェクトPHPを読了しました。オライリーの「プログラミングPHP」よりもこっちのほうが好きになりました。

パーフェクトPHP (PERFECT SERIES 3)

パーフェクトPHP (PERFECT SERIES 3)

2〜5章は理解を確実にするために問題集を作りながら読みました。その時につくった問題を公開します。

  • 解答は載せてません。パーフェクトPHPを読んで(なければ、ぜひお買いになって)ご確認下さい。
  • あまりにも簡単すぎると感じた事柄は出題していません。
  • 記述式の問題がほとんどなので多少難しく感じることもあるかもしれません。

2章 PHPの基本

  • PHP_EOLとは?
  • PHPブロックとは?
  • PHPブロックの終了タグを省略することができるのはどのような場合においてか?
  • ライブラリHTMLを含まないファイルでは終了タグを記述することが推奨されているか?それとも記述しないことが推奨されているか?そして、それは何故か?
  • PHPにおいて文の途中での空白、タブ、改行はどのように扱われるか。
  • PHPでのコメントの記述方法3種類を挙げよ
  • echo文での出力の特徴は?
  • phpの識別子のルールは?
  • PHPのエラーを大きく分けるとどのような分類になるか?すべて挙げよ
  • 変数がセットされているか調べるにはどうすればいいか?
  • 可変変数とは?
  • スコープとは?
  • ローカルスコープ内でグローバルスコープに定義された変数を参照するにはどうするか?
  • 定義済み定数の例を1つ挙げよ
  • スーパーグローバル変数の特徴は?
  • スーパーグローバル変数の例を挙げよ
  • 定数を定義する方法を2つ挙げよ
  • 文字列から該当する定数を取得するには?
  • マジック定数とは?
  • マジック定数を全て挙げよ
  • 発生したエラーを表示させるかどうかを制御する設定項目は何か?

3章 型と演算子

  • PHPは符号なし整数をサポートしているか?それともサポートしていないか?
  • PHP_INT_MAXを超える整数はどうなるか?
  • 整数型に明示的にキャストする方法を2つ挙げよ
  • 浮動小数点型に明示的にキャストする方法を3つ挙げよ
  • 文字列において"(ダブルクォート)が'(シングルクォート)と比べて違うところは何か?
  • ヒアドキュメントとNowdoc、変数が展開されるのはどちらか?
  • ヒアドキュメントはどのように書く?
  • Nowdocはどのように書く?
  • 文字列型への明示的なキャストをする方法を2つ書け
  • 次の例はどのように出力されるか echo 22.0;
  • PHPがfalseと判断するものを挙げよ
  • リソース型を初期化する関数を一つあげよ
  • 変数の持つリソース型の種類を調べることのできる関数は?
  • 変数がnullになる場合3つを挙げよ
  • nullの代入された変数とunset()された変数とは何が違うか
  • 自動キャストはどんな場合に発生する?
  • なるべく===または!==を使って厳密な比較を行うべきであるが、それはなぜか?
  • ある変数が特定のクラスのインスタンスであることを調べるために用いる型演算子は何か?
  • 次の表記は複合演算子の表記である。これと等しい表記のPHPプログラムを書け

$i += 1;

$result = func() ? func() : 'hoge';

$flag1 = true;

$flag2 = false;

echo $flag1 ? 1 : $flag2 ? 2 : 0;

  • PHPにおける三項演算子は右結合か左結合か?
  • 実行演算子``の機能について述べよ
  • 実行演算子``と同じ機能をもつ関数は何か?
  • PHP配列の特徴を3つあげよ
  • 配列のキーがセットされているか調べる方法を2つのべよ

4章 制御構造と関数

  • グループ文とは?
  • $hoge = 3という式の評価は?
  • 以下のプログラムを:とendifを使って表現せよ

if ($bool) {

echo 'hoge';

}

  • forの括弧内の3番目の式(反復式)はいつ実行されるか?
  • foreachに渡す配列の各要素の値を変更するには?
  • 関数の返り値に参照を用いるには関数の定義においてどのようにすればいいか?
  • 関数に渡す引数を参照で受け取るにはどうすればいいか?
  • 引数を参照で受け取る関数には値を渡すことができる?それともできない?
  • 返り値に参照を用いている関数は値を返すことができる?それともできない?
  • 可変関数とは?
  • 可変関数と同じようなことを実現できる関数を2つ挙げよ
  • 無名関数の主な使い道は?
  • クロージャとは?
  • 無名関数を定義する際に、関数内で利用する変数を指定してクロージャを作るために使われる構文は?
  • 言語構造が関数と違うところは?
  • 関数と言語構造、可変関数やコールバックに指定できないのはどっち?

5章 クラスとオブジェクト

アクセス修飾子)

private

protected

public

(説明)

自分のクラスの内側または自分のクラスを継承したクラスの内側からのみ参照・呼び出しができる

自分のクラスの内側からのみ参照・呼び出しができる

クラスの外側からでも参照・呼び出しができる

2011-05-25

Twitterのツイート取得3200件制限およびツイートの消去についてのメモ

基本

  • Twitterツイートは3200件までさかのぼることができる。それより前へはさかのぼれない
  • 3200件より前にはさかのぼることはできないが、個別のツイートそのものは残っている
  • よって、URLを知っていれば(または、検索で見つけることができれば)個別のツイートのページへ直接アクセスすることが可能である

ツイートの消去が取得に及ぼす影響

  • たとえば、APIで3101件前〜3200件前を指定して取得(http://api.twitter.com/1/statuses/user_timeline.json?count=100&page=32)し、100件が返ってきたとする
  • ここで、3150件前のツイートを消す。この後3101〜3200件目を取得し直そうと試みても99件しか返ってこない
  • このことより、3200件前より新しいツイートを消したとしても、3201件目を取得することはできないと思われる
  • イメージとしては3200件前までのデータを管理するテーブルがあって、新しいツイートがなされると古いツイートが一つ消える、ツイートが消されるとそこは詰められずに空白になる、という感じのものが想像できる

2010-09-03

HTTP_OAuthでアクセストークンを取得するときにユーザIDとスクリーン名を取得できるようにするための修正

Twitter API 仕様書*1によると、アクセストークンを取得するための認証に成功すると、アクセストークン、アクセストークンシークレットの他にユーザID、スクリーン名が返ってくることになっています。

PEARのHTTP_OAuthのバージョン0.1.18では認証成功時にアクセストークンとアクセストークンシークレットは取得できます。しかし、ユーザIDおよびスクリーン名を取得することはできないようです。

なので、これらを取得できるように修正してみました。

修正の対象となるのは、Consumer.php内のクラスHTTP_OAuth_Consumerです。

クラス変数を追加する

<?php
    protected $userId = null;
    protected $screenName = null;
?>

既存のメソッドに書き加える

<?
    public function getAccessToken($url, $verifier = '',
        array $additional = array(), $method = 'POST'
    )
    {
        if ($this->getToken() === null || $this->getTokenSecret() === null) {
            throw new HTTP_OAuth_Exception('No token or token_secret');
        }

        $this->debug('Getting access token from ' . $url);
        $additional['oauth_verifier'] = $verifier;

        $this->debug('verifier: ' . $verifier);
        $response = $this->sendRequest($url, $additional, $method);
        $data     = $response->getDataFromBody();
        if (empty($data['oauth_token']) || empty($data['oauth_token_secret'])) {
            throw new HTTP_OAuth_Consumer_Exception_InvalidResponse(
                'Failed getting token and token secret from response', $response
            );
        }

        $this->setToken($data['oauth_token']);
        $this->setTokenSecret($data['oauth_token_secret']);
        
        /* 
         * ここから追加
         */
            $this->setUserId($data['user_id']);
            $this->setScreenName($data['screen_name']);
        /* 
         * 追加ここまで
         */
    }
?>

メソッドを新たに追加する

<?
    public function getUserId()
    {
        return $this->userId;
    }
    
    public function setUserId($userId)
    {
        $this->userId = $userId;
    }

    public function getScreenName()
    {
        return $this->screenName;
    }
    
    public function setScreenName($screenName)
    {
        $this->screenName = $screenName;
    }
?>

使い方

スクリーン名、ユーザIDを取得するときはアクセストークン等を取得するときに、以下のようにすれば取得できます。

<?php
$screenName = $consumer->getScreenName();
$userId = $consumer->getUserId();
?>

2009-10-21

Services_Twitterで返信対象のつぶやきを指定するには

<?php
require_once 'Services/Twitter.php';

$username = 'Your_Username';
$password = 'Your_Password';

$args = array('status' => "@YBahn お疲れ様です!",
              'in_reply_to_status_id' => "4466621967"
              );
try {
    $twitter = new Services_Twitter($username, $password);
    $msg = $twitter->statuses->update($args);
    print_r($msg);
} catch (Services_Twitter_Exception $e) {
    echo $e->getMessage(); 
}
?>

2009-10-20

Services_Twitter0.4.0を日本語で使うための修正

PEARTwitterライブラリであるServices_Twitterのバージョン0.4.0を使ってTwitterに投稿をしようとすると「statuses/update: status must not exceed 140 chars」とのエラーが出ることがあります。これはつぶやきが140字を超えてはいけないという意味ですが、つぶやきが日本語である場合、140字を超えていないにもかかわらずこのエラーが発生することがあります。

この現象が起こる原因は、Services_Twitter0.4.0が文字列の長さの判定にstrlen関数を使っていることです。strlen関数は日本語をはじめとするマルチバイト文字の文字数を正確に数えることができず、実際の文字数より大きい数字が返ってくるからです。

マルチバイト文字列の文字数を正確に数えるにはマルチバイト文字列に対応したmb_strlen関数を使います。

修正前のソースコードと修正後のコードを以下に示します。修正後のコードではstrlen関数をmb_strlen関数に変更しています。ここではつぶやきの文字コードはUTF-8であるものとします。

修正前

<?php
    protected function validateArg($name, &$val, $type, $maxLength = null)
    {
        // check length if necessary
        if ($maxLength !== null && strlen($val) > $maxLength) {
            throw new Exception(
                $name . ' must not exceed ' . $maxLength . ' chars',
                self::ERROR_PARAMS
            );
        }
?>

修正後

<?php
    protected function validateArg($name, &$val, $type, $maxLength = null)
    {
        // check length if necessary
        if ($maxLength !== null && mb_strlen($val,"UTF-8") > $maxLength) {
            throw new Exception(
                $name . ' must not exceed ' . $maxLength . ' chars',
                self::ERROR_PARAMS
            );
        }
?>