2016-09-26 42 views
0

更新什麼,我試圖做之前屬於的hasMany關聯:如何檢查項目中的CakePHP 3.2

我估計和估計有項目「EstimateItems」。更新估計時,更改的估計項應更新。 (使用patchEntity)

這與我當前的代碼一起工作,唯一的問題是其他用戶可以在編輯窗體中更改EstimateItem的主鍵時編輯其他用戶的估計項目,因爲修補現有的EstimateItem時CakePHP只查看EstimateItem的主鍵,並不考慮關聯。此外,仍可以編輯EstimateItem的estimate_id,而$ protected estimate_id設置爲false。

所以我需要的是CakePHP在更新之前或嘗試更新時驗證此EstimateItem屬於當前關聯。

我希望有人能告訴我我做錯了什麼或我失蹤了。

當前查詢

UPDATE 
    estimate_items 
SET 
    data = 'Test Query 1', 
    amount = 123456789, 
    tax_id = 3 
WHERE 
    id = 3 

預期查詢

UPDATE 
    estimate_items 
SET 
    data = 'Test Query 1', 
    amount = 123456789, 
    tax_id = 3 
WHERE 
    id = 3 AND estimate_id = 1 

當前代碼:

預估 - >編輯。CTP

<?php $this->Form->templates($formTemplates['default']); ?> 
<?= $this->Form->create($estimate, ['enctype' => 'multipart/form-data']) ?> 
    <fieldset> 
     <legend><?= __('Offerte') ?></legend> 

     <?= $this->Form->input('reference', ['label' => __('#Referentie'), 'autocomplete' => 'off']) ?> 
     <?= $this->Form->input('client_id', 
      [ 
       'type' => 'select', 
       'empty' => true, 
       'label' => __('Klant'), 
       'options' => $clients 
      ] 
     ) 
     ?> 

     <?php 

     foreach($estimate->estimate_items as $key => $item){ 
     ?> 
     <div class="item"> 
      <legend>Item</legend> 
      <?= $this->Form->hidden('estimate_items.'. $key .'.id') ?> 
      <?= $this->Form->input('estimate_items.'. $key .'.data', ['type' => 'text', 'label' => __('Beschrijving')]) ?> 
      <?= $this->Form->input('estimate_items.'. $key .'.amount', ['type' => 'text', 'label' => __('Bedrag'), 'class' => 'input-date']) ?> 
      <?= $this->Form->input('estimate_items.'. $key .'.tax_id', 
       [ 
        'type' => 'select', 
        'empty' => true, 
        'label' => __('Belasting type'), 
        'options' => $taxes 
       ] 
      ) 
      ?> 
     </div> 
     <?php 
     } 

     ?> 

     <legend>Informatie</legend> 
     <?= $this->Form->input('date', ['type' => 'text', 'label' => __('Offerte datum'), 'autocomplete' => 'off']) ?> 
     <?= $this->Form->input('expiration', ['type' => 'text', 'label' => __('Verloop datum'), 'autocomplete' => 'off']) ?> 
    </fieldset> 
<?= $this->Form->button(__('Save')); ?> 
<?= $this->Form->end() ?> 

估計控制器

namespace App\Controller; 

use App\Controller\AppController; 
use Cake\Event\Event; 
use Cake\ORM\TableRegistry; 

class EstimatesController extends AppController 
{ 
public function edit($id){ 
     $associated = ['EstimateItems']; 

     $estimate = $this->Estimates->get($id, ['contain' => $associated]); 

     $this->log($estimate); 
     if($this->request->is(['patch', 'post', 'put'])) { 

      $estimate = $this->Estimates->patchEntity($estimate, $this->request->data, [ 
       'associated' => $associated 
      ]); 

      $estimate->total = '0'; 
      $this->log($estimate); 
      $this->log($this->request->data); 

      if($this->Estimates->save($estimate, ['associated' => $associated])){ 
       $this->Flash->success(__('De offerte is bijgewerkt')); 
       return $this->redirect(['action' => 'index']); 
      } 
     } 

     $this->set('taxes', $this->Estimates->Taxes->find('list', [ 'keyField' => 'id', 'valueField' => 'tax_name' ])); 
     $this->set('clients', $this->Estimates->Clients->find('list', [ 'keyField' => 'id', 'valueField' => 'companyname' ])); 
     $this->set('estimate', $estimate); 
    } 
} 

EstimatesTable

