Symfony - Gelişmiş Kavramlar
Bu bölümde, Symfony çerçevesindeki bazı gelişmiş kavramları öğreneceğiz.
HTTP Önbelleği
Bir web uygulamasında önbelleğe almak performansı artırır. Örneğin bir alışveriş sepeti web uygulamasındaki sıcak ürünler sınırlı bir süre için önbelleğe alınabilir, böylece veritabanına girmeden müşteriye hızlı bir şekilde sunulabilir. Önbelleğin bazı temel bileşenleri aşağıdadır.
Önbellek Öğesi
Önbellek Öğesi, anahtar / değer çifti olarak saklanan tek bir bilgi birimidir. key ip olmalı ve valueherhangi bir PHP nesnesi olabilir. PHP nesneleri serileştirme yoluyla dizge olarak saklanır ve öğeleri okurken nesnelere geri dönüştürülür.
Önbellek Adaptörü
Önbellek Adaptörü, öğeyi bir mağazada depolamak için gerçek mekanizmadır. Depo bir bellek, dosya sistemi, veritabanı, redis vb. Olabilir. Önbellek bileşeni,AdapterInterfacebir bağdaştırıcının önbellek öğesini arka uç deposunda saklayabileceği. Çok sayıda yerleşik önbellek bağdaştırıcısı mevcuttur. Bunlardan birkaçı aşağıdaki gibidir -
Dizi Önbellek adaptörü - Önbellek öğeleri PHP dizisinde saklanır.
Dosya Sistemi Önbellek adaptörü - Önbellek öğeleri dosyalarda saklanır.
PHP Dosyaları Önbellek Adaptörü - Önbellek öğeleri php dosyaları olarak saklanır.
APCu Önbellek Adaptörü - Önbellek öğeleri, PHP APCu genişletme kullanılarak paylaşılan bellekte saklanır.
Redis Önbellek Adaptörü - Önbellek öğeleri Redis sunucusunda saklanır.
PDO ve Doctrine DBAL Önbellek Adaptörü - Önbellek öğeleri veritabanında saklanır.
Zincir Önbellek Adaptörü - Çoğaltma amacıyla birden çok önbellek bağdaştırıcısını birleştirir.
Proxy Önbellek Adaptörü - Önbellek öğeleri, CacheItemPoolInterface'i uygulayan üçüncü taraf adaptör kullanılarak saklanır.
Önbellek Havuzu
Önbellek Havuzu, önbellek öğelerinin mantıksal bir deposudur. Önbellek havuzları, önbellek bağdaştırıcıları tarafından uygulanır.
Basit Uygulama
Önbellek kavramını anlamak için basit bir uygulama oluşturalım.
Step 1 - Yeni bir uygulama oluşturun, cache-example.
cd /path/to/app
mkdir cache-example
cd cache-example
Step 2 - Önbellek bileşenini yükleyin.
composer require symfony/cache
Step 3 - Bir dosya sistemi adaptörü oluşturun.
require __DIR__ . '/vendor/autoload.php';
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
$cache = new FilesystemAdapter();
Step 4 - kullanarak bir önbellek öğesi oluşturun getItem ve setadaptör yöntemi. getItem, anahtarını kullanarak önbellek öğesini getirir. anahtar kalıcı değilse, yeni bir öğe oluşturur. set yöntemi, gerçek verileri depolar.
$usercache = $cache->getitem('item.users');
$usercache->set(['jon', 'peter']);
$cache->save($usercache);
Step 5 - Önbellek öğesine şunu kullanarak erişin getItem, isHit ve getyöntem. isHit, önbellek öğesinin kullanılabilirliğini bildirir ve alma yöntemi gerçek verileri sağlar.
$userCache = $cache->getItem('item.users');
if(!$userCache->isHit()) {
echo "item.users is not available";
} else {
$users = $userCache->get();
var_dump($users);
}
Step 6 - Önbellek öğesini kullanarak silin deleteItem yöntem.
$cache->deleteItem('item.users');
Tam kod listesi aşağıdaki gibidir.
<?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');
?>
Sonuç
array(2) {
[0]=>
string(3) "jon"
[1]=>
string(5) "peter"
}
Hata ayıklama
Hata ayıklama, bir uygulama geliştirirken en sık yapılan faaliyetlerden biridir. Symfony, hata ayıklama sürecini kolaylaştırmak için ayrı bir bileşen sağlar. Symfony hata ayıklama araçlarını yalnızcaenable Debug sınıfının yöntemi.
use Symfony\Component\Debug\Debug
Debug::enable()
Symfony iki sınıf sağlar, ErrorHandler ve ExceptionHandlerhata ayıklama amacıyla. ErrorHandler, PHP hatalarını yakalayıp bunları istisnalara, ErrorException veya FatalErrorException'a dönüştürürken, ExceptionHandler yakalanmamış PHP istisnalarını yakalar ve bunları yararlı PHP yanıtına dönüştürür. ErrorHandler ve ExceptionHandler varsayılan olarak devre dışıdır. Register yöntemini kullanarak etkinleştirebiliriz.
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\ExceptionHandler;
ErrorHandler::register();
ExceptionHandler::register();
Bir Symfony web uygulamasında, debug environmentDebugBundle tarafından sağlanır. Paketi AppKernel'da kaydedinregisterBundles etkinleştirmek için yöntem.
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
$bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle();
}
Profil oluşturucu
Bir uygulamanın geliştirilmesi, birinci sınıf bir profil oluşturma aracına ihtiyaç duyar. Profil oluşturma aracı, bir uygulama hakkındaki yürütme süresi, tek tek modüllerin yürütme süresi, bir veritabanı etkinliği tarafından harcanan süre, bellek kullanımı vb. Gibi tüm çalışma zamanı bilgilerini toplar. Bir web uygulaması, istek zamanı gibi çok daha fazla bilgiye ihtiyaç duyar, Yukarıdaki ölçümlere ek olarak bir yanıt oluşturmak için geçen süre vb.
Symfony, bir web uygulamasında bu tür tüm bilgileri varsayılan olarak etkinleştirir. Symfony, web profili oluşturma için ayrı bir paket sağlar:WebProfilerBundle. Web profil oluşturucu paketi, paketi AppKernel'in registerBundles yöntemine kaydederek bir web uygulamasında etkinleştirilebilir.
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
}
Web profili bileşeni altında yapılandırılabilir web_profile section uygulama yapılandırma dosyasının app/config/config.xml
web_profiler:
toolbar: false
position: bottom
Symfony uygulaması, profilli verileri sayfanın altında ayrı bir bölüm olarak gösterir.
Symfony ayrıca profil verilerinde sayfa hakkında özel ayrıntılar eklemek için kolay bir yol sağlar. DataCollectorInterface interfaceve dal şablonu. Kısacası, Symfony, bir web geliştiricisinin, göreli kolaylıkla harika bir profil oluşturma çerçevesi sağlayarak birinci sınıf bir uygulama oluşturmasını sağlar.
Güvenlik
Daha önce tartışıldığı gibi Symfony, güvenlik bileşeni aracılığıyla sağlam bir güvenlik çerçevesi sağlar. Güvenlik bileşeni aşağıdaki gibi dört alt bileşene ayrılmıştır.
- symfony / security-core - Temel güvenlik işlevi.
- symfony / security-http - HTTP protokolünde entegre güvenlik özelliği.
- symfony / security-csrf - Bir web uygulamasında siteler arası istek sahteciliğine karşı koruma.
- symfony / security-acl - Gelişmiş erişim kontrol listesi tabanlı güvenlik çerçevesi.
Basit Kimlik Doğrulama ve Yetkilendirme
Basit bir demo uygulaması kullanarak kimlik doğrulama ve yetkilendirme kavramını öğrenelim.
Step 1 - Yeni bir web uygulaması oluşturun securitydemo aşağıdaki komutu kullanarak.
symfony new securitydemo
Step 2- Güvenlik yapılandırma dosyasını kullanarak uygulamadaki güvenlik özelliğini etkinleştirin. Güvenlikle ilgili konfigürasyon ayrı bir dosyaya yerleştirilir,security.yml. Varsayılan konfigürasyon aşağıdaki gibidir.
security:
providers:
in_memory:
memory: ~
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
#http_basic: ~
#form_login: ~
Varsayılan yapılandırma, bellek tabanlı güvenlik sağlayıcısını ve tüm sayfalara anonim erişimi etkinleştirir. Güvenlik duvarı bölümü, modelle eşleşen dosyaları hariç tutar,^/(_(profiler|wdt)|css|images|js)/güvenlik çerçevesinden. Varsayılan kalıp, stil sayfalarını, görüntüleri ve JavaScript'leri (artı profil oluşturucu gibi geliştirme araçlarını) içerir.
Step 3 - Ana bölüme http_basic seçeneğini aşağıdaki gibi ekleyerek HTTP tabanlı güvenlik kimlik doğrulama sistemini etkinleştirin.
security:
# ...
firewalls:
# ...
main:
anonymous: ~
http_basic: ~
#form_login: ~
Step 4- Bellek sağlayıcı bölümüne bazı kullanıcılar ekleyin. Ayrıca kullanıcılar için roller ekleyin.
security:
providers:
in_memory:
memory:
users:
myuser:
password: user
roles: 'ROLE_USER'
myadmin:
password: admin
roles: 'ROLE_ADMIN'
ROLE_USER rolünde kullanıcı ve ROLE_ADMIN rolünde yönetici olmak üzere iki kullanıcı ekledik .
Step 5- Geçerli oturum açmış kullanıcının tüm ayrıntılarını almak için kodlayıcıyı ekleyin. Kodlayıcının amacı, web talebinden mevcut kullanıcı nesnesinin tüm ayrıntılarını almaktır.
security:
# ...
encoders:
Symfony\Component\Security\Core\User\User: bcrypt
# ...
Symfony bir arayüz sağlar, UserInterface kullanıcı adı, roller, parola vb. gibi kullanıcı ayrıntılarını almak için arayüzü gereksinimimize uygulamalı ve kodlayıcı bölümünde yapılandırmalıyız.
Örneğin kullanıcı detaylarının veri tabanında olduğunu düşünelim. Ardından, veritabanından kullanıcı bilgilerini almak için yeni bir User sınıfı oluşturmalı ve UserInterface yöntemlerini uygulamalıyız. Veriler mevcut olduğunda, güvenlik sistemi bunu kullanıcıya izin vermek / reddetmek için kullanır. Symfony, Bellek sağlayıcı için varsayılan bir Kullanıcı uygulaması sağlar. Algoritma, kullanıcı şifresinin şifresini çözmek için kullanılır.
Step 6 - Kullanıcı şifresini kullanarak şifreleyin bcryptalgoritması ve yapılandırma dosyasına yerleştirin. Kullandığımızdan beribcryptAlgoritması, Kullanıcı nesnesi yapılandırma dosyasında belirtilen şifrenin şifresini çözmeye çalışır ve ardından kullanıcı tarafından girilen şifre ile eşleşmeye çalışır. Symfony konsol uygulaması, parolayı şifrelemek için basit bir komut sağlar.
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 - Şifrelenmiş parolayı oluşturmak ve yapılandırma dosyasında güncellemek için komutu kullanın.
# 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- Şimdi, güvenliği uygulamanın bir bölümüne uygulayın. Örneğin, yönetici bölümünü ROLE_ADMIN rolündeki kullanıcılarla kısıtlayın.
security:
# ...
firewalls:
# ...
default:
# ...
access_control:
# require ROLE_ADMIN for /admin*
- { path: ^/admin, roles: 'ROLE_ADMIN' }
Step 9 - DefaultController'a aşağıdaki gibi bir yönetici sayfası ekleyin.
/**
* @Route("/admin")
*/
public function adminLandingAction() {
return new Response('<html><body>This is admin section.</body></html>');
}
Step 10- Son olarak, bir tarayıcıda güvenlik yapılandırmasını kontrol etmek için yönetici sayfasına erişin. Tarayıcı, kullanıcı adı ve parolayı soracak ve yalnızca yapılandırılmış kullanıcılara izin verecektir.
Sonuç
İş akışı
İş akışı, birçok kurumsal uygulamada kullanıma sahip gelişmiş bir kavramdır. Bir e-ticaret uygulamasında, ürün teslim süreci bir iş akışıdır. Ürün ilk olarak faturalandırılır (sipariş oluşturma), mağazadan temin edilir ve paketlenir (paketleme / gönderime hazır) ve kullanıcıya gönderilir. Herhangi bir sorun varsa ürün kullanıcıdan iade edilir ve sipariş geri alınır. Eylem akışının sırası çok önemlidir. Örneğin, faturalandırmadan bir ürünü teslim edemeyiz.
Symfony bileşeni, bir iş akışını tanımlamak ve yönetmek için nesneye yönelik bir yol sağlar. Bir süreçteki her adım denirplace ve bir yerden başka bir yere gitmek için gereken eyleme transition. Bir iş akışı oluşturmak için yerlerin koleksiyonuna ve geçişeWorkflow definition.
İzin yönetimi için basit bir uygulama oluşturarak iş akışı kavramını anlayalım.
Step 1 - Yeni bir uygulama oluşturun, workflow-example.
cd /path/to/dev
mkdir workflow-example
cd workflow-example
composer require symfony/workflow
Step 2 - Yeni bir sınıf oluşturun, Leave sahip olmak applied_by, leave_on ve status Öznitellikler.
class Leave {
public $applied_by;
public $leave_on;
public $status;
}
Burada uygulandı_by, ayrılmak isteyen çalışanları ifade eder. allow_on, ayrılma tarihini ifade eder. durum, izin durumunu ifade eder.
Step 3 - İzin yönetiminin dört yeri vardır, uygulandı, işlemde ve onaylandı / reddedildi.
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']);
Burada, kullanarak yeni bir tanım oluşturduk DefinitionBuilder ve kullanarak yerler eklendi addPlaces yöntem.
Step 4 - Bir yerden başka bir yere gitmek için gereken eylemleri tanımlayın.
$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'));
Burada üç geçişimiz var, to_process, approve ve reject. to_process geçişi, bırakma uygulamasını kabul eder ve yeri uygulanan durumdan in_process'e taşır. geçişi onayla, izin başvurusunu onaylar ve yeri onaylanan konuma taşır. Benzer şekilde, reddetme geçişi, izin uygulamasını reddeder ve yeri reddedilene taşır. Tüm geçişleri addTransition yöntemini kullanarak oluşturduk.
Step 5 - Oluşturma yöntemini kullanarak tanımı oluşturun.
$definition = $builder->build();
Step 6 - İsteğe bağlı olarak, tanım, referans amacıyla görüntü dosyasına dönüştürülebilen graphviz nokta formatı olarak atılabilir.
$dumper = new GraphvizDumper();
echo $dumper->dump($definition);
Step 7 - Nesnenin mevcut yerlerini / durumunu saklamak için kullanılan bir işaretleme deposu oluşturun.
$marking = new SingleStateMarkingStore('status');
Burada kullandık SingleStateMarkingStoreişareti oluşturmak için sınıf ve nesnenin status özelliğine geçerli durumu işaretler. Örneğimizde nesne, Bırak nesnesidir.
Step 8 - Tanım ve işaretleme kullanarak iş akışını oluşturun.
$leaveWorkflow = new Workflow($definition, $marking);
Burada kullandık Workflow iş akışını oluşturmak için sınıf.
Step 9 - İş akışını kullanarak iş akışı çerçevesinin kayıt defterine ekleyin Registry sınıf.
$registry = new Registry();
$registry->add($leaveWorkflow, Leave::class);
Step 10 - Son olarak, belirli bir geçişin uygulanıp uygulanmadığını bulmak için iş akışını kullanın. can yöntem ve eğer öyleyse, applyuygulama yöntemini kullanarak geçiş. Bir geçiş uygulandığında, nesnenin durumu bir yerden diğerine hareket eder.
$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";
Tam kodlama aşağıdaki gibidir -
<?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";
?>
Sonuç
Can we approve the leave now?
Can we approve the start process now? 1
Can we approve the leave now? 1
in_process
approved