higan96技術メモ

https://github.com/higan96

勝手に他人の本をアップデートしてる。

先日リリースしましたhttp://bnqa.jpを使い、他人の本を買ってにアップデートするという活動を行っております。アップロードじゃないですよ、念のため。


勝手にアップデートしているのは以下の本です。

効率的なWebアプリケーションの作り方 ~PHPによるモダン開発入門

効率的なWebアプリケーションの作り方 ~PHPによるモダン開発入門

http://bnqa.jp/item/4774150827


こちらの本、大変素晴らしい本なのですが、いかんせん解説に使用しているフレームワークであるSymfony2のバージョンが2.0です。現在、LTS(長期サポート)のバージョンとして2.3がリリースされており、今から勉強をしようとする場合、バージョン2.0では勉強の投資対効果があまりよろしくない現状です。


Symfony2を解説している日本語の書籍は、現在この本しかありません。これからSymfony2を触ろうとしているかたにとっては、大変有意義な一冊であることは間違いありません。


そのため、Symfony2のバージョンを2.3に上げて勉強を行う場合に詰みそうなところ幾つか「アドバイス」という形で投稿しました。何か疑問等があれば、可能な限り対応しますので、よかったら利用してみてください。また、他の方にもアドバイス等を投稿していただけると、多くの学習者にとって有意義なことと思います。

独学で2度目のWebサービスリリースまでにやったこと

先日Webサービスをリリースしました。
http://bnqa.jp

今回、2度目のWebサービス公開までにやったことや考えたことについて書いていきたいと思います。



【再掲】やってみた「WebデザイナーやノンプログラマーにおすすめしたいPHPの勉強法」
このエントリを書いたのが2012年の5月なので、1年半前くらいそこからさらに独学で勉強を続けてました。エントリの時点で半年やったと書いてあったので、2年間独学で続けてきたことになります。


ここまでよく続いたな、というのが自分の感想ですが、自分の置かれた状況を考えればやらないわけにはいかなかった、といったとこです。そのあたりは別の機会に書こうと思います。


やったことリスト

PHP, MySQL

一番大きな理由としてはこちらのエントリPHPに関する記事であった、というのがあります。とっつきやすさもあってよかった。とりあえず動くものはすぐ作れるので、やりながら学ぶタイプの人でWebアプリ作りたい人は、PHPって選択肢は悪くないと思います。
おすすめの書籍はパーフェクトPHPです。
MySQLについては書籍やネット上の情報が多いことが選んだ理由です。

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

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


http://bnqa.jp/item/4774144371


Symfony2

今回作ったアプリはSymfony2で作られています。Symfony2を選択した理由としては、PHPでいくつかあるフレームワークを比較検討したうえの選択、、、とかではなく、こちらの本がSymfony2に関する本だったからです。

効率的なWebアプリケーションの作り方 ~PHPによるモダン開発入門

効率的なWebアプリケーションの作り方 ~PHPによるモダン開発入門


http://bnqa.jp/item/4774150827


とてもいい本です。こちらの本を選んだ理由としては、パーフェクトPHPを執筆された方の本だったからです。執筆されたのは小川 雄大さんという方。

この本の良い所は、「モダンなPHP開発の流れ」を体験できるところです。個人的にはGitとテストに触れることができた点が良かった。モダンな感じで。ただ、本の中でも言及されているとおり、全体の大まかな流れについては本通りに進めていけば体験できるチュートリアル形式の構成になっているのですが、個別の詳細な解説は大きく省かれています。これらは紙面の都合で、しかたのないことだと思いますし、中途半端に詳しくやってコンセプトがブレてもしょうがないですし。本以上のことは、自力でやりました。あとこの本はSymfony2.0で書かれていますので、バージョン2.1位上で本を進めていこうとすると結構大変ですよ、というのは経験者の言葉です。ただ2.3が長期サポートなので、2.3で勉強することをおすすめします。

