netliva / symfony-fast-search-table
Symfony Fast Search Table Library
Requires
- php: >=8.1
- ext-intl: *
- symfony/framework-bundle: >=5.0
README
Symfony için cache yapılı filtrelemeli tablo listeleme yapısı.
Bu sistem listelemeyi direk veri tabanından topluca veri çekerek yapmak yerine, daha hızlı listeleme yapmak için; verileri cache dosyasında tutup, sayfa içi soruglar ile listelemeyi en hızlı şekilde yapabilmeyi amaçlamaktadır.
Kurulum
composer require netliva/symfony-fast-search-table
Bundle'ı aktifleştir
Ardından, projenizin "app/AppKernel.php" dosyasında paketi kayıtlı paketler listesine ekleyerek etkinleştirin:
<?php // app/AppKernel.php // ... class AppKernel extends Kernel { public function registerBundles() { $bundles = array( // ... new Netliva\SymfonyFastSearchBundle\NetlivaSymfonyFastSearchBundle(), ); // ... } // ... }
Sayfa Yolu Tanımlanması
Sayfada tablo verilerinin yüklenebilmesi için aşağıdaki yol tanımlamasının yapılması gerekmektedir.
NetlivaFastTableBundle: resource: "@NetlivaSymfonyFastSearchBundle/Controller/" type: annotation prefix: /fasttable
- prefix: Ön ek için dilediğiniz bir yol değeri girebilirsiniz.
Ayarlar Yapılandırması
Oluşturacağınız tabloların nasıl ve ne şekilde oluşturulacağının bilgisini yapılandırın.
# Symfony >= 4.0. Create a dedicated netliva_config.yaml in config/packages with: # Symfony >= 3.3. Add in your app/config/config.yml: # Netliva Fast Search netliva_symfony_fast_search: cache_path: %kernel.cache_dir%/../shared/fastsearch default_limit_per_page: 15 default_input_class: 'form-control' entities: ~
- cache_path: Ön bellek dosyalarınızın nerede oluşturulacağını tanımlamanızı sağlar.
- default_limit_per_page: Tabloda her seferinde kaç kaydın listeleneceğinin belirlenmesi
- default_input_class: Arama form elemanlarının varsayılan css classlarının tanımlanması
- entities: Önbelleğe alınacak, tabloların yapılandırılması
Bağımlılıklar
Hızlı tablolamanın çalışabilmesi için bazı js bağımlılıklarına sahiptir. Vue ve Axios sisteminizde dahil değilse ilgili linklerini sitenizin temasına ilave edin;
<script src="https://unpkg.com/vue@3"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
Kullanım
User adında bir entitimiz olduğunu kabul edelim. Ve bu tablomuzda, ad (name), soyad (surname), doğum tarihi (birthday) ve oluşturma tarihi (createAt) verisi tuttuğumuzu varsayıyoruz. Bu tablodaki verilere göre aşağıdaki konfigrasyonu yapabiliriz.
Konfigrasyon
Öncelikle önbelleğe alınacak verileri konfirasyon dosyasında tanımlamalıyız. Tanılama entities belirteci altında yapılır. Her bir tablonuz bunun altında tanımlanır. Key değeri olarak istediğiniz değeri verebilirsiniz. Bu değeri listelemeyi oluştururken kullanacağız.
netliva_symfony_fast_search: # ... entities: user_table: class: App\DefaultBundle\Entity\Users # Haangi entitiy için veriler önbelleğe alınacak limit_per_page: 15 # Her seferinde yüklenecek veri, tanılanmazsa default_input_class geçerli olur. default_sort_field: createAt # varsayılan sıralama hangi field için yapılacak default_sorting_direction: desc # varsayılşan sıralama yönü where: # Önbelleğe alınacak ve listelenecek verileri kısıtlamak için. Bu kısıtlamalar sonrası kısıtlanan veriler hiç önbelleğe alınmaz. - { field: createAt, expr: gte, value: -2 years, valueType: date } # son 2 yıla ait verileri önbelleğe alır fields: # ön belleğe alınacak verilerin listesi # entitiy'deki field isimleri key olarak eklenerek liste oluşturulur. catId: { title: 'Kategori Idsi', field: 'category.id' } # ilişkili entity'de id field'ını cache'e dahil ediyoruz name: { title: 'Adı' } surname: { title: 'Soyadı' } birthday: { title: 'Doğum Tarihi' } # tüm tarihler ISO 8601 tarih formati ile önbelleğe kaydedilir (2004-02-12T15:19:21+00:00 gibi) createAt: { title: 'Oluşturma Tarihi' } age: { title: 'Yaşı' } # entitiy'de olmayan veriyi ön belleğe kaydetmek için maniplasyon kullnacağız. # ... filters: # Listeleme tablosu üzerindeki filtreleme alanının oluşturulması category: { type: 'hidden', fields: [catId], exp: eq, decrease_from_total_count: true } # kategory id'sine göre filtreleme yapıyoruz, filtrelenen öğeler toplam sayıdan düşülecek. search_box: { type: 'text', title: 'Ara', fields: [name, surname] } create_range: { type: 'date_range', title: 'Oluşturma', fields: [createAt] } cache_clear: # ilişkili başka entitiy üzerinden bir veri bu tablo için cachlenmiş ise, o entitiyde değişiklik yapıldığında bağlı bu tablodaki veririnin cache'inin temizlenmesi için yapılan tanımlama Crm\DefaultBundle\Entity\OtherEntity: { reverse_fields: [ user ] } # reverse_fields ile diğer tablodan user tablosuna hangi field tanımıyla ulaşıldığı bilgisi tanımlanır. Böylece diğer tablodaki bir veri değiştirildiğinde, bağlantılı user tablolarının cache'i de düzenlenir Crm\DefaultBundle\Entity\AnotherEntity: { clear_all: true } # clear_all true olursa; AnotherEntity'de değişiklik yapıldığında user_table için tüm cachelenen veri silinir. other_table: # listelenencek diğer tablolar için tanılama yapılmaya devam edilir. # ...
Listeleme
{% import _self as funcs %} {% set tableColumns = [ {'title': 'Adı', 'releated_field': 'name'}, {'title': 'Soyadı', 'releated_field': 'surname'}, {'title': 'Yaşı', 'releated_field': 'age'}, {'title': 'Oluşturma', 'releated_field': 'createAt'}, {'title': 'İşlemler'}, ] %} <div id="bina_bilgileri_table"> {{ get_fast_search_table('all_bids', { 'table_class' : 'table table-striped table-hover table-bordered font-size-12', 'record_variable_name' : 'user_data', 'table_tbody_cells_vue_template' : funcs.tBodyCells(), 'table_columns' : tableColumns, 'vue_variables' : { vueVarName: twigVarName, }, 'filter_values' : { category: category.id, } }) }} </div> {% macro tBodyCells() %} <td>[[ user_data.name ]]</td> <td>[[ user_data.surname ]]</td> <td>[[ user_data.age ]] Yaşında</td> <td>[[ user_data.createAtText ]]</td> <td> <a class="btn btn-xs btn-info" target="_blank" :href="'{{ path('users_show', { 'id': '__ID__' }) }}'.replace('__ID__', user_data.id)" > Görüntüle </a> </td> {% endmacro %}
table_tbody_cells_vue_template : değişkeni içinde bir vue template göndermek gerekiyor. Bunun için twig makro kullanıyoruz. twig parentezlerinin {{ }} vue parantezleri ile karışmaması için; vue parantezlerini [[ ]] şeklinde köşeli parantez olarak kullanmamız gerekiyor.
filter_values : oluşturulan filtrelemelerin varsayılan değeri buradanbelirlenir. Hidden filtrelemelrin değerleri de burdan gönderilir..
record_variable_name : her bir listelenecek kaydın vue template içinde hangi değişken tanımıyla alacağınızı tanımlayacağınız bölüm.
vue_variables : ile vue template içinde kullanmak isteyeceğiniz twig değişkenlerini gönderebilirsiniz.
js_variables : ile vue template içinde kullanmak isteyeceğiniz javascript değişkenlerini gönderebilirsiniz.
js_methods : ile vue template içinde kullanmak isteyeceğiniz javascript fonksiyonlarını gönderebilirsiniz.
//...
'js_methods' : {
moment: '(date) => window.moment(date)',
}
//...
components ile vue template içinde import etmek isteyeceğiniz componentleri gönderebilirsiniz.
//...
'js_methods' : {
'ComponentAdi': asset('vue_components/component_dosyasi.js'),
}
//...
Veri Manipülasyonu
Veriyi cache'e kadetmeden önce ve listeleme işleminden hemen önce kullanabileceğiniz iki tane event listener mevcut; Bu listenerları aşağıdaki örnekteki gibi tanımlayabilirsin;
services: #... user_fasttable_subscriber: class: App\DefaultBundle\EventListener\FastTableSubscriber tags: - { name: kernel.event_subscriber }
<?php namespace App\DefaultBundle\EventListener\FastTableSubscriber; use App\DefaultBundle\Entity\Users; use Netliva\SymfonyFastSearchBundle\Events\BeforeViewEvent; use Netliva\SymfonyFastSearchBundle\Events\NetlivaFastSearchEvents; use Netliva\SymfonyFastSearchBundle\Events\PrepareRecordEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class FastTableSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents () { return [ NetlivaFastSearchEvents::PREPARE_RECORD => 'prepareRecord', NetlivaFastSearchEvents::BEFORE_VIEW => 'beforeView', ]; } public function prepareRecord (PrepareRecordEvent $event) { $entity = $event->getEntity(); // kaydedilecek ilgili entity $fKey = $event->getFKey(); // kaydedilecek field ley $entityKey = $event->getEntityKey(); // kayıt yapılacak tablo tanımı $value = $event->getValue(); // kaydedilecek veri switch ($entityKey) { case 'user_table': // hangi tablo tanımlaması için işlem yapılacağının seçilmesi if ($entity instanceof Users) // gelen verinin bu tabloaya ait entitiy'e mi ait olduğunun kontrolü { switch ($fKey) { case 'age' : $value = $entity->getBirthday() ? $entity->getBirthday()->diff(new DateTime())->y : '---'; break; } } break; } // değiştirilen veriyi kaydediyoruz $event->setValue($value); } public function beforeView (BeforeViewEvent $event) { // gerektiğinde filtre verileri gibi post edilen verileri alabilirsiniz $postedData = $event->getRequests(); // listelenecek verileri döndürüyoruz foreach ($event->getRecords() as $key => $record) { switch ($event->getEntityKey()) { // düzenleme yapacağımız tabloyu belirliyoruz case 'user_table': // gelen oluşturma tarihi verisini, okunabilir tarih formatına çevirerek yeni bir değişken ile vue template'e gönderiyoruz $record['createAtText'] = $record['createAt']?(new \DateTime($record['createAt']))->format('d.m.Y H:i'):null; $event->updateRecord($key, $record); break; } } } }