Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CakePHP3 Modelless Form

CakePHP3 Modelless Form

CakePHP3 Modelless Form について、Fukuoka.php vol.17で発表した内容です。

B63ed943582d5b36a78f3be3c4d659e2?s=128

Takashi Nojima

June 22, 2016
Tweet

Transcript

  1. CakePHP 3 Modelless Form +VO 'VLVPLBQIQWPM

  2. About Me ໊લɿ໺ౡོʢͷ͡·͔ͨ͠ʣ ॴଐɿΠϥεςΟοΫίϯαϧλϯπגࣜձࣾ
 w CMPHIUUQQIQUJQTDPN w 5XJUUFS!OPKJNBHF

  3. CakePHPެࣜͷSlackʹ
 ೔ຊޠνϟϯωϧͰ͖·ͨ͠ ! w IUUQDBLFTGIFSPLVBQQDPN͔Βొ࿥ w νϟϯωϧʮKBQBOFTFʯͰ͓଴͍ͪͯ͠·͢ ! w ৄ͍͠ࢀՃͷ࢓ํͳͲ͸ʮ$BLF1)1ެࣜ4MBDL೔ຊޠʯͰάά͍ͬͯͩ͘͞

  4. ࿩͢͜ͱ w .PEFMMFTT'PSNͷػೳ w ར༻έʔε

  5. Modelless Form ͱ͸

  6. Modelless Form 'PSN)FMQFSʁ Ͱ͸ͳͯ͘ ίϯτϩʔϥ͔Βݺͼग़ͯ͠࢖͏΋ͷ

  7. Cake\Form\Form wεΩʔϚఆٛ wೖྗݕࠪʢόϦσʔγϣϯʣ wॲཧ࣮ߦ

  8. Cake\Form\Form w@CVJME4DIFNB  w@CVJME7BMJEBUPS  w@FYFDVUF

  9. ྫ: ͓໰͍߹ΘͤϑΥʔϜ namespace App\Form; ! use Cake\Form\Form; use Cake\Form\Schema; use

    Cake\Validation\Validator; ! class ContactForm extends Form { ! protected function _buildSchema(Schema $schema) { return $schema->addField('name', 'string') ->addField('email', ['type' => 'string']) ->addField('body', ['type' => 'text']); } ! protected function _buildValidator(Validator $validator) { return $validator->add('name', 'length', [ 'rule' => ['minLength', 10], 'message' => '໊લ͸ඞਢͰ͢' ])->add('email', 'format', [ 'rule' => 'email', 'message' => '༗ޮͳϝʔϧΞυϨε͕ཁٻ͞Ε·͢', ]); } ! protected function _execute(array $data) { // ϝʔϧΛૹ৴͢Δ return true; } } ^@CVJME4DIFNB ^@CVJME7BMJEBUPS ^@FYFDVUF ˞$BLFa'PSNa'PSNΛܧঝ http://book.cakephp.org/3.0/en/core-libraries/form.html
  10. ྫ: ͓໰͍߹ΘͤϑΥʔϜ class ContactController extends AppController { public function index()

    { $contact = new ContactForm(); ! if ($this->request->is('post')) { if ($contact->execute($this->request->data)) { $this->Flash->success('͙͢ʹ͝࿈བྷ͍ͨ͠·͢ɻ'); } else { $this->Flash->error('ϑΥʔϜૹ৴ʹ໰୊͕͋Γ·ͨ͠ɻ'); } } ! $this->set('contact', $contact); } } http://book.cakephp.org/3.0/en/core-libraries/form.html
  11. ྫ: ͓໰͍߹ΘͤϑΥʔϜ <?php ! // Template ! echo $this->Form->create($contact); echo

    $this->Form->input('name'); echo $this->Form->input('email'); echo $this->Form->input('body'); echo $this->Form->button('Submit'); echo $this->Form->end(); http://book.cakephp.org/3.0/en/core-libraries/form.html
  12. ࢖͍ํ w $BLFa'PSNa'PSNΛܧঝͨ͠ΫϥεΛ࣮૷ w $POUSPMMFSଆͰ࣮૷ͨ͠ΫϥεΛOFX w ϦΫΤετσʔλΛϑΥʔϜͷFYFDVUF ʹ ౉ͯ͠ॲཧ࣮ߦ

  13. ࢖͍ํ w ςϯϓϨʔτଆͰΤϯςΟςΟͷ୅ΘΓʹ 'PSN)FMQFSDSFBUF΁౉͢ ‣ ೖྗΤϥʔ͕͋Ε͹ΤϥʔදࣔΛߦͬͯ͘ΕΔ

  14. Fat Controller! Fat Model

  15. Fat Controller ϏδωεϩδοΫΛͲ͜ʹॻ͔͘໰୊ $POUSPMMFS  $PNQPOFOU  .PEFM

  16. Fat Model େྔͷϝιου େྔͷόϦσʔγϣϯ ! ॲཧຖʹϞσϧΛ༻ҙ͢Δʁ

  17. Α͋͘Δ͜ͱ w ෳ਺ͷϞσϧʹରͯ͠ॲཧΛߦ͍͍ͨ w ೖྗ͞ΕΔύϥϝʔλʔ໊ͱϞσϧͷϑΟʔ ϧυ໊͕ҧ͏ʢ"1*ͱ͔ w 4IFMM͔Β΋ಉ͡ૢ࡞Λ͍ͨ͠

  18. શ෦Formʹॻ͚͹͍͍ ೖྗΛ͏͚ͯ ೖྗΛνΣοΫͯ͠ ॲཧͯ͠ ݁ՌΛฦ͢

  19. ࣮૷ྫ

  20. ύεϫʔυมߋϑΥʔϜ w ݱࡏͷύεϫʔυͱ৽͍͠ύεϫʔυɺ৽͍͠ύ εϫʔυͷ֬ೝΛೖྗ w ݱࡏͷύεϫʔυ͕Ұகͯ͠ɺ͔ͭɺ৽͍͠ύε ϫʔυͱ֬ೝೖྗ͕Ұக͢Δ৔߹ʹɺύεϫʔυ Λߋ৽͢Δ w ύεϫʔυ͕ߋ৽͞ΕͨࢫΛϝʔϧૹ৴

  21. change_password.ctp <?= $this->Form->create($form, $formOptions); ?> <?= $this->Form->input('password', [ 'label' =>

    ['text' => __('ݱࡏͷύεϫʔυ')], 'placeholder' => __('ύεϫʔυΛೖྗ'), ]); ?> <?= $this->Form->input('new_password', [ 'type' => 'password', 'label' => ['text' => __('৽͍͠ύεϫʔυ')], 'placeholder' => __('ύεϫʔυΛೖྗ'), ]) ?> <?= $this->Form->input('confirm_password', [ 'type' => 'password', 'label' => ['text' => __('ύεϫʔυʢ֬ೝʣ')], 'placeholder' => __('֬ೝͷͨΊ΋͏Ұ౓ೖྗ'), ]) ?> <?= $this->Form->button(__('อଘ'), ['class' => 'btn btn-primary']) ?> <?= $this->Form->end() ?>
  22. Controller <?php ! namespace App\Controller; ! class ProfileController extends AppController

    { public function change_password() { $form = new \App\Form\Profile\ChangeEmailForm($this->Auth->user('id')); ! if ($this->request->is(['patch', 'post', 'put'])) { // POST/PUT/PATCH if ($form->execute($this->request->data)) { $this->Flash->success(__('ύεϫʔυΛߋ৽͠·ͨ͠ɻ')); $this->redirect(['action' => 'edit']); } else { $this->Flash->error(__('ύεϫʔυͷߋ৽ʹࣦഊ͠·ͨ͠ɻ')); } } else { // GET $this->request->data['id'] = $this->Auth->user('id'); } ! $this->set('form', $form); } }
  23. ChangePasswordForm <?php ! namespace App\Form\Profile; ! use Cake\Form\Form; use Cake\Form\Schema;

    use Cake\Validation\Validator; use Cake\ORM\TableRegistry; ! class ChangePasswordForm extends Form { protected $table; protected $user; ! public function __construct($id) { // ͲͷϢʔβʔʹରͯ͠มߋΛߦ͏ͷ͔ίϯετϥΫλͰઃఆ $this->table = TableRegistry::get('Users'); $this->user = $this->table->get($id); } ! protected function _buildSchema(Schema $schema) { // ϑΟʔϧυఆٛ return $schema ->addField('password', ['type' => 'string']) ->addField('new_password', ['type' => 'string']) ->addField('confirm_password', ['type' => 'string']); } ! protected function _buildValidator(Validator $validator) { // UsersTableʹఆٛͯ͋͠ΔvalidationΛར༻͢Δ // ݱࡏͷύεϫʔυͱҰக͢Δ $this->table->validationRequireCurrentPassword($validator); ! // ৽͍͠ύεϫʔυͱ֬ೝύεϫʔυͷೖྗ͕Ұக͢Δ $validator ->notEmpty('new_password', __('ύεϫʔυ͸ඞͣೖྗ͍ͯͩ͘͠͞ɻ')) ->notEmpty('confirm_password', __('ύεϫʔυ͸ඞͣೖྗ͍ͯͩ͘͠͞ɻ')); $validator->add('new_password', 'minLength', [ 'rule' => ['minLength', 6], 'message' => __('ύεϫʔυ͸6จࣈҎ্Ͱೖྗ͍ͯͩ͘͠͞ɻ'), ]) ->add('new_password', 'maxLength', [ 'rule' => ['maxLength', 255], 'message' => __('ύεϫʔυ͸255จࣈҎ಺Ͱೖྗ͍ͯͩ͘͠͞ɻ'), ]); $validator->add('confirm_password', 'maxLength', [ 'rule' => ['maxLength', 255], 'message' => __('ύεϫʔυ͸255จࣈҎ಺Ͱೖྗ͍ͯͩ͘͠͞ɻ'), ]) ->add('confirm_password', 'compareWith', [ 'rule' => ['compareWith', 'new_password'], 'message' => __('ύεϫʔυ͕Ұக͠·ͤΜɻ'), ]); ! return $validator; } ! protected function _execute(array $data) { // ύεϫʔυߋ৽ $newpassword = ['password' => $data['new_password']]; $this->table->patchEntity($this->user, $newpassword); if (!$this->table->save($this->user)) { return false; } ! // send email $mailer = new Email('default'); $mailer->to($this->user) ->subject(__('ύεϫʔυ͕มߋ͞Ε·ͨ͠')) ->template('change_password') ->viewVars(['user' => $user]) ->send(); ! return true; } ! public function getUser() { return $this->user; } }
  24. ChangePasswordForm <?php class ChangePasswordForm extends Form { protected $table; protected

    $user; ! public function __construct($id) { // ͲͷϢʔβʔʹରͯ͠มߋΛߦ͏ͷ͔ίϯετϥΫλͰઃఆ $this->table = TableRegistry::get('Users'); $this->user = $this->table->get($id); } ! !
  25. ChangePasswordForm <?php class ChangePasswordForm extends Form { ! protected function

    _buildSchema(Schema $schema) { // ϑΟʔϧυఆٛ return $schema ->addField('password', ['type' => 'string']) ->addField('new_password', ['type' => 'string']) ->addField('confirm_password', ['type' => 'string']); } ! ! ! !
  26. ChangePasswordForm <?php class ChangePasswordForm extends Form { ! protected function

    _buildValidator(Validator $validator) { // UsersTableʹఆٛͯ͋͠ΔvalidationΛར༻͢Δ // ݱࡏͷύεϫʔυͱҰக͢Δ $this->table->validationRequireCurrentPassword($validator); ! // ৽͍͠ύεϫʔυͱ֬ೝύεϫʔυͷೖྗ͕Ұக͢Δ $validator ->notEmpty('new_password', __('ύεϫʔυ͸ඞͣೖྗ͍ͯͩ͘͠͞ɻ')) ->notEmpty('confirm_password', __('ύεϫʔυ͸ඞͣೖྗ͍ͯͩ͘͠͞ɻ')); $validator->add('new_password', 'minLength', [ 'rule' => ['minLength', 6], 'message' => __('ύεϫʔυ͸6จࣈҎ্Ͱೖྗ͍ͯͩ͘͠͞ɻ'), ]) ->add('new_password', 'maxLength', [ 'rule' => ['maxLength', 255], 'message' => __('ύεϫʔυ͸255จࣈҎ಺Ͱೖྗ͍ͯͩ͘͠͞ɻ'), ]); $validator->add('confirm_password', 'maxLength', [ 'rule' => ['maxLength', 255], 'message' => __('ύεϫʔυ͸255จࣈҎ಺Ͱೖྗ͍ͯͩ͘͠͞ɻ'), ]) ->add('confirm_password', 'compareWith', [ 'rule' => ['compareWith', 'new_password'], 'message' => __('ύεϫʔυ͕Ұக͠·ͤΜɻ'), ]); !
  27. ChangePasswordForm <?php class ChangePasswordForm extends Form { protected function _execute(array

    $data) { // ύεϫʔυߋ৽ $newpassword = ['password' => $data['new_password']]; $this->table->patchEntity($this->user, $newpassword); if (!$this->table->save($this->user)) { return false; } ! // มߋͨ͠Βϝʔϧૹ৴ $mailer = new Email('default'); $mailer->to($this->user) ->subject(__('ύεϫʔυ͕มߋ͞Ε·ͨ͠')) ->template('change_password') ->viewVars(['user' => $user]) ->send(); ! return true; }
  28. ·ͱΊ

  29. ·ͱΊ w .PEFMMFTT'PSN͸εΩʔϚఆٛɺೖྗݕূɺॲཧ࣮ߦ͕Ͱ͖Δ w .PEFMMFTT'PSNΛ࢖͏ͱίϯτϩʔϥͷهड़Λ؆ૉԽͰ͖Δ w .PEFMMFTT͚ͩͲɺॲཧதʹ.PEFMΛར༻ͯ͠΋0, w ϏδωεϩδοΫΛهड़͢Δͷʹద͍ͯ͠Δ

  30. υΩϡϝϯτ w $PPLCPPL.PEFMMFTT'PSN
 IUUQCPPLDBLFQIQPSHFODPSFMJCSBSJFTGPSNIUNM w ೔ຊޠ༁
 IUUQCPPLDBLFQIQPSHKBDPSFMJCSBSJFTGPSNIUNM

  31. ฉ͖͍ͨ͜ͱ͋Δʁ

  32. ͓·͚

  33. Entityͷศརϝιου w EJSUZ  w HFU0SJHJOBM  w FYUSBDU 

    w FYUSBDU0SJHJOBM  w FYUSBDU0SJHJOBM$IBOHFE
  34. Entityͷศརϝιου w EJSUZ  ‣ ϓϩύςΟ͕มߋ͞Ε͔ͨνΣοΫ $entity = $Articles->get($id); //

    title = 'Original Title' $entity->title = 'New Title'; $entity->dirty('title'); // true
  35. Entityͷศརϝιου w HFU0SJHJOBM  ‣ มߋલͷ஋Λऔಘ $entity = $Articles->get($id); //

    title = 'Original Title' $entity->title = 'New Title'; $entity->getOriginal('title'); // 'Original Title'
  36. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