Symfony2は日本語情報が少ないです。さらにSymfonyユーザー会のみなさんが公開されている公式ドキュメントの翻訳はバージョンが2.0のものです。そのため、バージョン2.3位上を勉強する場合、本家サイトで情報を探すことになります。なので英語をよく読みました。それとStackOverflowにもおせわになりました。「エラーでググル→情報はStackOverflowだけ」とか結構あります。ある程度、英語は読めたほうがいいと思います。

Linux

勉強を進めてくとXAMPP、MAMPではダメなことに気が付きます。いろんな設定を試したいとか、特定のバージョンを使いたいとか。個人的にはVMwareFusionなんかの仮想環境でLinuxつかって、スナップショットを使いつつ、何度も環境ぶっ壊しながら勉強したほうがいいと思います。自分はUbuntu使ってました。
サーバはさくらのVPSの2Gプランを利用してます。当初、AWSの使用を検討し、microインスタンスで実験を繰り返していたのですが、やはり個人プロジェクトとしてはコストが大きすぎると判断して、今回は見送りました。でも本当は使いたいですね。

jQuery

Javascript勉強中です。。はやくWebサービスを完成させたかったので、開発優先でちょっと勉強不十分です。よく読んだのは以下の本。


http://bnqa.jp/item/4774148563


TwitterBootstrap3

スマートフォン対応はとても悩んでいたので、よいタイミングで公開してもらえました。レスポンシブデザインについては、ちょっと思うところがありますが、スマートフォン対応が小さな手間でできたことは良かった。TwitterBootstrapの学習はドットインストールを利用するのがおすすめです。

その他

当初、AmazonのAPIとの通信がボトルネックになっていたので、Memcachedを導入しデータを一定期間保存するようにしました。データの保存期間はAPIの利用規約を順守するように設定し、そのタイミングで更新するようにしています。デザインについては、友人に見せたら「Twitterじゃん」と言われましたが、参考にしたのはYoutubeです。

ノンデザイナーズ・デザインブック [フルカラー新装増補版]

ノンデザイナーズ・デザインブック [フルカラー新装増補版]


http://bnqa.jp/item/4839928401



大変でしたが、多くの学びがあり、また作ってる最中はとても楽しかった。まあ大変でしたが、とても。

Symfony2.1でBreadcrumbを簡単に書く方法

Symfony2.1でパンくずリストを簡単に書くために。whiteoctober / BreadcrumbsBundleを使用します。分かる範囲で解説します。

https://github.com/whiteoctober/BreadcrumbsBundle

インストール

Composer:

Composerを使用する場合、composer.jsonに以下の通り追加。Symfony2.1を使う場合は以下のように「 "2.1.x-dev"」となる。さらに↓に記入しているが、2.0は違う。

Symfony2.1x

"require": {
..
"whiteoctober/breadcrumbs-bundle": "2.1.x-dev"
..
},

symfony2.0x

"require": {
..
"whiteoctober/breadcrumbs-bundle": "master"
..
},

追加したらインストール

php composer.phar update

namespaceのoautoloadへの登録

Composerを使っているので、自動で書き込まれている。

AppKernel.phpへの登録

// app/AppKernel.php
public function registerBundles()
{
    return array(
        // ...
        new WhiteOctober\BreadcrumbsBundle\WhiteOctoberBreadcrumbsBundle(),
        // ...
    );
}

config.ymlに追加

最後にapp/config/config.phpを編集、以下のように追加。追加場所は一番下にでも。

white_october_breadcrumbs: ~

書き方

コントローラ
public function yourAction(User $user)
{
    $breadcrumbs = $this->get("white_october_breadcrumbs");
    // Simple example
    $breadcrumbs->addItem("Home", $this->get("router")->generate("index"));

    // Example without URL
    $breadcrumbs->addItem("Some text without link");

    // Example with parameter injected into translation "user.profile"
    $breadcrumbs->addItem($txt, $url, array("%user%" => $user->getName()));
}

