Symfonyについて

Symfony は、オープンソースのPHPWeb開発フレームワークです。優れたアプリケーションの構築に役立つツールと方法論のセットです。 このフレームワークの特徴のいくつかは、その速度、柔軟性、スケーラビリティ、および安定性です。 本格的なWebアプリケーションだけでなく、プロジェクトに必要な小さな機能にも使用できます。

前のチュートリアルでは、Symfony2フレームワークを使用してCRUD(作成、読み取り、更新、削除)操作を実行する方法を説明する小さなアプリケーションの作成を開始しました。 このために、 Symfony2 Standard Distribution をインストールし、データベースからのニュース記事の操作を開始しました。すべての手順を実行すると、www.example.com/Symfony/webに表示されます。 /app_dev.php/news/

このチュートリアルでは、前回の作業で開始したのと同じデータモジュールを使用して、残りのCRUD操作(作成、更新、削除)を実行する方法を確認します。 したがって、このチュートリアルを開始する前に、前のチュートリアルを完了していることを前提としています。

データの作成

データを作成するために、まずニュース記事を追加するためのフォームページへの別のルートを作成しましょう。 それでは、NewsBundleからrouting.ymlファイルを編集しましょう。

nano /var/www/Symfony/src/Foo/NewsBundle/Resources/config/routing.yml

そして、新しいルートを追加します。

foo_news_add:
    pattern:  /news/add/
    defaults: { _controller: FooNewsBundle:Default:add }

ここで気付くかもしれないのは、 add という単語を見て、それがIDであると考えるため、以前に作成したルート( foo_news_show )のパターンと競合することです。見つける必要があるニュースの。 それでは、 foo_news_show ルートを編集して、{id}変数が整数であるという要件を作成しましょう。 したがって、次のように変換します。

foo_news_show:
    pattern:  /news/{id}
    defaults: { _controller: FooNewsBundle:Default:show }
    requirements:
        id:  \d+

では、ファイルを保存して、 DefaultControlleraddAction()メソッドを作成し、このルートのコールバックとして機能させましょう。 それでは、DefaultController.phpファイルを編集しましょう。

nano /var/www/Symfony/src/Foo/NewsBundle/Controller/DefaultController.php

最初に行うことは、クラスがNewsエンティティクラス、フォーム処理用のSymfony Requestコンポーネント、およびResponseコンポーネントをロードすることを確認する必要があります。 したがって、名前空間宣言の下のファイルの上部に、次の行を追加します。

use Foo\NewsBundle\Entity\News;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

ここで、 showAction()メソッドの下に、新しい addAction()メソッドを追加しましょう。

public function addAction(Request $request) {

     $news = new News();
     $news->setCreatedDate(new \DateTime());
    
     $form = $this->createFormBuilder($news)
        ->add('title', 'text')
        ->add('body', 'text')
        ->add('save', 'submit')
        ->getForm();

     $form->handleRequest($request);    
     if ($form->isValid()) {
       $em = $this->getDoctrine()->getManager();
       $em->persist($news);
       $em->flush();
       return new Response('News added successfuly');
     }
    
     $build['form'] = $form->createView();
     return $this->render('FooNewsBundle:Default:news_add.html.twig', $build);
 }

では、ここで何が起こりますか? まず、Newsオブジェクトをインスタンス化し、その作成日を現在の時刻に設定します。 次に、Symfonyフォームビルダーを使用して、2つのフィールド(ニュースエンティティのプロパティに一致する)と送信ボタンを持つフォームを作成します。 関数の最後で、フォームを作成し、それをform変数のnews_add.html.twigテンプレートファイルに渡して表示します。 そのファイルをすばやく作成してから、フォーム処理部分について説明します。 したがって、残りを作成した場所に新しいテンプレートを作成します。

nano /var/www/Symfony/src/Foo/NewsBundle/Resources/views/Default/news_add.html.twig

そして、それに次の簡単な行を追加します。

{{ form(form) }}

ブラウザで新しいルートを指定してページを保存してテストすると、次のフォームが表示されます。

www.example.com/Symfony/web/app_dev.php/news/add

提出するとどうなりますか? 作成したばかりのaddAction()メソッドを見ると、まだ説明していない次のブロックが表示されます。

  $form->handleRequest($request);    
     if ($form->isValid()) {
       $em = $this->getDoctrine()->getManager();
       $em->persist($news);
       $em->flush();
       return new Response('News added successfully');
     }

これは基本的に、フォームリクエストが渡されたかどうかをチェックし(リクエストオブジェクトが引数として渡されたことを覚えていますか?)、それが有効である場合は、作成したばかりの $ news オブジェクトを自動的に更新し、DoctrineManagerを使用してそれをデータベースに永続化します。 次に、画面に出力される成功メッセージを含む新しいResponseオブジェクトを作成します。 フォームリクエストが届かない場合は、これらの手順をスキップして、通常の方法でフォームを表示します。 単純。