<?php 
namespace App\Model\Table; 

use Cake\ORM\Query; 
use Cake\ORM\Table; 
use Cake\Validation\Validator; 
use Cake\ORM\RulesChecker; 
use Cake\ORM\Rule\IsUnique; 

class EstimatesTable extends Table 
{ 
public function initialize(array $config) 
    { 
     $this->addAssociations([ 
      'hasOne' => ['Taxes'], 
      'belongsTo' => ['Companies', 'Clients'], 
      'hasMany' => ['EstimateItems' => [ 
       'foreignKey' => 'estimate_id' 
      ]] 
     ]); 

    } 

public function buildRules(RulesChecker $rules){ 

     // A Node however should in addition also always reference a Site. 
     $rules->add($rules->existsIn(['estimate_id'], 'EstimateItems')); 

     return $rules; 
    } 

} 

EstimateItem實體

<?php 
namespace App\Model\Entity; 

use Cake\ORM\Entity; 

class EstimateItem extends Entity 
{ 
    protected $_accessible = [ 
     '*' => false, 
     'data' => true, 
     'amount' => true, 
     'tax_id' => true, 
     'unit_id' => true 
    ]; 
} 

EstimateItemsTable

<?php 
namespace App\Model\Table; 

use Cake\ORM\Entity; 
use Cake\ORM\Table; 
use Cake\Validation\Validator; 
use Cake\ORM\RulesChecker; 
use Cake\ORM\Rule\IsUnique; 
use Cake\ORM\Query; 


class EstimateItemsTable extends Table 
{ 

    public function initialize(array $config) 
    { 
     $this->addAssociations([ 
      'belongsTo' => ['Estimates' => ['foreignKey' => 'estimate_id']], 
      'hasOne' => ['Taxes' => ['foreignKey' => 'tax_id']] 
     ]); 
    } 

評估實體

<?php 
namespace App\Model\Entity; 

use Cake\ORM\Entity; 

class Estimate extends Entity 
{ 

    /** 
    * Fields that can be mass assigned using newEntity() or patchEntity(). 
    * 
    * Note that when '*' is set to true, this allows all unspecified fields to 
    * be mass assigned. For security purposes, it is advised to set '*' to false 
    * (or remove it), and explicitly make individual fields accessible as needed. 
    * 
    * @var array 
    */ 
    protected $_accessible = [ 
     '*' => false, 
     'id' => false, 
    ]; 
} 
+0

你只是假設,這可能發生,還是你真的測試過它?考慮到你的'$ _accessible'配置,'id'和'estimate_id'都不能使它從請求數據到實體中。 – ndm

+0

這已經過測試。我也沒有想到你提到的這種行爲,這就是爲什麼我明天會在github蛋糕上發帖子,並問爲什麼會發生這種情況。 –

回答

0

Markstory回覆了我在github上一個解決方案學分他: https://github.com/cakephp/cakephp/issues/9527

在型號/表/ EstimateItemsTable.php


<?php 
namespace App\Model\Table; 

use Cake\ORM\RulesChecker; 
.... 
class EstimateItemsTable extends Table 
{ 
.... 
public function buildRules(RulesChecker $rules){ 
     $rules->addUpdate(function($entity) { 

      if (!$entity->dirty('estimate_id')) { 
      return true; 
      } 
      return $entity->estimate_id == $entity->getOriginal('estimate_id'); 
     }, 'ownership', ['errorField' => 'estimate_id']); 

     return $rules; 
    } 
} 
0

看起來,你需要通過beforeSave回調函數來實現的檢查,如果你不相信,設定欄隱藏/不可編輯是不夠的。

在callBack中,您可以檢查該關係是否已經存在,然後用錯誤編輯的值覆蓋它們。

+0

所以Cake沒有解決這個問題?所以你說我應該對每個單獨的EstimateItem進行查詢,以檢查它是否與當前的Estimate相關聯?有沒有辦法在更新查詢中添加where子句? –

+0

我不確定CakePhp3我對CaePhp2有更多的經驗,但是如果你可以用特殊查詢解決問題,你可以自由地覆蓋正常的保存行爲。 但是我會做的是: *確保沒有人與原始數據混淆 *如果這是不可能的寫回調 –

+0

我想我會在他們的github上發佈一篇文章,如果沒有人知道內置的解決方案並向開發人員詢問最佳解決方案。但我會考慮你的答案。如果沒有其他解決方案,我可能會使用beforeSave。 –