phalcon あれこれ

2016.01.12 Tuesday 00:34
0
    phalcon めも

    Phalcon の DI は 生成されたり Singleton になったり
    その説明の前に一旦 Phalcon の DI の特性について書いておきます.
    Phalcon の DI は shared にしてるかどうかで返ってくるインスタンスが新規か使い回しか変わります.
    つまり
    $di->get('hoge') としてる場合は 毎回異なるインスタンスが返ってきて,
    $di->getShared('hoge') とすると毎回同じインスタンスが返ってきます. ($di->set() 時に shared としてるかどうかにもよるけど)
    そのインスタンスが生成されたか既存のインスタンスを返しているかどうかについては
    $di->getShared() を呼び出した直後に $di->wasFreshInstance() を呼び出すことでわかります.


    ・Singleton
    Singleton パターンを用いると、そのクラスのインスタンスが1つしか生成されないことを保証することができる。 ロケールやLook&Feelなど、絶対にアプリケーション全体で統一しなければならない仕組みの実装に使用される。


    ・phalcon ログ出力方法
    $logger = new ¥Phalcon¥Logger¥Adapter¥File('D:¥xampp¥phalcon-devtools-master¥log¥p.log');
    $logger->log('zzzzzz1');

    $logger = new ¥Phalcon¥Logger¥Adapter¥File('D:¥xampp¥phalcon-devtools-master¥log¥p.log');
    $logger->log("[" . __FILE__ ."][" . __LINE__ . "]");

    ・use で以下を指定すると Logger::ERRORなどつかえる
    use Phalcon¥Logger;
    use Phalcon¥Logger¥Adapter¥File as FileAdapter;
    $logger = new ¥Phalcon¥Logger¥Adapter¥File('¥log¥p.log');
    $logger->log("zzz1", Logger::ERROR);
    $logger->log("zzz2", Logger::DEBUG);
    $logger->log("zzz3", Logger::INFO);
    $logger->log("zzz4", Logger::NOTICE);
    $logger->log("zzz5", Logger::ALERT);
    $logger->log("zzz6", Logger::CRITICAL);


    // These are the different log levels available:
    $logger->critical("This is a critical message");
    $logger->emergency("This is an emergency message");
    $logger->debug("This is a debug message");
    $logger->error("This is an error message");
    $logger->info("This is an info message");
    $logger->notice("This is a notice message");
    $logger->warning("This is a warning message");
    $logger->alert("This is an alert message");

    // You can also use the log() method with a Logger constant:
    $logger->log("This is another error message", Logger::ERROR);

    // If no constant is given, DEBUG is assumed.
    $logger->log("This is a message");
    The log generated is below:


    ・controller内でview指定
    // D:¥xampp¥htdocs¥tutorial¥app¥views¥signup¥index.phtml
    $this->view->setMainView( 'signup/index.phtml' ); // viewを指定する。これがないと ¥views¥index.phtml が存在するとこれを呼ぶ(¥views¥signup¥index.phtmlではなく)



    ・mysql
    database作成
    create database test_db
    use test_db
    mysql -u root -p test_db


    CREATE TABLE `users` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `name` varchar(70) NOT NULL,
    `email` varchar(70) NOT NULL,
    PRIMARY KEY (`id`)
    );


    validate コントローラーでやるんだね いや modelだわ
    d:¥xampp¥htdocs¥invo¥app¥models¥users.php
    https://docs.phalconphp.com/ja/latest/reference/tutorial-invo-2.html

    viewで以下(tag)を指定すると
    tag->form("signup/register"); ?>
    htmlでは以下となる



    エラーメッセージなどをビューで表示する際には Phalcon では flash を使うときがある

    今日は、Phalconのフラッシュメッセージについて調べてみます。

    フラッシュメッセージは、単にユーザに情報を表示するアクションの状態をユーザに通知するために使用されます。メッセージのこれらの種類は、このコンポーネントを使用して生成することができます


    Dispatcher
    アプリケーションがこの動きをどのように実現しているか見ていきましょう。
    最初に知るべきは、Dispatcher コンポーネントです。
    これは、 Routing コンポーネントによって発見されたルートの情報を受け取ります。
    次に、適切なコントローラーを読み込んで、対応するアクションのメソッドを実行します。
    通常、フレームワークはディスパッチャを自動的に作成します。
    今回は、要求されたアクションを実行する前に、認証を行い、ユーザーがアクセスできるか否かチェックする必要があります。
    これを実現するため、ブートストラップの中に関数を用意して、ディスパッチャを置き換えています:


    フレーワークの多くのコンポーネントはイベントを発火するので、
    内部の処理の流れを変更することができます。DIコンポーネントが接着剤として機能し、
    EventsManager がコンポーネントが生み出すイベントをインターセプトし、イベントをリスナーに通知します。


    アクセス制御リスト (ACL)

    PHPフレームワークのPhalconで、RedirectとForwardの違い
    --------------------------------------------------
    // 内部的な処理で、コントローラーだけがフォワードされる。URLは変わらない。
    $this->dispatcher->forward(array('controller' => 'news', 'action' => 'index'));
    // HTTPリダイレクトが行われて、URLも変わる
    $this->response->redirect("news/index");
    --------------------------------------------------

    画面のパラを受ける
    $year = $this->dispatcher->getParam ( 'year' );
    $postTitle = $this->dispatcher->getParam ( 'postTitle' );
    だったり
    $email = $this->request->getPost('email');
    $password = $this->request->getPost('password');


    dispatch はこうやってつかわれたりもする
    public function showAction($year, $postTitle)
    {
    $this->flash->error("You don't have permission to access this area");
    // 別のアクションへ転送する
    $this->dispatcher->forward(array(
    "controller" => "users",
    "action" => "signin"
    ));
    }


    コントローラの初期化
    何らかのアクションがコントローラ上で実行される前に、Phalcon¥Mvc¥Viewコンポーネントは、最初に実行されるinitialize()メソッドを提供しています。__construct “メソッドの使用は推奨されません。
    class PostsController extends ¥Phalcon¥Mvc¥Controller
    {
    public $settings;
    public function initialize()
    {
    $this->settings = array(
    "mySetting" => "value"
    );
    }
    public function saveAction()
    {
    if ($this->settings["mySetting"] == "value") {
    //...
    }
    }
    }



    ・サービスの注入
    $di = new Phalcon¥DI();
    $di->set('storage', function() {
    return new Storage('/some/directory');
    }, true);
    それから、下記のようにいくつかの方法でそのサービスにアクセスすることができます。

    ソースを表示印刷?
    class FilesController extends ¥Phalcon¥Mvc¥Controller
    {
    public function saveAction()
    {
    //Injecting the service by just accessing the property with the same name
    $this->storage->save('/some/file');
    //Accessing the service from the DI
    $this->di->get('storage')->save('/some/file');
    //Another way to access the service using the magic getter
    $this->di->getStorage()->save('/some/file');
    //Another way to access the service using the magic getter
    $this->getDi()->getStorage()->save('/some/file');
    //Using the array-syntax
    $this->di['storage']->save('/some/file'); ★これがわかりやすいかな
    }
    }


    // リクエストがPOSTで作られているかどうかをチェック
    if ($this->request->isPost() == true) {
    // POSTデータにアクセス
    $customerName = $this->request->getPost("name");
    $customerBorn = $this->request->getPost("born");
    }



    セッションデータ
    セッションは、リクエスト間の永続データを維持するのに役立ちます。永続的に必要なデータをカプセル化しますので、あなたはどんなコントローラからでもPhalcon¥Session¥Bagにアクセスすることができます。
    class UserController extends Phalcon¥Mvc¥Controller
    {
    public function indexAction()
    {
    $this->persistent->name = "Michael";
    }
    public function welcomeAction()
    {
    echo "Welcome, ", $this->persistent->name;
    }
    }


    ・phalcon
    flashSession’属性はフラッシュが以前に依存性注入コンテナにセットした方法です。あなたは、セッションを成功裏にflashSessionメッセンジャーを使用するために最初に起動する必要があります。
    フラッシャーには、DirectとSessionの2つのアダプタがある
    Directは直接渡されたメッセージを出力する
    Sessionは、一時的にセッション内にメッセージを保存する


    // 別のアクションへ転送する
    $this->dispatcher->forward(array(
    "controller" => "users",
    "action" => "signin"
    ));



    サービスの注入
    コントローラがPhalcon¥Mvc¥Controller拡張する場合、それはアプリケーション内のサービスコンテナへの容易なアクセスを持っています。例として、下記のようなサービスを登録している場合があります。
    $di = new Phalcon¥DI();
    $di->set('storage', function() {
    return new Storage('/some/directory');
    }, true);

    それから、下記のようにいくつかの方法でそのサービスにアクセスすることができます。
    class FilesController extends ¥Phalcon¥Mvc¥Controller
    {
    public function saveAction()
    {
    $this->storage->save('/some/file'); //Injecting the service by just accessing the property with the same name
    $this->di->get('storage')->save('/some/file'); //Accessing the service from the DI
    $this->di->getStorage()->save('/some/file'); //Another way to access the service using the magic getter
    $this->getDi()->getStorage()->save('/some/file'); //Another way to access the service using the magic getter
    $this->di['storage']->save('/some/file'); //Using the array-syntax ★これがわかりやすいかな
    }
    }
    フルスタックフレームワークとしてPhalconを使用している場合は、あなたはフレームワークのデフォルトで
    提供されるサービスを読み込むことができます。



    リクエストとレスポンス
    フレームワークは、予め登録されたサービスのセットを提供するものと見なします。
    私たちは、HTTP環境と対話する方法について説明します。「リクエスト」サービスには、
    Phalcon¥Http¥Requestコンポーネントのインスタンスが含まれいて、「response」には、
    クライアントに返信するために何が起こっているかを表すPhalcon¥Http¥Responseコンポーネントが含まれています。
    class PostsController extends Phalcon¥Mvc¥Controller
    {
    public function saveAction()
    {
    // リクエストがPOSTで作られているかどうかをチェック
    if ($this->request->isPost() == true) {
    // POSTデータにアクセス
    $customerName = $this->request->getPost("name");
    $customerBorn = $this->request->getPost("born");
    }
    }
    }



    セッションデータ
    セッションは、リクエスト間の永続データを維持するのに役立ちます。
    永続的に必要なデータをカプセル化しますので、あなたはどんなコントローラからでも
    Phalcon¥Session¥Bagにアクセスすることができます。
    class UserController extends Phalcon¥Mvc¥Controller
    {
    public function indexAction()
    {
    $this->persistent->name = "Michael";
    }
    public function welcomeAction()
    {
    echo "Welcome, ", $this->persistent->name;
    }
    }



    http://localhost/blog/posts/show/2012/the-post-title/
    ※GETクエリには、パラメータの値だけで、変数名は不要。
    以下のようにActionメソッド関数に引数を設定することで、取得できる。
    URLに設定されているパラメータ値と、メソッドの引数は順序的1対1の関係にある。
    class PostsController extends ¥Phalcon¥Mvc¥Controller
    {
    public function showAction($year, $postTitle)
    {
    /*
    $year に 2012
    $postTitle に the-post-title
    がアサインされる


    もし、URL形式を以下のようにしたい場合は、
    http://localhost/blog/posts/show/?year=2012&title=the-post-title
    以下のようにパラメータ値を取得できる。
    public function showAction()
    {
    $year = $this->request->getQuery('year');
    $title = $this->request->getQuery('title');
    }


    GET以外のPOSTなども上記と同じような理屈で対応できる。
    リクエストに関するクラスは、 Phalcon¥Http¥Request



    レスポンス
    レスポンスに関するクラスは、 Phalcon¥Http¥Response

    フォワード
    $this->dispatcher->forward(array(
    "controller" => "users",
    "action" => "signin"
    ));



    登録サービスへのアクセス
    Phalcon¥Mvc¥Controllerを継承したコントローラーであれば、以下のようにしてDIにアクセスできます。
    $this->di;
    or
    $this->getDI();



    セッションデータ
    セッションに関するクラスは、 Phalcon¥Session¥Bag
    以下のようにして、値のセット、取得ができます。
    class UserController extends Phalcon¥Mvc¥Controller
    {
    public function indexAction()
    {
    $this->persistent->name = "Michael";
    }
    public function welcomeAction()
    {
    echo "Welcome, ", $this->persistent->name;
    }


    ・validation
    controllers/UserController.php
    require __DIR__ . '/../interfaces/request/validation/UserValidation.php';
    require __DIR__ . '/../interfaces/response/UserResponse.php';
    class UserController extends ControllerBase {
    public function getUser() {
    $req = $this->input();

    //バリデーション処理
    $uv = new UserValidation();
    $valid = $uv->getUserValidation($req);

    if ($valid->count()) {
    //Error
    $msg = $valid[0]->getMessage();
    $this->output(400, UserResponse::errorResponse(400, $msg));
    return;
    }



    コントローラーでは、基本的に全て共通して、

    リクエストを取得

    バリデーションチェック

    エラーの場合は、エラーレスポンスを返す

    エラーがない場合は、DB操作を何かする

    レスポンスデータを作成し、JSONを返す
    といった感じですかね。

    バリデーションチェックでは、
    nullチェックや、型チェック、値チェック、長さチェックなど
    基本的なことをやります。

    また、リクエストフィールドに対するバリデーションチェックは、
    APIの種類に関係なく、基本は同じはずだと思います。
    (nullがOKの有無はAPIの種類によって異なる場合はあるかと思います。)

    なので、APIで扱う全てのリクエストフィールド情報は、
    interfaces/request/fields/CommonFields.php
    に記述するようにしました。

    内容としては、
    フィールド名、フィールドに対して使用するバリデーションインスタンス
    となります。

    サンプルソース
    interfaces/request/fields/CommonFields.php


    use Phalcon¥Validation¥Validator¥PresenceOf,
    Phalcon¥Validation¥Validator¥InclusionIn,
    Phalcon¥Validation¥Validator¥Email,
    Phalcon¥Validation¥Validator¥Between,
    Phalcon¥Validation¥Validator¥StringLength;

    class CommonFields {

    //Request Fields
    protected $_fields;

    public function __construct() {
    $this->_fields = array(
    'sex' => array(
    'default' => array(
    new PresenceOf(array(
    'cancelOnFail' => TRUE,
    )),
    new InclusionIn(array(
    'domain' => array('male', 'female'),
    'cancelOnFail' => TRUE
    )),
    ),
    'custom' => array(
    new Type(array(
    'type' => 'string'
    )),
    ),
    ),
    'birthday' => array(
    'default' => array(
    new PresenceOf(array(
    'cancelOnFail' => TRUE,
    )),
    ),
    'custom' => array(
    new Type(array(
    'type' => 'integer'
    )),
    new Date(array(
    'format' => 'Ymd'
    )),
    ),
    ),
    〜省略〜
    );
    }

    public function getFields() {
    return $this->_fields;
    }

    }
    バリデーションの部分が
    defaultとcustomに分かれているのは、
    Phalconで用意されているバリデーションクラスと、
    自前で用意したバリデーションクラスを区別するためです。

    上記のクラスでは、APIの全てで扱うフィールドを設定したので、
    interfaces/request/fields/UserFields.php
    では、各APIで扱うフィールドを記述するようにしました。

    サンプルソース
    interfaces/request/fields/UserFields.php

    namespace Interfaces¥Request¥Fields {

    class UserFields {
    static public function getUserFields() {
    return array(
    array('sex', TRUE),
    array('birthday', TRUE),
    〜省略〜
    );
    }
    }
    }
    TRUEの部分は、NOT NULLのフラグとしています。
    ここをFALSEにすると、バリデーションチェックで、
    nullチェックは行わないようにします。

    バリデーションチェックして、OKだったら、
    何かDB操作して、レスポンスを返さなければいけません。

    リクエストと同様にして、
    各APIごとにレスポンスのフィールドも設定するようにします。

    サンプルソース
    interfaces/response/fields/UserFields.php


    namespace Interfaces¥Response¥Fields {

    class UserFields {
    static public function getUserFields() {
    return array(
    'sex',
    'birthday',
    );
    }
    }
    }
    DBから得られた結果から、上記で設定したフィールドをもとに
    必要なものだけを取得して、レスポンスを作成し、クライアントに返します。

    ここまで、ソースを抜粋しながら、簡単な説明を記載してきました。
    DB操作以外の部分は、
    API実装前に存在している仕様書から全て設定できる範囲なので、
    実装の半分くらい?は簡単にできるのではないかなと感じてます。





    __NAMESPACE__


    ・validation
    https://docs.phalconphp.com/ja/latest/reference/validation.html

    phalcon validate email
    use Phalcon¥Validation¥Validator¥Email as Email

    use Phalcon¥Mvc¥Model¥Validator¥Email as EmailValidator;

    class Subscriptors extends ¥Phalcon¥Mvc¥Model
    {
    public function validation()
    {
    $this->validate(new EmailValidator(array(
    'field' => 'electronic_mail'
    )));
    if ($this->validationHasFailed() == true) {
    return false;
    }
    }




    イベントマネージャ
    イベントマネージャのカスタマイズ

    モデルのイベントコンポーネントは、Phalcon¥Events¥Managerと統合されています。そのため、イベントが実行される際のリスナーを作ることもできます。


    use Phalcon¥Mvc¥Model,
    Phalcon¥Events¥Manager as EventsManager;

    class Robots extends Model
    {

    public function initialize()
    {

    $eventsManager = new EventsManager();

    // "model"イベントに無名関数を登録する
    $eventsManager->attach('model', function($event, $robot) {
    if ($event->getType() === 'beforeSave') {
    if ($robot->name === 'Scooby Doo') {
    echo "Scooby Dooはロボットではありません!";
    return false;
    }
    }
    return true;
    });

    // イベントマネージャをイベントに登録
    $this->setEventsManager($eventsManager);
    }

    }
    上記サンプルコードでは、イベントマネージャはオブジェクトとリスナーの橋渡しを行います。イベントは、Robotsモデルのsave時に発火します。


    $robot = new Robots();
    $robot->name = 'Scooby Doo';
    $robot->year = 1969;
    $robot->save();
    全てのオブジェクトに共通のEventsManagerを実装したい場合、EventsManagerをModelsManagerに登録します。


    // modelsManagerサービスをDIコンテナに登録
    $di->setShared('modelsManager', function() {

    $eventsManager = new ¥Phalcon¥Events¥Manager();

    // "model"イベントのリスナーとして無名関数を登録する
    $eventsManager->attach('model', function($event, $model){

    // Robotsモデルに寄って生成されるイベントをキャッチする
    if (get_class($model) == 'Robots') {

    if ($event->getType() == 'beforeSave') {
    if ($model->name == 'Scooby Doo') {
    echo "Scooby Dooはロボットではありません!";
    return false;
    }
    }

    }
    return true;
    });

    // EventsManagerを登録する
    $modelsManager = new ModelsManager();
    $modelsManager->setEventsManager($eventsManager);
    return $modelsManager;
    });
    リスナーがfalseを返すと、その処理の実行は中断されます。







    データの完全性バリデーション

    Phalcon¥Mvc¥Modelは、データをバリデーションし、ビジネスルールを実装するためのイベントを提供しています。「validation」イベントによって、組み込みのバリデーターを呼び出すことができます。Phalconは、いくつかの組み込みバリデーターを提供しています。
    use Phalcon¥Mvc¥Model¥Validator¥InclusionIn,
    Phalcon¥Mvc¥Model¥Validator¥Uniqueness;

    class Robots extends ¥Phalcon¥Mvc¥Model
    {

    public function validation()
    {

    $this->validate(new InclusionIn(
    array(
    "field" => "type",
    "domain" => array("Mechanical", "Virtual")
    )
    ));

    $this->validate(new Uniqueness(
    array(
    "field" => "name",
    "message" => "ロボットの名前が重複してはいけません"
    )
    ));

    return $this->validationHasFailed() != true;
    }

    }
    上記コード例では、組み込みの「InclusionIn」バリデーターを使用しています。このバリデーターは、「type」フィールドの値がdomainのリストに含まれているかチェックしています。値が含まれていなかった場合は、バリデーションに失敗し、バリデーターはfalseを返します。

    組み込みのバリデーターの一覧は以下です。

    名前 説明 実装例
    PresenceOf フィールドの値がnullではなく、空文字列でもないことをバリデーションする。NOT NULL制約が設定されているフィールドに対しては、このバリデーターが自動的に追加される。 例
    Email フィールドの値が有効なEメールアドレスであるかバリデーションする 例
    ExclusionIn フィールドの値が禁止リストに含まれないことをバリデーションする 例
    InclusionIn フィールドの値が許可リストに含まれることをバリデーションする 例
    Numericality フィールドの値が数値形式かバリデーションする 例
    Regex フィールドの値が正規表現にマッチするかバリデーションする 例
    Uniqueness フィールドの値が既存のレコードと重複しないかバリデーションする 例
    StringLength 文字列の長さをバリデーションする 例
    Url フィールドの値が有効なURLの形式化バリデーションする 例
    組み込みのバリデーターに加えて、独自のバリデーターを作成することもできます。


    use Phalcon¥Mvc¥Model¥Validator,
    Phalcon¥Mvc¥Model¥ValidatorInterface;

    class MaxMinValidator extends Validator implements ValidatorInterface
    {

    public function validate($model)
    {
    $field = $this->getOption('field');

    $min = $this->getOption('min');
    $max = $this->getOption('max');

    $value = $model->$field;

    if ($min <= $value && $value <= $max) {
    $this->appendMessage(
    "フィールドの値が有効範囲外です",
    $field,
    "MaxMinValidator"
    );
    return false;
    }
    return true;
    }

    }
    バリデーターをモデルに追加するには、以下のようにします。
    class Customers extends ¥Phalcon¥Mvc¥Model
    {

    public function validation()
    {
    $this->validate(new MaxMinValidator(
    array(
    "field" => "price",
    "min" => 10,
    "max" => 100
    )
    ));
    if ($this->validationHasFailed() == true) {
    return false;
    }
    }

    }
    バリデーターを作成することで、バリデーションのロジックを複数のモデルで使い回すことができます。1箇所でしか使わないバリデーションであれば、以下のようにシンプルに実装することもできます。

    use Phalcon¥Mvc¥Model,
    Phalcon¥Mvc¥Model¥Message;

    class Robots extends Model
    {

    public function validation()
    {
    if ($this->type === "Old") {
    $message = new Message(
    "Sorry, old robots are not allowed anymore",
    "type",
    "MyType"
    );
    $this->appendMessage($message);
    return false;
    }
    return true;
    }

    }





    SQLインジェクションを避ける

    モデルのプロパティに代入された値は全て、そのデータ型に応じたエスケープが施されます。開発者が、DBに入れる値のエスケープを実装する必要はありません。Phalconは内部でPDOのバインド機構を使用して、自動エスケープを行っています。

    mysql> desc products;
    +------------------+------------------+------+-----+---------+----------------+
    | Field | Type | Null | Key | Default | Extra |
    +------------------+------------------+------+-----+---------+----------------+
    | id | int(10) unsigned | NO | PRI | NULL | auto_increment |
    | product_types_id | int(10) unsigned | NO | MUL | NULL | |
    | name | varchar(70) | NO | | NULL | |
    | price | decimal(16,2) | NO | | NULL | |
    | active | char(1) | YES | | NULL | |
    +------------------+------------------+------+-----+---------+----------------+
    上記テーブルへのINSERTをする際、PDOを使用すると、以下のようなコードになります。


    $productTypesId = 1;
    $name = 'Artichoke';
    $price = 10.5;
    $active = 'Y';

    $sql = 'INSERT INTO products VALUES (null, :productTypesId, :name, :price, :active)';
    $sth = $dbh->prepare($sql);

    $sth->bindParam(':productTypesId', $productTypesId, PDO::PARAM_INT);
    $sth->bindParam(':name', $name, PDO::PARAM_STR, 70);
    $sth->bindParam(':price', doubleval($price));
    $sth->bindParam(':active', $active, PDO::PARAM_STR, 1);

    $sth->execute();
    Phalconのモデルを使用すると、以下のように書けます(エスケープは全て自動で行われます)。


    $product = new Products();
    $product->product_types_id = 1;
    $product->name = 'Artichoke';
    $product->price = 10.5;
    $product->active = 'Y';
    $product->create();
    カラムをスキップする


    category:phalcon | by:ittoocomments(0)trackbacks(0) | -

    スポンサーサイト

    2019.12.08 Sunday 00:34
    0
      category:- | by:スポンサードリンク | - | - | -
      Comment








         
      Trackback
      この記事のトラックバックURL

      ad
      Calender
      1234567
      891011121314
      15161718192021
      22232425262728
      293031    
      << December 2019 >>
      Selected entry
      PR
      Category
      Archives
      Recent comment
      • パス指定 SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-4: truncated ¥xXX escape
        久米隆文
      • 円マークが自動変換されてる
        aaaaaa
      • マクドナルドでYahoo BBモバイルポイント 公衆無線LANサービスがつながらない
        66hills
      • マクドナルドでYahoo BBモバイルポイント 公衆無線LANサービスがつながらない
        ssd
      • マクドナルドでYahoo BBモバイルポイント 公衆無線LANサービスがつながらない
        max
      • マクドナルドでYahoo BBモバイルポイント 公衆無線LANサービスがつながらない
        DOM
      • マクドナルドでYahoo BBモバイルポイント 公衆無線LANサービスがつながらない
        DOM
      • コンピュータ業界の根本的な変化
        cloud
      • コンピュータ業界の根本的な変化
        Dellの仮想化
      • マクドナルドでYahoo BBモバイルポイント 公衆無線LANサービスがつながらない
        えちごや
      Recent trackback
      • スマートフォンの法人活用例
        無線LANネットのブログ
      • Yahoo!オークションからのアフィリエイト収入が一気に70%減になってしまい涙目になってる話
        特選情報
      Recommend
      Link
      Profile
      Search
      Others
      Mobile
      qrcode
      Powered
      無料ブログ作成サービス JUGEM