Thinkphp 5.0 modifier and data completion

Keywords: PHP Database less

Problems encountered in cryptographic encryption

Today we encounter the problem of md5 encryption. At that time, we used "thinkphp 5.0.9-> model - > data completion" to realize automatic encryption. But in the above "thinkphp 5.0.9-> model - > modifier", we found that the modifier and data completion function are the same. Looking at the comments below, it is said that data completion and modifier are used together, I followed them.

//Model Layer

class User extends Model{
//The $auto contains the new $insert and the update operation $update, which means that I automatically execute whether it's new or updated.
    protected $auto = ['password','create'];
    public function setPasswordAttr($value)
    {
        return md5($value);
    }
    public function setCreateAttr()
    {
        return time();
    }
    
//Registered User
    public function register($data){
            $bool = $this->save($data);
            return $bool ? $this->id : 0;
    } 
}

//Controller Layer Method
public function register()
    {
        if(request()->isAjax()){
            $userModel=new \app\index\Model\User();
            $data=input('post.');
//register
            $res = $userModel->register($data);
           echo $res;
        }else{
            $this->error('Illegal visits');
        }
    }

After I entered "www www" and registered according to the above code, the password encryption result was b8d3c8f4db0c248ac242dd6e098bbf85.

The correct encryption result is d785c99d298a4e9e6e13fe99e602ef42. At this time, you may not find that when you log in, you just can't log in. You must register a new user, such as password or www. You can't log in when you log in. You can only suspect that the encryption is wrong, and then find "setPasswordAttr()" on it.

Take it out separately for testing

Let's go straight to the answer. I looked at the modifier and the data for two hours to complete the test. I finally got the reason. The new test table

//New test model layer
namespace app\index\Model;
use think\Model;
class Test extends Model
{
    protected $auto = ['password'];
    protected function setPasswordAttr($value)
    {
        dump(md5(NULL));
        dump($value);
        dump(md5($value));
        return md5($value);

    }
    public function addPass(){
        echo "Modifier";
        $this->password='wwwwww';
        dump($this->password);
        
        echo "Data completion";
        $this->save([
            'username'  => 'thinkphp',
            'password'  => 'wwwwww',
            'create'    => '123456'
        ]);
    }
}

//Adding test method to controller
 public function test(){
        $user = model('Test');
        //Calling model Layer Functions
        $user->addPass();
    }

Test the modifier separately

First, comment out the "data completion" section in the model layer

namespace app\index\Model;
use think\Model;
class Test extends Model
{
    protected $auto = ['password'];
    protected function setPasswordAttr($value)
    {
        dump(md5(NULL));//Encrypt NULL
        dump($value);   //View the values passed in when the call is invoked
        dump(md5($value));//Encrypt the value
        return md5($value);//Encrypt the value back

    }
    public function addPass(){
        echo "Modifier: The function of the modifier is to automatically convert data when it is assigned.";
        $this->password='wwwwww';
        dump($this->password);//Output Returns

//        echo "data completion: data field insert,update,auto processing";
//        $this->save([
//            'username'  => 'thinkphp',
//            'password'  => 'wwwwww',
//            'create'    => '123456'
//        ]);
    }
}

After execution, the page displays the results, and finds that the modifier is automatically encrypted when assigning values. Note: At this time, it is not stored in the database!

Modifier: The function of the modifier is to automatically convert data when it is assigned.

string(32) "d41d8cd98f00b204e9800998ecf8427e" [Encrypted NULL]

String (6) "www www" [passed in $value]

string(32) "d785c99d298a4e9e6e13fe99e602ef42" [encryption $value]

string(32) "d785c99d298a4e9e6e13fe99e602ef42" [results return ed]

Test data completion

Comment out the "Modifier" part of the code and only execute data completion

namespace app\index\Model;
use think\Model;
class Test extends Model
{
    protected $auto = ['password'];
    protected function setPasswordAttr($value)
    {
        dump(md5(NULL));//Encrypt NULL
        dump($value);   //View the values passed in when the call is invoked
        dump(md5($value));//Encrypt the value
        return md5($value);//Encrypt the value back

    }
    public function addPass(){
//        echo "modifier: the function of modifier is to automatically convert data when assigning value";
//        $this->password='wwwwww';
//        Dump ($this - > password); // Output the returned result

        echo "Data completion: in data fields insert,update,auto Processing from time to time";
        $this->save([
            'username'  => 'thinkphp',
            'password'  => 'wwwwww',
            'create'    => '123456'
        ]);
    }
}

Find out why

After execution, setPasswordAttr() was executed twice, so password was encrypted twice.

Data Completion: Processing in insert,update,auto data fields

string(32) "d41d8cd98f00b204e9800998ecf8427e" [Encrypted NULL]

String (6) "www www" [incoming $value]

string(32) "d785c99d298a4e9e6e13fe99e602ef42" [encryption $value= "www"]

string(32) "d41d8cd98f00b204e9800998ecf8427e" [Encrypted NULL]

string(32) "d785c99d298a4e9e6e13fe99e602ef42" [incoming $value]

string(32) "b8d3c8f4db0c248ac242dd6e098bbf85" [re-encrypted $value="d785c99...f42"]

The reason for encrypting twice is that it is encrypted once at assignment time and once at auto time.

[
    'username'  => 'thinkphp',
    'password'  => 'wwwwww',
    'create'    => '123456'
]

Solve the initial problem

If you want to encrypt it once, you can annotate protected $auto = ['password']; or you can annotate MD5 (md5 ("wwwww") in the login code and execute after annotation:

Data Completion: Processing in insert,update,auto data fields

string(32) "d41d8cd98f00b204e9800998ecf8427e" [Encrypted NULL]

string(6) "wwwwww"[$value]

string(32) "d785c99d298a4e9e6e13fe99e602ef42" [encryption result]

If you have multiple fields protected $auto = ['password','create']; you can remove the password and protect $auto = ['create']; so the initial problem is solved.

When only data is complete but not assigned

I may have noticed above how I always encrypt NULL, and another case is protected $auto = ['password']; automatic completion is defined, but I don't assign a value:

namespace app\index\Model;
use think\Model;
class Test extends Model
{
    protected $auto = ['password'];
    protected function setPasswordAttr($value)
    {
        dump(md5(NULL));//Encrypt NULL
        dump($value);   //View the values passed in when the call is invoked
        dump(md5($value));//Encrypt the value
        return md5($value);//Encrypt the value back

    }
    public function addPass(){
//        echo "modifier: the function of modifier is to automatically convert data when assigning value";
//        $this->password='wwwwww';
//        Dump ($this - > password); // Output the returned result

        echo "Data completion: in data fields insert,update,auto Processing from time to time";
        $this->save([
            'username'  => 'thinkphp',
//Note out, no assignment
 //           'password'  => 'wwwwww',
            'create'    => '123456'
        ]);
    }
}

After execution, NULL is encrypted

Data Completion: Processing in insert,update,auto data fields

string(32) "d41d8cd98f00b204e9800998ecf8427e" [Encrypted NULL]

NULL [No value, $value=NULL]

String (32) d41d8cd98f00b204e9800998ecf8427e

The remaining $update and $insert are used in the same way as $auto, $auto contains $update and $insert.

summary

The modifier executes at assignment time; data completion is executed twice, once at assignment time and once at write time.

Hope that the manual can be a little more detailed, in vain delayed my development time, hereby share, you step on the pit less, if not understand, please correct, thank you.

Posted by joePHP on Mon, 17 Jun 2019 15:20:51 -0700