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