តើអ្នកធ្លាប់បានដឹងទេអំពី OptionsResolver component នៅក្នុង Symfony3 ? ថ្ងៃនេះ Techfree នឹងធ្វើការពន្យល់ណែនាំ អំពី OptionsResolver component នៅក្នុង Symfony3 ។ OptionsResolver component គឺជា array_replace នៅលើ steroids ។ វាអនុញ្ញាតអោយអ្នកអាចបង្កើតនូវ options system ជាមួយនឹង options ដែលត្រូវតែមាន, defaults, validation (ប្រភេទ និង តម្លៃ រឺក៏ type, value), normalization និងមានជាច្រើនទៀត។
១) ការតម្លើង
អ្នកអាចតម្លើង OptionsResolver component បានតាមរយៈវិធី ២ ផ្សេងគ្នា៖
ទី១៖ តម្លើងតាម Composer (symfony/option-resolver នៅលើ Packagist)
ទី២៖ ប្រើប្រាស់ official Git repository (https://github.com/symfony/options-resolver)
បន្ទាប់ពីនោះ គឺទាមទារអោយមាន vendor/autoload.php file ដើម្បីធ្វើការ enable នូវការ load mechanism ដែលបានផ្ដល់ដោយ Composer ដោយស្វ័យប្រវត្តិ។ បើមិនដូច្នោះទេ application របស់អ្នកនឹងមិនអាច ស្វែងរកនូវ classes នៃ Symfony component បាននោះទេ។
២) ការប្រើប្រាស់
សាកស្រម៉ៃថា អ្នកមាន Mailer class ដែលមាន options ចំនួន ៤ ដូចជា host, username, password និង port ៖
នៅពេលដែលកំពុងធ្វើការ access នូវ $options នោះអ្នកត្រូវបន្ថែមនូវកូដ boilerplate ជាច្រើនដើម្បីពិនិត្យថាតើ options ណាមួយត្រូវកំណត់ ៖
Biolerplate គឺពិតជាពិបាកក្នុងការ read និងមានភាពដដែលៗ ។ ដូចគ្នានេះផងដែរ តម្លៃ default នៃ options គឺត្រូវបានកប់ទៅក្នុង business logic នៃកូដរបស់អ្នករួចហើយ។ ដូចនេះ សូមប្រើ array_replace ដើម្បីជួសជុលវា ៖
នាពេលនេះ options ទាំង ៤ គឹត្រូវបានធានាថាត្រូវបានកំណត់ ។ ប៉ុន្តែនឹងមានអ្វីកើតឡើងប្រសិនបើ user នៃ Mailer class បង្កើតនូវ កំហុសឡើង?
មិនមាន error បានបង្ហាញនោះទេ ។ ក្នុងករណីដ៏ល្អបំផុត គឺ bug នឹងលេចឡើងកំឡុងពេលធ្វើការតេស្ត ប៉ុន្តែ developer នឹងមិនចំណាយពេលច្រើនទេក្នុងការស្វែងរកបញ្ហា ។ ក្នុងករណីធ្ងន់ធ្ងរ bug ប្រហែលជានឹងមិនលេចរូបរាងរហូតដល់វាត្រូវបានដាក់ពង្រាយទៅលើ live system ។
សំណាងល្អ OptionsResolver class ជួយអ្នកដើម្បីជួសជុលបញ្ហានេះបាន ៖
ដូចពីពេលមុនដែរ options ទាំងអស់នឹងធានាថានឹងត្រូវបានកំណត់ ។ បន្ថែមពីនេះ UndefinedOptionsException គឺបានបោះ ប្រសិនបើ option ដែលមិនស្គាល់បាន pass ៖
កូដដែលនៅសល់របស់អ្នកអាច access នូវ តម្លៃ នៃ options ដោយមិនគិតពីកូដ boilerplate ៖
វាជាការអនុវត្តដ៏ល្អមួយក្នុងការបំបែក នូវ option configuration ទៅកាន់ method ដាច់ពីគ្នា ៖
ជាដំបូង កូដរបស់អ្នកក្លាយទៅជាកូដដែលងាយស្រួល read ជាពិសេសប្រសិនបើ constructor ធ្វើការច្រើនជាង ធ្វើដំណើរការ options ។ ទីពីរគឺ sub-classes ពេលនេះប្រហែលជា override នូវ configureOptions() method ដើម្បីតម្រូវនូវ configuration នៃ options ៖
៣) Options ដែលត្រូវតែមាន រឺក៏ Required Options
ប្រសិនបើ option ត្រូវតែកំណត់ដោយអ្នកហៅ គឺត្រូវ pass option មួយនោះទៅ setRequired() ។ សម្រាប់ឧទាហរណ៏ គឺ ដើម្បីធ្វើអោយ host option ទាមទារ អ្នកត្រូវធ្វើដូចខាងក្រោម៖
ប្រសិនបើអ្នកលុប option ដែលទាមទារ នោះ MissingOptionException នឹងត្រូវបានបោះ ៖
setRequired() method យល់ព្រមទទួលយកនូវ single name រឺក៏ array នៃ option names ប្រសិនបើអ្នកមាន required option ច្រើនជាងមួយ ៖
ប្រើប្រាស់ isRequired() ដើម្បីស្វែងរកថា ប្រសិនបើ option គឺ required ។ អ្នកអាចប្រើ getRequiredOptions() ដើម្បីទទួលយកនូវឈ្មោះនៃ required options ទាំងអស់ ៖
ប្រសិនបើអ្នកចង់ពិនិត្យមើលថាតើ required option នៅតែមិនមានពី default options នោះអ្នកអាចប្រើ isMissing() ។ ភាពខុសគ្នារវាង isMissing() និង isRequired() គឺថា method នេះនឹង return false ប្រសិនបើ required option បានកំណត់រួចហើយ ៖
Method getMissingOptions() នាំអោយអ្នក access នូវឈ្មោះនៃ option ដែលមិនមានទាំងអស់ ។
៤) ប្រភេទនៃ Validation
អ្នកអាច run បន្ថែមទៀតដើម្បីពិនិត្យទៅលើ options ដើម្បីប្រាកដថា ពួកគេ បាន pass ដោយត្រឹមត្រូវ ។ ដើម្បី validate នូវប្រភេទនៃ options សូមធ្វើការហៅ setAllowedTypes() ៖
សម្រាប់ option នីមួយៗ អ្នកអាចកំណត់បានទាំង ប្រភេទ (type) មួយ រឺក៏ array នៃ types ដែលអាចទទួលយកបាន ។ អ្នកអាច pass នូវ type ផ្សេងទៀតសម្រាប់ is_<type>() function ណាដែលបានកំណត់ក្នុង PHP ។ បន្ថែមពីនេះ អ្នកប្រហែលជាអាច pass នូវ class ដែលមានលក្ខណៈគ្រប់គ្រាន់ រឺក៏ interface names ។
ប្រសិនបើ pass នូវ invalid option នាពេលនេះ នោះ InvalidOptionsException គឺត្រូវបានបោះ ៖
នៅក្នុង sub-classes អ្នកអាចប្រើ addAllowedTypes() ដើម្បីបន្ថែមនូវ types ដែលត្រូវបានអនុញ្ញាតដោយមិនចាំបាច់លុបនូវ អ្វីដែលបានកំណត់រួចហើយ ។
៥) តម្លៃនៃ Validation
Options ខ្លះអាចទទួលយកបានតែមួយនៃ បញ្ជីនៃតម្លៃដែលបានកំណត់ជាមុន ។ ឧទាហរណ៏ ឧបមាថា Mailer class មាន transport option ដែលអាចជាផ្នែកមួយនៃ sendmail, mail និង smtp ។ ប្រើប្រាស់នូវ method setallowedValues() ដើម្បីផ្ទៀងផ្ទាត់ថា option ដែលបាន pass ផ្ទុកនូវអ្វីមួយនៃ តម្លៃទាំងនោះ ៖
ប្រសិនបើអ្នក pass នូវ invalid transport នោះ InvalidOptionsException នឹងត្រូវបានបោះ ៖
សម្រាប់ options ជាមួយនឹង validation schemes ស្មុគស្មាញជាច្រើនទៀត គឺឆ្លងកាត់នូវការបិទដែលជាអ្នក returns true សម្រាប់ តម្លៃដែលអាចទទួលយកបាននិង returns false សម្រាប់តម្លៃដែល Invalid ៖
ក្នុង sub-classes អ្នកអាចប្រើ addAllowedValues() ដើម្បីបន្ថែមនូវ តម្លៃដែលអនុញ្ញាតអោយបន្ថែមដោយមិនបាច់លុបនូវតម្លៃណាមួយដែលបានកំណត់រួច ។
៦) Option Normalization
ពេលខ្លះ តម្លៃនៃ option ចាំបាច់ត្រូវការ normalized មុននឹងអ្នកអាចប្រើវាបាន ។ ឧទាហរណ៏ សន្មតថា host គួរតែតែងតែចាប់ផ្ដើមជាមួយនឹង http:// ។ ដើម្បីធ្វើដូចនេះ អ្នកអាចសរសេរ normalizers ។ Normalizers គឺបាន execute បន្ទាប់ពីធ្វើការ validate នូវ option ។ អ្នកអាច configure normalizer ដោយធ្វើការហៅ setNormalizer() ៖
Normalizer ទទួលនូវ $value ពិតនិង returns នូវ normalized form ។ អ្នកឃើញថា closure តែងតែប្រើ $options parameter ។ នេះជាសារប្រយោជន៏ ប្រសិនបើអ្នកត្រូវការប្រើ options ផ្សេងទៀតកំឡុងពេល normalization ៖
៧) តម្លៃ Default ដែលពឹងផ្អែកទៅលើ Option ដទៃទៀត
ឧបមាថាអ្នកចង់កំណត់នូវ default value នៃ port option ដោយផ្អែកទៅលើ encryption ដែលបានរើសដោយ user នៃ Mailer class ។ កាន់តែច្បាស់ជាងនេះ អ្នកចង់កំណត់ នូវ port ទៅជា 465 ប្រសិនបើ SSL គឺត្រូវបានប្រើហើយបើមិនដូច្នោះទេ គឺទៅជា 25 ។
អ្នកអាច Implement feature មួយនេះដោយធ្វើការ pass closure ជា default value នៃ port option ។ Closure ទទួលយកនូវ options ជា argument ។ ដោយផ្អែកទៅលើ options ទាំងនោះ អ្នកអាច return default value បាន ៖
Default value ដែលបានកំណត់ពីមុនអាចនឹង access បានដោយការបន្ថែម argument ទី២ ទៅកាន់ closure ៖
ដូចដែលបានឃើញក្នុងឧទាហរណ៏ feature មួយនេះគឺ ភាគច្រើនមានប្រយោជន៏ ប្រសិនបើអ្នកត្រូវការ ប្រើម្ដងទៀតនូវ default values កំណត់ក្នុង parent classes គ្នុង sub-classes ។
៨) Options ដែលមិនគិតពី តម្លៃ default
មានករណីខ្លះ វាមានប្រយោជន៏ ក្នុងការកំណត់នូវ option ដោយមិនបាច់ធ្វើការកំណត់នូវ default value ។ វាមានប្រយោជន៏ប្រសិនបើអ្នកត្រូវការដឹងរឺក៏អត់នូវ user ពិតប្រាកដ ជាកំណត់នូវ option រឺក៏អត់ ។ ឧទាហរណ៏ ប្រសិនបើអ្នកកំណត់នូវ default value សម្រាប់ option វាគឺមិនអាចទៅរួចទេ ដើម្បីដឹងថា user បាន pass តម្លៃនេះរឺក៏ប្រសិនបើវា គ្រាន់តែមកពី default ៖
អ្នកអាចប្រើ setDefined() ដើម្បីកំណត់នូវ option ដោយមិនបាច់កំណត់នូវ default value ។ បន្ទាប់មក option ប្រហែលជាអាចត្រឹមតែបញ្ចូលក្នុង resolved options ប្រសិនបើវាពិតជាបាន pass ទៅ resolve() ៖
អ្នកក៏អាច pass នូវ array នៃ option names ប្រសិនបើអ្នកចង់កំណត់នូវ options ច្រើនក្នុងពេលតែមួយ ៖
Methods isDefined() និង getDefinedOptions() នឹងអោយអ្នកស្វែងរកថា options ណាមួយដែលបានកំណត់ ៖
៩) ដំណើរការនៃ Tweaks រឺ ដំណើរការនៃ ល្បឿន
ជាមួយនឹងការអនុវត្តនាពេលបច្ចុប្បន្ននេះ configureOptions() method អាចនឹងបានហៅសម្រាប់ single instance ទាំងអស់នៃ Mailer class ។ ដោយអាស្រ័យទៅលើចំនួនសរុបនៃ option configuration និង ចំនួននៃការដែលបានបង្កើត Instances នេះប្រហែលជាបន្ថែមនូវការចំណាយដែលគួរអោយកត់សម្គាល់ទៅលើ application របស់អ្នក។ ប្រសិនបើការចំណាយនោះក្លាយទៅជាបញ្ហា អ្នកអាចប្ដូរកូដរបស់អ្នកទៅធ្វើតែ configuration ម្ដងក្នុង class មួយ ៖
ពេលនេះ OptionsResolver instance អាចនឹងបានបង្កើតម្ដងសម្រាប់ class នីមួយៗ និង ប្រើម្ដងទៀតពីពេលនេះទៅ។ ត្រូវចាំថា របៀបនេះអាចនឹងនាំអោយ memory លេចចេញទៅក្នុងការ run រយៈពេលយូរនៃ application របស់អ្នក ប្រសិនបើ default options ផ្ទុកនូវ references ទៅកាន់ objects រឺក៏ object graphs ។ ប្រសិនបើករណីនេះកើតមានសម្រាប់អ្នក សូមអនុវត្តនូវ method clearOptionsConfig() និងហៅវាអោយបានទៀងទាត់ ៖