Symfony2プロジェクトでZend GDataを使用する





Symfonyフレームワークの主要な開発者であるFabien Potencierは、2009年のZend / PHP Conferenceで、Symfony 1.3 / 1.4とZend Frameworkを共有することの利点について報告しました。 彼のスピーチの主なポイントは、彼の個人ウェブサイトで公開されているプレゼンテーションで利用可能です[1]。



ご存知のように、Symfony2はPHP言語の最新機能を使用して作成されたほぼ新しいフレームワークです。 現時点では、開発はRCサイクルに移行しており、最初のSymfonyブランチで作業した経験を持つ開発者(および彼らだけでなく)が新しいフラッグシップに目を向けています。 しかし、標準版には多数のコンポーネントが含まれていますが、Symfony2はWeb開発者のすべてのニーズに対応しているわけではないため、遅かれ早かれ、外部ライブラリを接続するという疑問が生じます。



明らかに、この観点から、Zendライブラリの膨大なセット(Gdata、Search_Lucene、Pdfなど)は無視できません。 この投稿では、 Google Data APIと対話するためのライブラリであるZend Gdataの例を使用して、Symfony2とZendを統合するプロセスについて説明します [2]。





Symfony2のインストールについて簡単に説明します





README標準symfony2ディストリビューションで述べられているように、開発者はgitの使用を推奨しなくなり、代わりに公式サイトからアーカイブをダウンロードすることを提案します。 執筆時点では、最新バージョンはRC4です。 以下のすべては、クラス名に影響を与えるCommandで重要なリファクタリングが実行され、コードジェネレーターが登場したため、いくつかの予約を使用して以前のバージョンで動作します。 GITを使用すると 、ベンダーディレクトリが.gitignoreに追加されるため、ベンダーなしでアーカイブをダウンロードすることを好みます [3]。



開発には、Apache WebサーバーとPHP 5.3.2(以上)で十分です。 詳細な要件は、 ドキュメント [4]で詳述されています



Zend Gdataのプロジェクトへの統合





この記事で提示された決定は、すでに上で述べたFabienの提示によって促されました。 インターネット上では、Zendディストリビューションを正規表現で処理するなど、非常にクレイジーなソリューションを見つけることができます。 コメントで他の提案を聞いてうれしいです。 stackoverflowに関する議論もあります[5]。



プラグインライブラリの配布ライブラリに変更を加えると、アップグレード中に問題が発生する可能性があり(また、一般的に味が悪いと考えられます)、サーバー環境変数へのバインドは開発者を制限するため、提案されたソリューションは標準のSymfony2およびphpツールのみを使用します。



まず、Zend FrameworkのWebサイトに従って、 Gdataディストリビューションをダウンロードします[6]。



プロジェクトに次のディレクトリ構造を作成します。



vendor/

-> zend/

--> lib/

---> Zend/

----> [Zend directory from Zend GData package]

--> README

--> LICENSE









