0
votes

I'm trying to display the model data in the GridView column value, but it keep shows error: Call to a member function getUSD() on string.
I only want to display one data in that data cell. Can anyone know what's the problem?

Model code:

public static function getUSD(){
    $getUSD = Rate::find()
            ->select('rate')
            ->where(['currency_name' => 'USD'])
            ->orderBy('rate_id DESC')
            ->one();
        return $getUSD;
}

Code in the GirdView:

<?= GridView::widget([
'dataProvider' => $dataProvider,
'summary' => '',
'columns' => [
    [
        'label' => 'USD',
        'value' => function($model){
            return $model->getUSD();
        }
    ],

Expected output:

|USD|  
| 4.102|
3
Clarify the desired output. Since you not present in what form data is stored in DB - Serghei Leonenco
@SergheiLeonenco I want my output same as the one in my db which stored as float. - ahzy96

3 Answers

0
votes

You are returning the object from the function rather than the actual rate column value, you should instead be getting the error

htmlspecialchars() expects parameter 1 to be string, object given

rather the one you are mentioning, because the gridview column expects you to return string and when trying to render the cell using the yii\grid\DataColumn::renderDataCellContent which calls the yii\i18n\Formatter to render as text which finds the object instead in your case.

Also you have defined the function as getter and yii says

Nearly every core class in the Yii framework extends from yii\base\BaseObject or a child class. This means, that whenever you see a getter or setter in a core class, you can use it like a property.

And change your function to

public static function getUSD()
{
    $rate = Rate::find()
        ->select('rate')
        ->where(['currency_name' => 'USD'])
        ->orderBy('rate_id DESC')
        ->one();

    return null !== $rate ? $rate->rate : 'NA';
}

And call it like below.

echo GridView::widget(
    [
        'dataProvider' => $dataProvider,
        'summary' => '',
        'columns' => [
            [
                'label' => 'USD',
                'value' => function ($model) {
                    return $model->USD;
                },

            ],
        ],
    ]
);

If you dont wish to change the getUSD() function then you might have to check it inside the gridview like below

echo GridView::widget(
    [
        'dataProvider' => $dataProvider,
        'summary' => '',
        'columns' => [
            [
                'label' => 'USD',
                'value' => function ($model) {
                    return null !== $model->USD ? $model->USD->rate: 'NA';
                },

            ],
        ],
    ]
);
0
votes

The problem is that getUSD() function does not return an string, returns an object with the attribute rate.

In order for it to work as you do you must return directly the value of the object like:

public static function getUSD(){

    $getUSD = Rate::find()
            ->select('rate')
            ->where(['currency_name' => 'USD'])
            ->orderBy('rate_id DESC')
            ->one();

        return $getUSD ? $getUSD->rate : null;
}

Now you first check if the query found something, and if it found something then you return the property rate.

Then getUSD is an static method so you should not do like $model->getUsd() but $model::getUSD().

0
votes

If you handle same data over and over again the same time, then I would consider calling them not statically and save (in between) results somewhere (in a property of the class for example), saving you from having too many queries.

Like an answer for your question You can call it this way:

return $model::getUSD()->rate; //Call to a static method from current model

or

return 'USD ' . $model::getUSD()->rate; //Call to a static method from current model

Like an option described at the beginning you can do this way too:

$model = new MyModel();
$rate = MyModel::getUSD()->rate;//get value of current rate

//Gridview

<?= GridView::widget([
'dataProvider' => $dataProvider,
'summary' => '',
'columns' => [
    [
        'label' => 'USD',
        'value' => function($model) use ($rate){
            return 'USD' . $rate; //Your initially stored rate
        }
    ],