Thứ sáu, 06/09/2013 | 00:00 GMT+7

Cách sử dụng Symfony2 để thực hiện các hoạt động CRUD trên VPS (Phần 2)


Về Symfony

Symfony là một khung công tác phát triển web PHP open-souce - một bộ công cụ và phương pháp giúp bạn xây dựng các ứng dụng tuyệt vời. Một số đặc điểm của khuôn khổ này là tốc độ, tính linh hoạt, khả năng mở rộng và tính ổn định. Bạn có thể sử dụng nó cho một ứng dụng web hoàn chỉnh mà còn cho các chức năng nhỏ hơn cần thiết cho dự án của bạn.

Trong hướng dẫn trước , ta đã bắt đầu tạo một ứng dụng nhỏ để minh họa cách thực hiện các thao tác CRUD (tạo, đọc, cập nhật, xóa) bằng cách sử dụng khung công tác Symfony2. Đối với điều này, ta đã cài đặt Symfony2 Standard Distribution và bắt đầu làm việc với các bài báo của ta từ database - nếu bạn đã làm theo tất cả các bước, bạn sẽ thấy tại www.example.com/Symfony/web/ app_dev.php/ news/ .

Những gì ta sẽ làm trong hướng dẫn này là xem cách thực hiện phần còn lại của các hoạt động CRUD - tạo, cập nhật và xóa - sử dụng cùng một module dữ liệu mà ta đã bắt đầu làm việc trong phần trước. Do đó, có thể giả định bạn đã xem qua phần hướng dẫn trước trước khi bắt đầu phần này.

Tạo dữ liệu

Để tạo dữ liệu, trước tiên ta hãy tạo một tuyến đường khác đến trang biểu mẫu để thêm bài báo của ta . Vì vậy, hãy chỉnh sửa file routing.yml từ NewsBundle của ta :

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

Và thêm một tuyến đường mới:

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

Những gì bạn có thể nhận thấy bây giờ là bạn sẽ có xung đột với mẫu từ tuyến đường ta đã tạo trước đó ( foo_news_show ) vì nó sẽ nhìn vào từ thêm và nghĩ rằng đó là ID của tin tức cần được tìm thấy. Vì vậy, hãy chỉnh sửa tuyến foo_news_show và tạo một yêu cầu rằng biến {id} là một số nguyên. Vì vậy, hãy biến đổi nó như vậy:

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

Được rồi, lưu file và bây giờ ta hãy tạo phương thức addAction () của ta trong DefaultController để hoạt động như lệnh gọi lại cho tuyến đường này. Vì vậy, hãy chỉnh sửa file DefaultController.php:

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

Điều đầu tiên cần làm là ta cần đảm bảo lớp tải lớp thực thể Tin tức, thành phần Yêu cầu Symfony cho quá trình xử lý Biểu mẫu và thành phần Phản hồi. Vì vậy, ở đầu file bên dưới khai báo không gian tên, hãy thêm dòng sau:

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

Bây giờ, bên dưới phương thức showAction () , hãy thêm phương thức addAction () mới :

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);
 }

Điều gì xảy ra ở đây sau đó? Đầu tiên, ta khởi tạo một đối tượng News và đặt ngày tạo của nó thành thời gian hiện tại. Sau đó, ta sử dụng trình tạo biểu mẫu Symfony để tạo biểu mẫu có hai trường ( trùng với các thuộc tính trong thực thể Tin tức của ta ) và một nút gửi. Khi kết thúc hàm, sau đó ta tạo biểu mẫu và chuyển nó vào file mẫu news_add.html.twig trong biến biểu mẫu để nó được hiển thị. Hãy nhanh chóng tạo file đó và sau đó ta sẽ quay lại giải thích phần xử lý biểu mẫu. Vì vậy, hãy tạo mẫu mới ở nơi bạn đã tạo phần còn lại:

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

Và thêm dòng đơn giản sau vào đó:

{{ form(form) }}

Lưu và kiểm tra trang bằng cách trỏ trình duyệt của bạn đến tuyến đường mới và bạn sẽ thấy biểu mẫu:

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

Bây giờ điều gì xảy ra nếu bạn gửi nó? Nếu bạn nhìn vào phương thức addAction () mà ta vừa tạo, bạn sẽ thấy khối này mà ta chưa nói đến:

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

Về cơ bản, điều này sẽ kiểm tra xem một yêu cầu biểu mẫu đã được chuyển chưa (hãy nhớ rằng đối tượng Yêu cầu được chuyển như một đối số?) Và nếu nó hợp lệ, sau đó tự động cập nhật đối tượng $ news mà ta vừa tạo và sử dụng trình quản lý học thuyết để duy trì nó vào database . Sau đó, nó tạo một đối tượng Phản hồi mới với thông báo thành công sẽ được in trên màn hình. Nếu không có yêu cầu biểu mẫu nào đến, nó sẽ bỏ qua các bước này và hiển thị biểu mẫu theo cách bình thường. Đơn giản.

Cập nhật dữ liệu

Bây giờ ta đã biết cách đọc các trang tin tức và thêm các trang mới, việc cập nhật chúng sẽ thực sự dễ dàng - về cơ bản nó là kết hợp hai hành động. Giống như mọi khi, hãy thêm một tuyến mới vào file routing.yml của ta :

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

Và lộ editor của ta :

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

