CakePHP hasOne-belongsTo relationship, how to look

2019-08-28 02:20发布

问题:

I have two tables:

Property (..., postcode_id, ...)
Postcode (id, postcode, latitude, longitude)

The relationship:

class Property extends AppModel {
    public $belongsTo = array(
        'Postcode' => array(
            'className' => 'Postcode'
        )
    );

class Postcode extends AppModel {
    public $hasMany = array(
        'Property' => array(
            'className' => 'Property'
       )
    );

What I'd like to happen:

  1. Enter a postcode in the Property add form.
  2. Check entered postcode is in the Postcode table.
  3. If not, so some logic (possibly add it, just return validation error for now).
  4. If so, then record the Postcode.id in Properties.postcode_id (the foreign key).

I can't figure out the best way to do this with cake. A custom Property validation function that does the check and adds it to data to be added? Or in beforeValidation? Or does Cake deal with this?

Thanks!

EDIT

Based on the answer, I think this is the best solution...

I think this is the better way to do it, as it validates too. Thanks Anubhav for the putting me on the right track!

As per Anubhav's answer, in the Postcode model:

public function checkPostcode($postcode = null){
    $record = $this->find('first', array(
            'conditions'=>array('postcode' => $postcode),
            'fields' => array('id')
        ));
    if (!empty($record)){
        return $record['Postcode']['id'];
    } else {
        return false;
        // Logic for finding and adding new postcode
    } 
}

But and in the Property model:

public $validate = array(
    'postcode' => array(
        'exists' => array(
            'rule' => 'postcodeExists',
            'message' => 'Postcode does not exist'
        )
    )
);

public function postcodeExists($check) {
    $id = $this->Postcode->checkPostcode($check);
    if ($id) {
        $this->data['Property']['postcode_id'] = $id;
        return true;
    } 
    return false;
}

public function beforeSave($options = array()) {
    unset($this->data['Property']['postcode']);
}

By modifying the values to save here, the controller is kept skinny, and, rather than making sure postcode is real then finding the id, both are done at once, so only one query is needed.

回答1:

Follow the steps:

Step 1: Create one action in Postcode.php

function checkPostcode($postcodeValue = null){
  $returnData = $this->find('first',
                array('conditions'=>array('postcode'=>$postcodeValue),
                      'fields'=>array('id'))
                      );
  if(!empty($returnData)){
   return $returnData['Postcode']['id'];
  }else{
   $saveData['Postcode']['postcode'] = $postcodeValue;
   $this->save($saveData);
   return $this->getLastInsertID();
  } 
 }

The above function will check postcode from postcode model and insert postcode if not exist and returns the id of postcode table for corresponding row.

Step 2: Call this function controller action as

function someFuntion(){
        $postcode_id = $this->Postcode->checkPostcode($userInputPostcodeHere);
        // Write code to save property here 
    }

Hope this will give you some idea about the logic...