引数

  • 第1引数:表示したい文字列
  • 第2引数:URL(絶対URL or 相対URL)
  • 第3引数:

流れとしては、breadcrumbsをとってきて、そいつにaddItemし続けるだけ。第1引数には表示したい文字列、第2引数にurlを指定する。urlは絶対URLでも相対URLでもどちらでも大丈夫。
注意点

  • 表示される順番はaddItemした順
  • Templateに$breadcrumbsを渡す必要なし
  • 最後にaddItemで追加した文字列には第2引数を指定してもリンクされない。
テンプレート(Twig)

以下のように追加するだけ。

{{ wo_render_breadcrumbs() }}

テンプレートオプション

{{ wo_render_breadcrumbs({separator: '>', listId: 'breadcrumbs'}) }}

上の例では区切り文字に「>」、

  • のidにbreadcrumbsを指定している。

    separator: デフォルトでは '/'
    listId: デフォルトは'wo-breadcrumbs'
    listClass: デフォルトは'breadcrumb'
    locale: defaults to null, so the default locale is used
    translation_domain: defaults to null, so the default domain is used

  • CallbackValidatorを使わずにFormEventでフィールドのバリデーション

    Symfony2.1でCallbackValidatorを使わずに、addEventListnerでエンティティに関係ないフィールドのバリデーションを実装する方法。

    コードは「効率的なWebアプリケーションの作り方」p.215より

    Before

    public function buildForm(FormBuilder $builder, array $options)
      {
        $builder
          ->add('name')
          ->add('email', 'repeated', array(
            'type' => 'email',
            'invalid_message' => '同じ値を入力してください',
          ))
          ->add('rawPassword', 'password', array(
            'always_empty' => false,
          ))
          ->add('tel')
          ->add('birthday', 'birthday')
          ->add('agreement', 'checkbox', array(
            'property_path' => false,
            'required'      => true,
          ))
          ;
    
          $builder->addValidator(new CallbackValidator(function($form) {
          if (!$form['agreement']->getData()) {
            $form['agreement']->addError(new FormError('利用規約に同意してください'));
          }
        }));
    }
    

    after

    //...
    
    use Symfony\Component\Form\FormEvents;
    //...
    
      public function buildForm(FormBuilderInterface $builder, array $options)
      {
        $builder
        ->add('name')
        ->add('email','repeated',array(
          'type' => 'email',
          'invalid_message' => '同じ値を入力してください',
        ))
        ->add('rawPassword','password',array(
          'always_empty' => false,
        ))
        ->add('tel')
        ->add('birthday','birthday')
        ->add('agreement','checkbox',array(
          'property_path' => false,
          'required'      => true,
        ))
        ;
    
        $builder->addEventListener(FormEvents::POST_BIND,function($event){
          $form = $event->getForm();
          if(!$form->has('agreement')){
            $form->addError(new FormError('利用規約に同意してください'));
          }
        });
      }
    

    該当箇所以外も載せているので、ちょっとわかりにくいですが、変更されているのは下から6行くらい。

    //...
    
    use Symfony\Component\Form\FormEvents;
    
    //...
    $builder->addEventListener(FormEvents::POST_BIND,function($event){
      $form = $event->getForm();
      if(!$form->has('agreement')){
            $form->addError(new FormError('利用規約に同意してください'));
      }

    まず、use Symfony\Component\Form\FormEvents; を追加、POST_BINDイベントを監視する。

    リスナーの関数に渡されるのはFormオブジェクトではなく、FormEventオブジェクトになる。なので、FormEventオブジェクトからgetForm()でフォームを取り出し、フォームに値がセットされているかを確認し、適宜addError()する。

    効率的なWebアプリケーションの作り方 ~PHPによるモダン開発入門

    効率的なWebアプリケーションの作り方 ~PHPによるモダン開発入門