easy-swoole / orm

31 stars 27 forks source link

Model hasOne() relation not working when excluding $pk from parent model field()! #152

Closed AhmedAsser closed 3 years ago

AhmedAsser commented 4 years ago

orm: V1.4.12 I could not get "hasone" relation to work if the related $pk field excluded from SQL fields.

  public function category()
    {
        return $this->hasOne(CategoryModel::class, null, CarModel::CL_FK_CATEGORY_ID, CategoryModel::CL_PK_ID);
    }

Usage:

CarModel::create()
            ->field([
                CarModel::CL_PK_ID,
                CarModel::CL_S_NAME,
                CarModel::CL_I_ORDER,
               // CarModel::CL_FK_CATEGORY_ID,  <<< Removed
            ])
            ->with('category')
            ->all();

Query Result: SELECT * FROMcategoryWHEREpk_idIN ( 'NULL' )

I think $pk parameter in hasOne() function should be appended to the parent field() model and then unset it after that or at least explicitly throw an exception to avoid unexpected issues.

xuanyanwow commented 4 years ago

will fixes this question next version.thanks.

I hope you can help us to test when we fixes it.

xuanyanwow commented 3 years ago

We update the method to fixes this question. Can you test again and then tell us the result. Thank.

Tip: maybe you should use the master branch version.

        if (!empty($this->with) && $this->fields !== '*'){
            $this->preHandleWith = true;
            foreach ($this->with as $with){
                $pk = $this->$with()[2];
                if (!in_array($pk, $this->fields)){
                    $this->fields[] = $pk;
                }
            }
            $this->preHandleWith = false;
        }

test/RelationToArrayTest.php

    // 需要的field没有在fields中 自动补充
    public function testGetWithNoneField()
    {
        $test = TestRelationModel::create()->field(['id', 'age'])->with(['user_list', 'has_many'])->get([
            'name' => 'siam'
        ]);
        $this->assertNotEmpty($test['name']);   // look this.
        $this->assertInstanceOf(TestUserListModel::class, $test['user_list']);
    }

    public function testAllWithNOneField()
    {
        $test = TestRelationModel::create()->field(['id'])->with(['user_list', 'has_many'])->all();
        $this->assertNotEmpty($test[0]['user_list']);
        $this->assertNotEmpty($test[0]['name']);
        $this->assertInstanceOf(TestUserListModel::class, $test[0]['user_list']);
    }

Model Fiel

    public function user_list()
    {
        return $this->hasOne(TestUserListModel::class, null, 'name', 'name');
    }

    public function has_many_where()
    {
        return $this->hasMany(TestUserListModel::class, function (QueryBuilder $builder){
            $builder->where("age", 21);
        }, 'name', 'name');
    }

    public function has_many()
    {
        return $this->hasMany(TestUserListModel::class, null, 'name', 'name');
    }
AhmedAsser commented 3 years ago

I have tested it on master branch and it works well. thanks.