Như bạn thấy , ta duy trì yêu cầu đối với {id} là một số nguyên và ta trỏ đến một phương thức mới trong cùng một Bộ điều khiển được gọi là editAction () - mà bây giờ ta sẽ phải tạo. Vì vậy, hãy chỉnh sửa lại file lớp:

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

Và thêm phương thức mới:

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);
 }

Những gì xảy ra ở đây lại khá đơn giản. Sự khác biệt giữa phương thức này và addAction () là thay vì ta khởi tạo một thực thể Tin tức mới, ta lấy một thực thể hiện có từ database . Đối tượng $ news sau đó sẽ lại là cơ sở cho việc xây dựng biểu mẫu. Và như bạn nhận thấy, ta có thể sử dụng cùng một file mẫu để hiển thị biểu mẫu trong ví dụ đơn giản này. Một sự khác biệt nhỏ khác là ta có trình quản lý thực thể từ sớm và ta sẽ không phải sử dụng phương thức Kiên trì () của nó trong quá trình xử lý biểu mẫu vì đối tượng $ news đã được quản lý bởi nó. Vì vậy, sử dụng flush () là đủ để lưu nó vào database .

Bạn có thể tiếp tục và thử chỉnh sửa trang tin tức có ID 1 tại www.example.com/Symfony/web/ app_dev.php / news / 1 / edit và bạn sẽ thấy kết quả.

Xóa dữ liệu

Điều cuối cùng ta sẽ xem xét trong hướng dẫn này là cách xóa các trang tin tức của ta . Vì vậy, như thường lệ, hãy cài đặt một tuyến đường sẽ đưa ta đến trang xác nhận xóa. Vì vậy, hãy chỉnh sửa lại file routing.yml :

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

Và paste vào tuyến đường sau:

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

Tiếp theo, hãy tạo phương thức deleteAction () trong DefaultController của ta . Chỉnh sửa file lớp:

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

Và thêm phương thức mới:

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);
}

Phương thức này thực hiện hầu hết những gì editAction () thực hiện ngoại trừ việc thay vì xây dựng một biểu mẫu chỉnh sửa, nó chỉ xuất ra một nút gửi để xóa đối tượng $ news đã được truy xuất. Sau đó, khi biểu mẫu được gửi, ta sử dụng phương thức remove () của trình quản lý thực thể để xóa trang tin tức khỏi bài viết. Và bạn sẽ nhận thấy rằng ta đang sử dụng cùng một file mẫu: news_add.html.twig .

Nếu bây giờ bạn chuyển đến www.example.com/Symfony/web/ app_dev.php / news / 1 / delete , tất cả những gì bạn sẽ thấy chỉ là một nút xóa. Vì vậy, hãy thêm một sửa đổi nhỏ vào file mẫu của ta để trong trường hợp có nút xóa, bao gồm một số văn bản. Vì vậy, hãy chỉnh sửa file mẫu:

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

Và phía trên những gì đã có trong đó, hãy dán như sau:

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

Thao tác này sẽ in ra một văn bản xác nhận bao gồm tiêu đề của trang tin tức trong câu hỏi (được lấy từ biến biểu mẫu được chuyển đến mẫu). Bây giờ nếu bạn làm mới trang, bạn sẽ thấy nó ở đó và bạn có thể nhấp vào xóa để xóa tin tức có ID 1. Sau đó, bạn sẽ nhận được thông báo xác nhận được gửi bởi đối tượng Phản hồi mà ta đã tạo.

Dọn dẹp

Bây giờ ta đã triển khai các hoạt động CRUD cốt lõi nên đã đến lúc hoàn thiện ứng dụng nhỏ của ta bằng cách làm tròn nó lên một chút. Điều này nghĩa là thêm một số liên kết trên trang danh sách tin tức sẽ nhanh chóng cho phép bạn thực hiện các thao tác. Ta đã xem cách tạo liên kết trong mẫu trong hướng dẫn cuối cùng, vì vậy bây giờ nó không phải là vấn đề. Chỉnh sửa file mẫu news_show_all.html.twig và thêm một số liên kết administrator :

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

Dưới dòng sau:

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

Dán cái này:

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

Và ở đầu trang dán cái này:

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

Bây giờ, hãy truy cập www.example.com/Symfony/web/ app_dev.php / news / và xem nó hoạt động. Ở đó, bạn sẽ có các liên kết để chỉnh sửa và xóa từng trang tin tức cũng như một liên kết hàng đầu để tạo các mẩu tin mới.

Kết luận

Trong phần này và các bài hướng dẫn trước, ta đã biết cách xây dựng một ứng dụng Symfony2 nhỏ thực hiện CRUD trên mô hình dữ liệu của ta , các trang tin tức. Tệp lớp DefaultController.php của bạn bây giờ sẽ trông giống như sau:

<?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);
  }

}

Mặc dù điều này rất đơn giản, Symfony2 có khả năng mở rộng dữ liệu phức tạp hơn nhiều, được cấu trúc trong nhiều bảng và thực hiện những điều kỳ diệu khi quản lý nó. Cuối cùng, sử dụng hệ thống tạo khuôn mẫu Twig với Symfony cho phép bạn tạo các trang web rất mạnh mẽ và dễ quản lý. Chúc may mắn!

Bài viết gửi bởi: Danny

Tags:

Các tin liên quan