データの更新

ニュースページの読み方と新しいページの追加方法がわかったので、ニュースページの更新は非常に簡単になります。基本的には2つのアクションを組み合わせたものです。 いつものように、routing.ymlファイルに新しいルートを追加しましょう。

nano /var/www/Symfony/src/Foo/NewsBundle/Resources/config/routing.yml

そして私たちの編集ルート:

foo_news_edit:
    pattern:  /news/{id}/edit
    defaults: { _controller: FooNewsBundle:Default:edit }
    requirements:
        id:  \d+

ご覧のとおり、{id}が整数であるという要件を維持し、 editAction()と呼ばれる同じコントローラー内の新しいメソッドを指定します。これを作成する必要があります。 それでは、クラスファイルをもう一度編集しましょう。

nano /var/www/Symfony/src/Foo/NewsBundle/Controller/DefaultController.php

そして、新しいメソッドを追加します。

public function editAction($id, Request $request) {

    $em = $this->getDoctrine()->getManager();
    $news = $em->getRepository('FooNewsBundle:News')->find($id);
    if (!$news) {
      throw $this->createNotFoundException(
              'No news found for id ' . $id
      );
    }
    
    $form = $this->createFormBuilder($news)
        ->add('title', 'text')
        ->add('body', 'text')
        ->add('save', 'submit')
        ->getForm();

    $form->handleRequest($request);
 
    if ($form->isValid()) {
        $em->flush();
        return new Response('News updated successfully');
    }
    
    $build['form'] = $form->createView();

    return $this->render('FooNewsBundle:Default:news_add.html.twig', $build);
 }

ここで起こることはまた非常に簡単です。 このメソッドとaddAction()の違いは、新しい News エンティティをインスタンス化する代わりに、データベースから既存のエンティティを取得することです。 結果として得られる$news オブジェクトは、フォーム構築の基礎になります。 お気づきのとおり、この単純な例では、フォームのレンダリングに同じテンプレートファイルを使用できます。 もう1つの小さな違いは、エンティティマネージャーを早い段階で取得し、 $ news オブジェクトが既に管理されているため、フォーム処理でその persist()メソッドを使用する必要がないことです。それによります。 したがって、 flush()を使用するだけで、データベースに保存できます。

www.example.com/Symfony/web/app_dev.php/news/1/editでID1のニュースページを編集してみると、結果が表示されます。

データの削除

このチュートリアルで最後に見るのは、ニュースページを削除する方法です。 いつものように、削除確認ページに移動するルートを設定しましょう。 したがって、routing.ymlファイルを再度編集します。

nano /var/www/Symfony/src/Foo/NewsBundle/Resources/config/routing.yml

そして、次のルートに貼り付けます。

foo_news_delete:
    pattern:  /news/{id}/delete/
    defaults: { _controller: FooNewsBundle:Default:delete }
    requirements:
        id:  \d+

次に、 DefaultControllerにメソッドdeleteAction()を作成しましょう。 クラスファイルを編集します。

nano /var/www/Symfony/src/Foo/NewsBundle/Controller/DefaultController.php

そして、新しいメソッドを追加します。

public function deleteAction($id, Request $request) {

    $em = $this->getDoctrine()->getManager();
    $news = $em->getRepository('FooNewsBundle:News')->find($id);
    if (!$news) {
      throw $this->createNotFoundException(
              'No news found for id ' . $id
      );
    }

    $form = $this->createFormBuilder($news)
            ->add('delete', 'submit')
            ->getForm();

    $form->handleRequest($request);

    if ($form->isValid()) {
      $em->remove($news);
      $em->flush();
      return new Response('News deleted successfully');
    }
    
    $build['form'] = $form->createView();
    return $this->render('FooNewsBundle:Default:news_add.html.twig', $build);
}

このメソッドは、 editAction()が行うことのほとんどを実行しますが、編集フォームを作成する代わりに、取得した $newsオブジェクトを削除するための送信ボタンを出力するだけです。 次に、フォームが送信されると、エンティティマネージャーの remove()メソッドを使用して、記事からニュースページを削除します。 また、同じテンプレートファイルnews_add.html.twigを使用していることに気付くでしょう。

www.example.com/Symfony/web/app_dev.php/news/1/delete に移動すると、削除ボタンだけが表示されます。 それでは、テンプレートファイルに小さな変更を加えて、削除ボタンが存在する場合にテキストも含めるようにします。 したがって、テンプレートファイルを編集します。

nano /var/www/Symfony/src/Foo/NewsBundle/Resources/views/Default/news_add.html.twig

そして、すでにそこにあるものの上に、以下を貼り付けます:

{% if form.delete is defined %}
      Are you sure you want to delete the news page: {{ form.vars.value.title }} ?
    {% endif %}