Zend GDataディストリビューションからREADMEおよびLICENSEファイルをコピーします。 app / autoload.phpにプレフィックス「Zend_」を登録します。



  $loader->registerPrefixes(array( // ...  ,   Twig  Twig_Extensions 'Zend_' => __DIR__.'/../vendor/zend/lib', ));
      
      







次に、Fabienneプレゼンテーションのコードをファイルの最後に追加します(Swift Mailerと同様)。



  // Zend Framework GData needs a special autoload fix too set_include_path(__DIR__.'/../vendor/zend/lib'.PATH_SEPARATOR.get_include_path());
      
      







これで、Zend GDataに含まれるクラスは、Symfony2ローダーによってプレフィックス「Zend_」で定義され、Gdataディストリビューションに含まれる多数の無条件の要求はすべて、変更されたinclude_pathのおかげで正しく動作します。 ロードされたサーバーでは、php.iniでinclude_path値を指定するのが賢明である可能性があります。



サービス





Symfony2 [7]の用語集を引用すると、 サービスは、グローバルに使用されるタスクを実行するPHPオブジェクトの一般的な用語です。 例には、データベース接続または電子メールを送信するオブジェクトが含まれます。



この定義に基づいて、この場合、Zend_Gdataがサービスであることを理解するのは簡単です。



次に、Google GData APIサービスを使用して、ブログエントリをblogspot.comからデータベースにアップロードするコンソールチームを開発します。



まず、GdataTestBundleバンドルを作成します。 コードジェネレーターが登場したので、これは非常に簡単に行われます。



  $ php app/console generate:bundle --namespace=Habr/GDataBundle --format=yml
      
      







さて、src / Habr / GDataBundle / Resources / config / services.yml設定ファイルで、次の行を追加します(ブロガーでブログにアクセスするには、コメントでマークされた行の〜を実際のデータに置き換える必要があります):



  parameters: gdata.class: Zend_Gdata gdata.http_client.class: Zend_Gdata_HttpClient gdata.http_client_factory.class: Zend_Gdata_ClientLogin gdata.username: ~ # <email_address@gmail.com> gdata.password: ~ # <password> gdata.blog_id: ~ # <blog ID> gdata.service_name: blogger services: gdata_http_client: class: %gdata.http_client.class% factory_class: %gdata.http_client_factory.class% factory_method: getHttpClient arguments: - %gdata.username% - %gdata.password% - %gdata.service_name% gdata: class: %gdata.class% arguments: [@gdata_http_client]
      
      







この構成ファイルの内容について詳しく説明します。 Symfony2は、サービスを初期化し、依存関係を解決する多くの方法を提供します。 最も単純なケースでは、構成で指定されたクラス名に基づいて、ContainerInterfaceインターフェースからget()メソッドを使用してクライアントコードに返されるオブジェクトが作成されます。 実際には、オブジェクトは互いに複雑な関係にあり、多くの場合、1つのサービスの初期化には、コンストラクターへの引数として渡される別のサービスのインスタンスが必要です。 このケースは上記のgdataサービスで観察できます。



Zend_Gdata_HttpClientの初期化はさらに興味深い-このクラスのオブジェクトのインスタンスは、引数も渡されるファクトリクラスの静的メソッド(Zend_Gdata_ClientLogin)を呼び出すことで作成されます。 ファクトリクラスを使用してサービスを初期化する方法の詳細については、Symfony Cookbook [8]の特別な章を参照してください。

定義したサービスを使用するコンソールコマンドを作成するときに、結果の構成をテストできます。



モデル





Blogger.comからアップロードされた投稿を保存するための簡単なモデルを作成します。これは、組み込みジェネレーターによっても支援されます(モデルの構成に独自の変更を加えたくない場合は、対話型で後続のすべての質問に対してEnterを押します):



  $ php app/console doctrine:generate:entity --entity="HabrGDataBundle:Post" --fields="title:string(255) content:text remote_id:string(255) created_at:datetime"
      
      







src / Habr / GDataBundle / Entityディレクトリには、生成されたBlog.phpファイルがあり、必要なすべてのゲッターとセッターが含まれています。 さらに、DBMSレベルで行われた変更を反映するには、最初にデータベースへの接続を構成する必要があります。



MySQLを使用するには、接続設定を使用して、app / config / parameters.iniの対応する部分を次のように変更する必要があります。



  [parameters] ; ... database_driver = pdo_mysql database_host = localhost database_name = habr database_user = root database_password = ; …
      
      







次のステップは、データベースを作成することです。



  $ php app/console doctrine:database:create
      
      







モデルに基づいてテーブルを作成した後:

  $ php app/console doctrine:schema:update --force
      
      







phpmyadminまたは使用するデータベースの他のクライアントでコマンドの結果を確認できます。



チーム



Symfony 1.4で「タスク」と呼ばれたエンティティは、Symfony2のチームになりました。 現在のリリースにはまだコマンド用のジェネレーターがないため、バンドルのルートディレクトリ内にCommandサブディレクトリを手動で作成し、FetchFeedCommand.phpファイルを配置します(コマンドサフィックスが必要です)。 コマンド [9](およびSymfony2コンポーネントの大部分)の実装は非常に単純であるため、コメント付きのソースコードのみを提供します。



  // FetchFeedCommand.php <?php namespace Habr\GDataBundle\Command; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Habr\GDataBundle\Entity\Post; /** * FetchFeedCommand * @author temochka <http://temochka.habrahabr.ru> * @package HabrGDataBundle * @subpackage command * @version 0.1 */ class FetchFeedCommand extends ContainerAwareCommand { /** *   */ protected function configure() { $this->setName('gdata:blogger:fetch-feed'); } /** * * @param InputInterface $input * @param OutputInterface $output */ protected function execute(InputInterface $input, OutputInterface $output) { //    gdata ( Zend_Gdata) $gdClient = $this->getContainer()->get('gdata'); //    $blogID = $this->getContainer()->getParameter('gdata.blog_id'); //    API $query = new \Zend_Gdata_Query('http://www.blogger.com/feeds/' . $blogID . '/posts/default'); $feed = $gdClient->getFeed($query); //   EntityManager'   doctrine $em = $this->getContainer()->get('doctrine')->getEntityManager(); foreach($feed->entries as $entry) { //   $post = new Post; $post->setTitle($entry->title->text); $post->setRemoteId($entry->id); $post->setContent($entry->content); $post->setCreatedAt(new \DateTime($entry->published->text)); $em->persist($post); $output->writeln(sprintf("\tNew post %s has been added.\n", $entry->title->text)); } //     $em->flush(); } }
      
      







これで、setNameの呼び出しで定義された./app/consoleの名前を渡すことでコマンドを実行できます。

  $ ./app/console gdata:blogger:fetch-feed
      
      







結果は、データベース投稿テーブル内のすべてのブログエントリになります。



おわりに





上記の例は、Blogger.comからオープンブログフィードを受信するために認証が必要ないため、多少合成されています。 Symfony2を使用してさらに経験を積むことを希望する人は、新しいブログエントリの追加または削除を自分で実装できます。 詳細なドキュメントへのリンクはすでに上記で提供されています。



一般に、Symfony2はすでに「印象的であるが不安定なもの」の状態からすでに成長していることを付け加えたいと思います。 このフレームワークは、本格的なプロジェクトに対応しています。

PSこの投稿の公開に協力してくれたすべての人に感謝します。



参照資料



  1. SymfonyとZend Frameworkの連携-2009
  2. GData API
  3. ベンダーディレクトリを無視する
  4. Symfony2を実行するための要件
  5. StackoverflowのSymfony2でZend_GDataを使用することに関する質問
  6. Zend GDataダウンロードページ
  7. Symfony2用語集
  8. 工場を使用してサービスを作成する方法
  9. コンソール/コマンドラインコマンドの作成方法





All Articles