Symfony - Các khái niệm nâng cao
Trong chương này, chúng ta sẽ tìm hiểu về một số khái niệm nâng cao trong Symfony framework.
Bộ đệm HTTP
Bộ nhớ đệm trong ứng dụng web cải thiện hiệu suất. Ví dụ: các sản phẩm nóng trong ứng dụng web giỏ hàng có thể được lưu vào bộ nhớ cache trong một thời gian giới hạn, để có thể trình bày cho khách hàng một cách nhanh chóng mà không cần truy cập vào cơ sở dữ liệu. Sau đây là một số thành phần cơ bản của Cache.
Mục bộ nhớ đệm
Mục Cache là một đơn vị thông tin được lưu trữ dưới dạng một cặp khóa / giá trị. Cáckey nên là chuỗi và valuecó thể là bất kỳ đối tượng PHP nào. Các đối tượng PHP được lưu trữ dưới dạng chuỗi bằng cách tuần tự hóa và chuyển đổi trở lại thành các đối tượng trong khi đọc các mục.
Bộ điều hợp bộ nhớ đệm
Bộ điều hợp bộ nhớ cache là cơ chế thực tế để lưu trữ mặt hàng trong cửa hàng. Lưu trữ có thể là một bộ nhớ, hệ thống tệp, cơ sở dữ liệu, redis, v.v. Thành phần bộ nhớ cache cung cấp mộtAdapterInterfacequa đó bộ điều hợp có thể lưu trữ mục bộ nhớ cache trong cửa hàng phụ. Có rất nhiều bộ điều hợp bộ nhớ đệm tích hợp sẵn. Một vài trong số chúng như sau:
Bộ điều hợp bộ nhớ cache mảng - Các mục bộ nhớ cache được lưu trữ trong mảng PHP.
Bộ điều hợp bộ nhớ đệm hệ thống tệp - Các mục trong bộ nhớ cache được lưu trữ trong tệp.
Bộ điều hợp bộ đệm tệp PHP - Các mục trong bộ nhớ cache được lưu trữ dưới dạng tệp php.
Bộ điều hợp Bộ nhớ cache APCu - Các mục trong bộ nhớ cache được lưu trữ trong bộ nhớ dùng chung bằng cách sử dụng mở rộng APCu PHP.
Redis Cache Adapter - Các mục trong bộ nhớ cache được lưu trữ trong máy chủ Redis.
Bộ điều hợp bộ nhớ cache PDO và Doctrine DBAL - Các mục bộ nhớ cache được lưu trữ trong cơ sở dữ liệu.
Bộ điều hợp bộ nhớ cache chuỗi - Kết hợp nhiều bộ điều hợp bộ nhớ cache cho mục đích sao chép.
Bộ điều hợp bộ đệm ẩn proxy - Các mục bộ nhớ cache được lưu trữ bằng bộ điều hợp bên thứ ba, bộ điều hợp này triển khai CacheItemPoolInterface.
Nhóm bộ nhớ đệm
Cache Pool là một kho lưu trữ hợp lý các mục trong bộ nhớ cache. Nhóm bộ nhớ cache được triển khai bởi bộ điều hợp bộ nhớ cache.
Ứng dụng đơn giản
Hãy để chúng tôi tạo một ứng dụng đơn giản để hiểu khái niệm bộ nhớ cache.
Step 1 - Tạo một ứng dụng mới, cache-example.
cd /path/to/app
mkdir cache-example
cd cache-example
Step 2 - Cài đặt thành phần bộ nhớ cache.
composer require symfony/cache
Step 3 - Tạo một bộ điều hợp hệ thống tệp.
require __DIR__ . '/vendor/autoload.php';
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
$cache = new FilesystemAdapter();
Step 4 - Tạo một mục bộ nhớ cache bằng cách sử dụng getItem và setphương pháp tiếp hợp. getItem tìm nạp mục bộ nhớ cache bằng cách sử dụng khóa của nó. nếu khóa không còn tồn tại, nó sẽ tạo ra một mục mới. phương pháp set lưu trữ dữ liệu thực tế.
$usercache = $cache->getitem('item.users');
$usercache->set(['jon', 'peter']);
$cache->save($usercache);
Step 5 - Truy cập mục bộ nhớ cache bằng getItem, isHit và getphương pháp. isHit thông báo tính khả dụng của mục bộ nhớ cache và phương thức get cung cấp dữ liệu thực tế.
$userCache = $cache->getItem('item.users');
if(!$userCache->isHit()) {
echo "item.users is not available";
} else {
$users = $userCache->get();
var_dump($users);
}
Step 6 - Xóa mục bộ nhớ cache bằng cách sử dụng deleteItem phương pháp.
$cache->deleteItem('item.users');
Danh sách mã hoàn chỉnh như sau.
<?php
require __DIR__ . '/vendor/autoload.php';
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
$cache = new FilesystemAdapter();
$usercache = $cache->getitem('item.users');
$usercache->set(['jon', 'peter']);
$cache->save($usercache);
$userCache = $cache->getItem('item.users');
if(!$userCache->isHit()) {
echo "item.users is not available";
} else {
$users = $userCache->get();
var_dump($users);
}
$cache->deleteItem('item.users');
?>
Kết quả
array(2) {
[0]=>
string(3) "jon"
[1]=>
string(5) "peter"
}
Gỡ lỗi
Gỡ lỗi là một trong những hoạt động thường xuyên nhất trong khi phát triển ứng dụng. Symfony cung cấp một thành phần riêng biệt để dễ dàng quá trình gỡ lỗi. Chúng tôi có thể kích hoạt các công cụ gỡ lỗi Symfony bằng cách gọienable phương thức của lớp Gỡ lỗi.
use Symfony\Component\Debug\Debug
Debug::enable()
Symfony cung cấp hai lớp, ErrorHandler và ExceptionHandlercho mục đích gỡ lỗi. Trong khi ErrorHandler bắt các lỗi PHP và chuyển chúng thành các ngoại lệ, ErrorException hoặc FatalErrorException, thì ExceptionHandler bắt các ngoại lệ PHP chưa tìm thấy và chuyển chúng thành phản hồi PHP hữu ích. ErrorHandler và ExceptionHandler bị tắt theo mặc định. Chúng tôi có thể kích hoạt nó bằng cách sử dụng phương pháp đăng ký.
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\ExceptionHandler;
ErrorHandler::register();
ExceptionHandler::register();
Trong một ứng dụng web Symfony, debug environmentđược cung cấp bởi DebugBundle. Đăng ký gói trong AppKernel'sregisterBundles phương pháp để kích hoạt nó.
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
$bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle();
}
Hồ sơ
Việc phát triển một ứng dụng cần một công cụ lập hồ sơ đẳng cấp thế giới. Công cụ cấu hình thu thập tất cả thông tin thời gian chạy về một ứng dụng như thời gian thực thi, thời gian thực thi của từng mô-đun riêng lẻ, thời gian thực hiện bởi một hoạt động cơ sở dữ liệu, mức sử dụng bộ nhớ, v.v. Một ứng dụng web cần nhiều thông tin hơn như thời gian yêu cầu, thời gian cần thiết để tạo phản hồi, v.v. ngoài các chỉ số trên.
Symfony cho phép tất cả thông tin như vậy trong ứng dụng web theo mặc định. Symfony cung cấp một gói riêng để lập hồ sơ web có tên làWebProfilerBundle. Gói hồ sơ web có thể được bật trong ứng dụng web bằng cách đăng ký gói trong phương thức registerBundles của AppKernel.
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
}
Thành phần cấu hình web có thể được định cấu hình trong web_profile section của tệp cấu hình ứng dụng, app/config/config.xml
web_profiler:
toolbar: false
position: bottom
Ứng dụng Symfony hiển thị dữ liệu hồ sơ ở cuối trang dưới dạng một phần riêng biệt.
Symfony cũng cung cấp một cách dễ dàng để thêm các chi tiết tùy chỉnh về trang trong dữ liệu hồ sơ bằng cách sử dụng DataCollectorInterface interfacevà tiêu bản cành cây. Tóm lại, Symfony cho phép một nhà phát triển web tạo ra một ứng dụng đẳng cấp thế giới bằng cách cung cấp một khung cấu hình tuyệt vời một cách tương đối dễ dàng.
Bảo vệ
Như đã thảo luận trước đó, Symfony cung cấp một khung bảo mật mạnh mẽ thông qua thành phần bảo mật của nó. Thành phần bảo mật được chia thành bốn thành phần phụ như sau.
- symfony / security-core - Chức năng bảo mật cốt lõi.
- symfony / security-http - Tính năng bảo mật tích hợp trong giao thức HTTP.
- symfony / security-csrf - Bảo vệ chống giả mạo yêu cầu trên nhiều trang web trong ứng dụng web.
- symfony / security-acl - Khung bảo mật dựa trên danh sách kiểm soát truy cập nâng cao.
Xác thực và ủy quyền đơn giản
Hãy để chúng tôi tìm hiểu khái niệm xác thực và ủy quyền bằng ứng dụng demo đơn giản.
Step 1 - Tạo một ứng dụng web mới securitydemo bằng cách sử dụng lệnh sau.
symfony new securitydemo
Step 2- Bật tính năng bảo mật trong ứng dụng bằng tệp cấu hình bảo mật. Cấu hình liên quan đến bảo mật được đặt trong một tệp riêng biệt,security.yml. Cấu hình mặc định như sau.
security:
providers:
in_memory:
memory: ~
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
#http_basic: ~
#form_login: ~
Cấu hình mặc định cho phép nhà cung cấp bảo mật dựa trên bộ nhớ và quyền truy cập ẩn danh vào tất cả các trang. Phần tường lửa loại trừ các tệp phù hợp với mẫu,^/(_(profiler|wdt)|css|images|js)/từ khuôn khổ bảo mật. Mẫu mặc định bao gồm bảng định kiểu, hình ảnh và JavaScripts (cộng với các công cụ dành cho nhà phát triển như trình biên dịch).
Step 3 - Kích hoạt hệ thống xác thực bảo mật dựa trên HTTP bằng cách thêm tùy chọn http_basic trong phần chính như sau.
security:
# ...
firewalls:
# ...
main:
anonymous: ~
http_basic: ~
#form_login: ~
Step 4- Thêm một số người dùng trong phần nhà cung cấp bộ nhớ. Ngoài ra, hãy thêm vai trò cho người dùng.
security:
providers:
in_memory:
memory:
users:
myuser:
password: user
roles: 'ROLE_USER'
myadmin:
password: admin
roles: 'ROLE_ADMIN'
Chúng tôi đã thêm hai người dùng, người dùng trong vai trò ROLE_USER và quản trị viên trong vai trò ROLE_ADMIN.
Step 5- Thêm bộ mã hóa để có được thông tin chi tiết đầy đủ về người dùng đã đăng nhập hiện tại. Mục đích của bộ mã hóa là lấy thông tin chi tiết đầy đủ về đối tượng người dùng hiện tại từ yêu cầu web.
security:
# ...
encoders:
Symfony\Component\Security\Core\User\User: bcrypt
# ...
Symfony cung cấp một giao diện, UserInterface để lấy thông tin chi tiết về người dùng như tên người dùng, vai trò, mật khẩu, v.v. Chúng ta cần triển khai giao diện theo yêu cầu của mình và định cấu hình nó trong phần bộ mã hóa.
Ví dụ, chúng ta hãy xem xét rằng chi tiết người dùng có trong cơ sở dữ liệu. Sau đó, chúng ta cần tạo một lớp Người dùng mới và triển khai các phương thức UserInterface để lấy chi tiết người dùng từ cơ sở dữ liệu. Khi dữ liệu có sẵn, hệ thống bảo mật sẽ sử dụng nó để cho phép / từ chối người dùng. Symfony cung cấp triển khai Người dùng mặc định cho nhà cung cấp Bộ nhớ. Thuật toán được sử dụng để giải mã mật khẩu người dùng.
Step 6 - Mã hóa mật khẩu người dùng bằng bcryptthuật toán và đặt nó trong tệp cấu hình. Kể từ khi chúng tôi sử dụngbcryptThuật toán, Đối tượng người dùng cố gắng giải mã mật khẩu được chỉ định trong tệp cấu hình và sau đó cố gắng khớp với mật khẩu do người dùng nhập. Ứng dụng giao diện điều khiển Symfony cung cấp một lệnh đơn giản để mã hóa mật khẩu.
php bin/console security:encode-password admin
Symfony Password Encoder Utility
================================
------------------ -----------------------------------
Key Value
------------------ ------------------------------------
Encoder used Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder
Encoded password
$2y$12$0Hy6/.MNxWdFcCRDdstHU.hT5j3Mg1tqBunMLIUYkz6..IucpaPNO
------------------ ------------------------------------
! [NOTE] Bcrypt encoder used: the encoder generated its own built-in salt.
[OK] Password encoding succeeded
Step 7 - Sử dụng lệnh để tạo mật khẩu được mã hóa và cập nhật nó trong tệp cấu hình.
# To get started with security, check out the documentation:
# http://symfony.com/doc/current/security.html
security:
# http://symfony.com/doc/current/security.html#b-configuring-how-users-are-loaded
providers:
in_memory:
memory:
users:
user:
password: $2y$13$WsGWNufreEnVK1InBXL2cO/U7WftvfNvH
Vb/IJBH6JiYoDwVN4zoi
roles: 'ROLE_USER'
admin:
password: $2y$13$jQNdIeoNV1BKVbpnBuhKRuOL01NeMK
F7nEqEi/Mqlzgts0njK3toy
roles: 'ROLE_ADMIN'
encoders:
Symfony\Component\Security\Core\User\User: bcrypt
firewalls:
# disables authentication for assets and the profiler,
# adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
# activate different ways to authenticate
# http://symfony.com/doc/current/security.html#a-co
nfiguring-howyour-users-will-authenticate
http_basic: ~
# http://symfony.com/doc/current/cookbook/security/
form_login_setup.html
#form_login: ~
Step 8- Bây giờ, hãy áp dụng bảo mật cho một số phần của ứng dụng. Ví dụ: hạn chế phần quản trị đối với người dùng có vai trò, ROLE_ADMIN.
security:
# ...
firewalls:
# ...
default:
# ...
access_control:
# require ROLE_ADMIN for /admin*
- { path: ^/admin, roles: 'ROLE_ADMIN' }
Step 9 - Thêm một trang quản trị trong DefaultController như sau.
/**
* @Route("/admin")
*/
public function adminLandingAction() {
return new Response('<html><body>This is admin section.</body></html>');
}
Step 10- Cuối cùng, truy cập trang quản trị để kiểm tra cấu hình bảo mật trên trình duyệt. Trình duyệt sẽ hỏi tên người dùng và mật khẩu và chỉ cho phép những người dùng đã định cấu hình.
Kết quả
Quy trình làm việc
Workflow là một khái niệm nâng cao được sử dụng trong nhiều ứng dụng doanh nghiệp. Trong ứng dụng thương mại điện tử, quy trình phân phối sản phẩm là một quy trình làm việc. Sản phẩm được lập hóa đơn đầu tiên (tạo đơn hàng), thu mua từ cửa hàng và đóng gói (đóng gói / sẵn sàng gửi đi), và gửi đến người dùng. Nếu có bất kỳ vấn đề gì, sản phẩm sẽ được trả lại từ người dùng và đơn đặt hàng sẽ được hoàn nguyên. Thứ tự của luồng hành động là rất quan trọng. Ví dụ: chúng tôi không thể phân phối sản phẩm mà không lập hóa đơn.
Thành phần Symfony cung cấp một cách hướng đối tượng để xác định và quản lý quy trình làm việc. Mỗi bước trong một quy trình được gọi làplace và hành động cần thiết để di chuyển từ nơi này đến nơi khác được gọi là transition. Tập hợp các địa điểm và chuyển đổi để tạo quy trình làm việc được gọi làWorkflow definition.
Hãy để chúng tôi hiểu khái niệm về quy trình làm việc bằng cách tạo một ứng dụng đơn giản để quản lý nghỉ việc.
Step 1 - Tạo một ứng dụng mới, workflow-example.
cd /path/to/dev
mkdir workflow-example
cd workflow-example
composer require symfony/workflow
Step 2 - Tạo một lớp học mới, Leave đang có applied_by, leave_on và status thuộc tính.
class Leave {
public $applied_by;
public $leave_on;
public $status;
}
Ở đây, application_by đề cập đến những nhân viên muốn nghỉ việc. left_on đề cập đến ngày nghỉ phép. trạng thái đề cập đến trạng thái nghỉ việc.
Step 3 - Quản lý nghỉ việc có bốn vị trí, áp dụng, trong_quá trình và được chấp thuận / từ chối.
use Symfony\Component\Workflow\DefinitionBuilder;
use Symfony\Component\Workflow\Transition;
use Symfony\Component\Workflow\Workflow;
use Symfony\Component\Workflow\MarkingStore\SingleStateMarkingStore;
use Symfony\Component\Workflow\Registry;
use Symfony\Component\Workflow\Dumper\GraphvizDumper;
$builder = new DefinitionBuilder();
$builder->addPlaces(['applied', 'in_process', 'approved', 'rejected']);
Ở đây, chúng tôi đã tạo một định nghĩa mới bằng cách sử dụng DefinitionBuilder và thêm các địa điểm bằng cách sử dụng addPlaces phương pháp.
Step 4 - Xác định các hành động cần thiết để di chuyển từ nơi này đến nơi khác.
$builder->addTransition(new Transition('to_process', 'applied', 'in_process'));
$builder->addTransition(new Transition('approve', 'in_process', 'approved'));
$builder->addTransition(new Transition('reject', 'in_process', 'rejected'));
Ở đây, chúng ta có ba quá trình chuyển đổi, to_process, approve và reject. chuyển tiếp to_process chấp nhận đơn xin nghỉ việc và chuyển địa điểm từ áp dụng sang in_process. chấp thuận chuyển đổi duyệt đơn xin nghỉ và chuyển địa điểm đã duyệt. Tương tự, chuyển tiếp từ chối từ chối đơn xin nghỉ và chuyển nơi bị từ chối. Chúng tôi đã tạo tất cả các chuyển đổi bằng phương thức addTransition.
Step 5 - Xây dựng định nghĩa bằng phương pháp xây dựng.
$definition = $builder->build();
Step 6 - Tùy chọn, định nghĩa có thể được kết xuất dưới dạng định dạng chấm graphviz, có thể được chuyển đổi thành tệp hình ảnh cho mục đích tham khảo.
$dumper = new GraphvizDumper();
echo $dumper->dump($definition);
Step 7 - Tạo một kho lưu trữ đánh dấu, được sử dụng để lưu trữ các vị trí / trạng thái hiện tại của đối tượng.
$marking = new SingleStateMarkingStore('status');
Ở đây, chúng tôi đã sử dụng SingleStateMarkingStorelớp để tạo dấu và nó đánh dấu trạng thái hiện tại thành thuộc tính trạng thái của đối tượng. Trong ví dụ của chúng tôi, đối tượng là đối tượng Rời khỏi.
Step 8 - Tạo quy trình làm việc bằng cách sử dụng định nghĩa và đánh dấu.
$leaveWorkflow = new Workflow($definition, $marking);
Ở đây, chúng tôi đã sử dụng Workflow lớp để tạo quy trình làm việc.
Step 9 - Thêm dòng công việc vào sổ đăng ký của khung dòng công việc bằng cách sử dụng Registry lớp học.
$registry = new Registry();
$registry->add($leaveWorkflow, Leave::class);
Step 10 - Cuối cùng, sử dụng quy trình làm việc để tìm xem liệu một chuyển đổi nhất định có được áp dụng bằng cách sử dụng can và nếu vậy, applyquá trình chuyển đổi sử dụng phương pháp áp dụng. Khi một quá trình chuyển đổi được áp dụng, trạng thái của đối tượng sẽ di chuyển từ nơi này sang nơi khác.
$workflow = $registry->get($leave);
echo "Can we approve the leave now? " . $workflow->can($leave, 'approve') . "\r\n";
echo "Can we approve the start process now? " . $workflow->can($leave, 'to_process') . "\r\n";
$workflow->apply($leave, 'to_process');
echo "Can we approve the leave now? " . $workflow->can($leave, 'approve') . "\r\n";
echo $leave->status . "\r\n";
$workflow->apply($leave, 'approve');
echo $leave->status . "\r\n";
Mã hóa hoàn chỉnh như sau:
<?php
require __DIR__ . '/vendor/autoload.php';
use Symfony\Component\Workflow\DefinitionBuilder;
use Symfony\Component\Workflow\Transition;
use Symfony\Component\Workflow\Workflow;
use Symfony\Component\Workflow\MarkingStore\SingleStateMarkingStore;
use Symfony\Component\Workflow\Registry;
use Symfony\Component\Workflow\Dumper\GraphvizDumper;
class Leave {
public $applied_by;
public $leave_on;
public $status;
}
$builder = new DefinitionBuilder();
$builder->addPlaces(['applied', 'in_process', 'approved', 'rejected']);
$builder->addTransition(new Transition('to_process', 'applied', 'in_process'));
$builder->addTransition(new Transition('approve', 'in_process', 'approved'));
$builder->addTransition(new Transition('reject', 'in_process', 'rejected'));
$definition = $builder->build();
// $dumper = new GraphvizDumper();
// echo $dumper->dump($definition);
$marking = new SingleStateMarkingStore('status');
$leaveWorkflow = new Workflow($definition, $marking);
$registry = new Registry();
$registry->add($leaveWorkflow, Leave::class);
$leave = new Leave();
$leave->applied_by = "Jon";
$leave->leave_on = "1998-12-12";
$leave->status = 'applied';
$workflow = $registry->get($leave);
echo "Can we approve the leave now? " . $workflow->can($leave, 'approve') . "\r\n";
echo "Can we approve the start process now? " . $workflow->can($leave, 'to_process') . "\r\n";
$workflow->apply($leave, 'to_process');
echo "Can we approve the leave now? " . $workflow->can($leave, 'approve') . "\r\n";
echo $leave->status . "\r\n";
$workflow->apply($leave, 'approve');
echo $leave->status . "\r\n";
?>
Kết quả
Can we approve the leave now?
Can we approve the start process now? 1
Can we approve the leave now? 1
in_process
approved