1

I am using a rest api in yii2 with Authorization : Bearer and my update action requires sending data using PUT. I have configured the actionUpdate completely but somehow i am not getting any data in Request PUT.

I found few articles online about problems with Yii2 PUT but could not find out weather there is any solution to that yet or not?

One of the article or issue is github issue and it points to this github issue

Ad if no solution yet than what alternative should i use for Update action.

Here is my actionUpdate code

public function actionUpdate($id)
{
    $params = Yii::$app->request->bodyParams;

    $model = Event::find()->where(['event_id'=>$id])->andWhere(['partner_id' => Yii::$app->user->id])->one();

    if($model !== null){

        $model->load($params, '');
        $model->partner_id = Yii::$app->user->id;
        $model->updated_date = time();

        if ($model->save()) {

            $this->setHeader(200);
            echo json_encode(array('status'=>1,'data'=>array_filter($model->attributes)),JSON_PRETTY_PRINT);

        }
    }
 }

This is a screenshot of debug screen. See the event_name attribute.

enter image description here

That was screenshot after the execution of $model->load($params,'') line.

I am calling the service like following and not able to Update the data properly. My service works fine through postman.So i guess i am missing something in CURL request.

$service_url = 'http://localhost/site-api/api/web/v1/events/'.$eventDetailDBI->gv ('id');
            $curl = curl_init($service_url);
            $curl_post_data = array(
                "event_name" => $eventDetailDBI->gv ('name'),

            );

            $header = array();
            $header[] = 'Authorization: Bearer 4p9mj82PTl1BWSya7bfpU_Nm';
            $header[] = 'Content-Type: application/x-www-form-urlencoded';

            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($curl, CURLOPT_HTTPHEADER,$header);
            curl_setopt($curl, CURLOPT_PUT, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $curl_post_data);
            $curl_response = curl_exec($curl);
            $json = json_decode($curl_response, true);
            curl_close($curl);

I am getting correct data in my POST fields and passing correct data but the service doesnt update any data.

Thank you

Mike Ross
  • 2,942
  • 5
  • 49
  • 101
  • Please post the sample code as well. Thanks – Chetan Sharma May 17 '16 at 07:40
  • which problems ? I don't know about any open PUT related issue in their github repo. The only time I didn't get PUT working was because my IIS server had the PUT verbs disabled by default and had nothing to do with Yii. can you specify that PUT issue please by sharing code or linking any of those articles ? – Salem Ouerdani May 17 '16 at 07:48

1 Answers1

1

try this:

public function actionUpdate($id)
{
    // this will get what you did send as application/x-www-form-urlencoded params
    // note that if you are sending data as query params you can use Yii::$app->request->queryParams instead.
    $params = Yii::$app->request->bodyParams;

    $model = Event::find()->where(['event_id'=>$id])->andWhere(['partner_id' => Yii::$app->user->id])->one();

    if($model !== null){

        // This will load data to your safe attribute as defined in your model rules using your default scenario.
        $model->load($params, '');

        $model->partner_id = Yii::$app->user->id;
        $model->updated_date = time();

        if ($model->save()) {

            /*
                you can use Yii::$app->getResponse()->setStatusCode(200) here but no need to do that. 
                response will be 200 by default as you are returning data.
            */

            // yii\rest\Serializer will take care here of encoding model's related attributes.
            return [
                'status' => 1,
                'data' => $model
            ];

        }
        else {
           // when validation fails. you model instance will hold error messages and response will be auto set to 422.
           return $model;
        }
    }
 }
Salem Ouerdani
  • 7,596
  • 3
  • 40
  • 52
  • it works in a way. I do see the parameters in the `$params ` but it also has many other data in it so i dont know how can i load the model atributes only in it. `$params` has other values like `WebKitFormBoundary` etc. – Mike Ross May 17 '16 at 08:49
  • that is what does [load()](http://www.yiiframework.com/doc-2.0/yii-base-model.html#load()-detail). it will only get from the params what your model::rules() consider safe attributes. In other words if `WebKitFormBoundary` is not defined inside your model rules() or at least not set to safe then it will be simply ignored when loading data to your model. see [Yii docs](http://www.yiiframework.com/doc-2.0/guide-structure-models.html#validation-rules) for more details. – Salem Ouerdani May 17 '16 at 08:53
  • i got that from your comment above that line of code. But its not loading the data. I am uploading the debug screenshot in a moment. And i am making the request from postman right now. I know it doesnt matter but just so you know if it affects in anyway. – Mike Ross May 17 '16 at 08:58
  • It may also be useful to check how the built-in actionUpdate in Yii REST is working by default: https://github.com/yiisoft/yii2/blob/master/framework/rest/UpdateAction.php – Salem Ouerdani May 17 '16 at 09:04
  • i considered using the inbuilt `actionUpdate` but as you can see i want to use 2 `where` condition to find the desired record so i have to override the `actionUpdate`. If there is anyway i can do it wil built in function let me know.Thank you – Mike Ross May 17 '16 at 09:07
  • I think you are using the form-data tab in postman. use x-www-form-urlencoded instead (the tab next to it). that is what usually an ajax request will use. and I think yes there is other way to not override the built-in updateAction. I'll add it to my answer later. but first, is your model's primary key unique ? – Salem Ouerdani May 17 '16 at 09:12
  • Yes my model primary key is unique but i am using combination of event_id and partner_id to get the exact data. – Mike Ross May 17 '16 at 09:19
  • ah no. I think it is better to override the update action as you did in that case. my idea was to use `beforeSave` inside model to set `partner_id` like I've done it [here](https://github.com/tunecino/Yii2_foundation-apps/blob/cc01d7179cb93936dd74945f0173cbc1725f2963/backend/models/Image.php#L79) then using `checkAccess` in controller to deny non owner update like I've done [here](https://github.com/tunecino/Yii2_foundation-apps/blob/cc01d7179cb93936dd74945f0173cbc1725f2963/backend/api/modules/v1/controllers/ImageController.php#L18-L24). but your data structure is different than mine. – Salem Ouerdani May 17 '16 at 09:33
  • i have and it works properly through postman but when i send request using `curl` its acting out. Do i have to specify something in header for making sure that data is sent using `x-www-form-urlencoded`? – Mike Ross May 17 '16 at 10:35
  • yes. here is an example: http://stackoverflow.com/questions/18913345/curl-posting-with-header-application-x-www-form-urlencoded – Salem Ouerdani May 17 '16 at 10:47
  • i have tried that and it works fine with POSTMAN but not with my http request with `CURL`. I have added the code in the question using the link you suggested. Let me know what setting am i missing. – Mike Ross May 17 '16 at 23:37
  • I don't know. usually when it works in postman it should also work in my angular app. Sorry but I never used PHP as client before. – Salem Ouerdani May 20 '16 at 13:43