これにより、質問のニュースページのタイトルを含む確認テキストが出力されます(テンプレートに渡されたフォーム変数から取得)。 ここでページを更新すると、そこにページが表示され、[削除]をクリックしてID1のニュースを削除できます。 次に、作成したResponseオブジェクトによって配信される確認メッセージが表示されます。

掃除

これでコアCRUD操作が実装されたので、小さなアプリケーションを少し切り上げて完成させます。 これは、ニュースリストページにいくつかのリンクを追加して、操作をすばやく実行できるようにすることを意味します。 前回のチュートリアルでテンプレートにリンクを作成する方法を見てきましたので、問題はないはずです。 news_show_all.html.twig テンプレートファイルを編集して、いくつかの管理リンクを追加しましょう。

nano /var/www/Symfony/src/Foo/NewsBundle/Resources/views/Default/news_show_all.html.twig

次の行の下:

<h3><a href="{{ path('foo_news_show', {'id':  new.Id  }) }}">{{ new.Title }}</a></h3>

これを貼り付けます:

<a href="{{ path('foo_news_edit', {'id':  new.Id  }) }}">Edit</a> | <a href="{{ path('foo_news_delete', {'id':  new.Id  }) }}">Delete</a><hr />

そして、ページの上部にこれを貼り付けます:

<a href="{{ path('foo_news_add') }}">Add news</a>

次に、 www.example.com/Symfony/web/app_dev.php/news/ にアクセスして、動作を確認します。 そこには、各ニュースページを編集および削除するためのリンクと、新しいニュースを作成するためのトップリンクがあります。

結論

このチュートリアルと前のチュートリアルでは、データモデルであるニュースページでCRUDを実行する小さなSymfony2アプリケーションを構築する方法を見てきました。 DefaultController.phpクラスファイルは次のようになります。

<?php

namespace Foo\NewsBundle\Controller;

use Foo\NewsBundle\Entity\News;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class DefaultController extends Controller {

  public function indexAction() {
    $news = $this->getDoctrine()
            ->getRepository('FooNewsBundle:News')
            ->findAll();
      if (!$news) {
        throw $this->createNotFoundException('No news found');
      }
    
      $build['news'] = $news;
      return $this->render('FooNewsBundle:Default:news_show_all.html.twig', $build);
  }

  public function showAction($id) {
      $news = $this->getDoctrine()
            ->getRepository('FooNewsBundle:News')
            ->find($id);
      if (!$news) {
        throw $this->createNotFoundException('No news found by id ' . $id);
      }
    
      $build['news_item'] = $news;
      return $this->render('FooNewsBundle:Default:news_show.html.twig', $build);
   }

   public function addAction(Request $request) {

     $news = new News();
     $news->setCreatedDate(new \DateTime());
    
     $form = $this->createFormBuilder($news)
        ->add('title', 'text')
        ->add('body', 'text')
        ->add('save', 'submit')
        ->getForm();

     $form->handleRequest($request);    
     if ($form->isValid()) {
       $em = $this->getDoctrine()->getManager();
       $em->persist($news);
       $em->flush();
       return new Response('News added successfuly');
     }
    
     $build['form'] = $form->createView();
     return $this->render('FooNewsBundle:Default:news_add.html.twig', $build);
  }

  public function editAction($id, Request $request) {

    $em = $this->getDoctrine()->getManager();
    $news = $em->getRepository('FooNewsBundle:News')->find($id);
    if (!$news) {
      throw $this->createNotFoundException(
              'No news found for id ' . $id
      );
    }
    
    $form = $this->createFormBuilder($news)
        ->add('title', 'text')
        ->add('body', 'text')
        ->add('save', 'submit')
        ->getForm();

    $form->handleRequest($request);
 
    if ($form->isValid()) {
        $em->flush();
        return new Response('News updated successfully');
    }
    
    $build['form'] = $form->createView();

    return $this->render('FooNewsBundle:Default:news_add.html.twig', $build);
  }

  public function deleteAction($id, Request $request) {

    $em = $this->getDoctrine()->getManager();
    $news = $em->getRepository('FooNewsBundle:News')->find($id);
    if (!$news) {
      throw $this->createNotFoundException(
              'No news found for id ' . $id
      );
    }

    $form = $this->createFormBuilder($news)
            ->add('delete', 'submit')
            ->getForm();

    $form->handleRequest($request);

    if ($form->isValid()) {
      $em->remove($news);
      $em->flush();
    }
    
    $build['form'] = $form->createView();
    return $this->render('FooNewsBundle:Default:news_add.html.twig', $build);
  }

}

これは非常に単純ですが、Symfony2ははるかに複雑なデータにスケールアップすることができ、複数のテーブルで構造化されており、データの管理に関しては驚異的なパフォーマンスを発揮します。 最後に、SymfonyでTwigテンプレートシステムを使用すると、非常に強力で管理しやすいWebサイトを作成できます。 幸運を!

投稿者: Danny