如何使用Guzzle PHP获取SENT数据的主体?

时间:2016-01-20 20:57:05

标签: php http guzzle

我在PHP中使用Guzzle(v6.1.1)向服务器发出POST请求。它工作正常。我正在添加一些日志记录功能来记录发送和接收的内容,我无法弄清楚如何获取Guzzle发送到服务器的数据。我可以很好地获得响应,但如何获取已发送数据? (这将是JSON字符串。)

以下是我的代码的相关部分:

$client = new GuzzleHttp\Client(['base_uri' => $serviceUrlPayments ]);
    try {
       $response = $client->request('POST', 'Charge', [
            'auth' => [$securenetId, $secureKey],
            'json' => [     "amount" => $amount,
                            "paymentVaultToken" => array(
                                    "customerId" => $customerId,
                                    "paymentMethodId" => $token,
                                    "publicKey" => $publicKey
                                    ),
                            "extendedInformation" => array(
                                    "typeOfGoods" => $typeOfGoods,
                                    "userDefinedFields" => $udfs,
                                    "notes" => $Notes
                                    ),
                            'developerApplication'=> $developerApplication 
            ]
    ]);

    } catch (ServerErrorResponseException $e) {
        echo (string) $e->getResponse()->getBody();
    }


    echo $response->getBody(); // THIS CORRECTLY SHOWS THE SERVER RESPONSE
    echo $client->getBody();           // This doesn't work
    echo $client->request->getBody();  // nor does this

任何帮助将不胜感激。我确实试图在Guzzle源代码中查找类似于getBody()的函数,该函数可以处理请求,但我不是PHP专家,所以我没有提出任何有用的信息。我也经常搜索Google,但发现只有人在讨论从服务器上获取响应,我没有遇到任何问题。

4 个答案:

答案 0 :(得分:12)

您可以通过创建Middleware来完成这项工作。

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use Psr\Http\Message\RequestInterface;

$stack = HandlerStack::create();
// my middleware
$stack->push(Middleware::mapRequest(function (RequestInterface $request) {
    $contentsRequest = (string) $request->getBody();
    //var_dump($contentsRequest);

    return $request;
}));

$client = new Client([
    'base_uri' => 'http://www.example.com/api/',
    'handler' => $stack
]);

$response = $client->request('POST', 'itemupdate', [
    'auth' => [$username, $password],
    'json' => [
        "key" => "value",
        "key2" => "value",
    ]
]);

然而,这是在收到回复之前触发的。你可能想做这样的事情:

$stack->push(function (callable $handler) {
    return function (RequestInterface $request, array $options) use ($handler) {
        return $handler($request, $options)->then(
            function ($response) use ($request) {
                // work here
                $contentsRequest = (string) $request->getBody();
                //var_dump($contentsRequest);
                return $response;
            }
        );
    };
});

答案 1 :(得分:7)

使用Guzzle 6.2。

在过去的几天里,我一直在努力解决这一问题,同时尝试构建一种方法来审核与不同API的HTTP交互。在我的情况下,解决方案是简单地倒退请求正文。

请求的正文实际上是作为stream实现的。因此,发送请求时,Guzzle从流中读取。读取完整的流会将流的内部指针移到末尾。因此,在发出请求后调用getContents()时,内部指针已经位于流的末尾,并且不返回任何内容。

解决方案?将指针倒退到开头,然后再次读取流。

<?php
// ...
$body = $request->getBody();
echo $body->getContents(); // -->nothing

// Rewind the stream
$body->rewind();
echo $body->getContents(); // -->The request body :)

答案 2 :(得分:1)

您可以通过执行

来重现请求创建的数据字符串
public class ArticleListActivity extends ActionBarActivity implements LoaderManager.LoaderCallbacks<Cursor> {

    private int mFadeSleepTime = 16000;
    private int mWordBuffer = 200;//number of words we will display at a time
    private int mMaxChars = 0;
    private int mTotalPages = 0;
    private int mCurrentPage = 0;
    private Toolbar mToolbar;
    private SwipeRefreshLayout mSwipeRefreshLayout;
    private RecyclerView mRecyclerView;
    private int mTextPostion = 0;
    public int mPagePadding = 10;
    Animation fadeIn = new AlphaAnimation(0.0f, 1.0f);
    Animation fadeOut = new AlphaAnimation(1.0f, 0.0f);
    Animation mNewspaperClipSelectedAnimation;
    Animation mNewspaperClipSlideDownAnimation;
    Adapter mAdapter;
    String mbodyText;
    boolean mEndsInSpace = true;
    CoordinatorLayout mMainContainer;
    private Thread mTextSwitcherThread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_article_list);

        mToolbar = (Toolbar) findViewById(R.id.toolbar);

        final View toolbarContainerView = findViewById(R.id.toolbar_container);
        mMainContainer = (CoordinatorLayout) findViewById(R.id.main_coordinator_layout);
        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);

        fadeIn.setDuration(2000);
        fadeOut.setDuration(1000);

        mRecyclerView.setItemAnimator(null);
        mNewspaperClipSelectedAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.newspaper_selected_anim);
        mNewspaperClipSlideDownAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.newspaper_unselected_stories_slide_out);

        fadeOut.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
                    final int index = i;
                    View v = mRecyclerView.getChildAt(i);
                    v.findViewById(R.id.article_body).startAnimation(fadeIn);
                    mRecyclerView.invalidate();
                    ArticleListActivity.this.runOnUiThread(new Runnable() {
                        public void run() {
                            mAdapter.notifyItemChanged(index);
                        }
                    });
                }
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });


        getLoaderManager().initLoader(0, null, this);

        if (savedInstanceState == null) {
            refresh();
        }

        setTextFadeThread();
    }

    private void setTextFadeThread(){
        mTextSwitcherThread = new Thread() {
            @Override
            public void run() {
                try {
                    while (true) {
                        sleep(mFadeSleepTime);
                        mTextPostion += mWordBuffer;

                        while (mEndsInSpace) {
                            if (mbodyText.charAt(mTextPostion) != ' ') {
                                mTextPostion += 1;
                            } else {
                                mEndsInSpace = false;
                            }
                        }

                        if (mTextPostion > mMaxChars - mWordBuffer) {
                            mTextPostion = 0;
                            mCurrentPage = -1;
                        }

                        ArticleListActivity.this.runOnUiThread(new Runnable() {
                            public void run() {
                                for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
                                    View v = mRecyclerView.getChildAt(i);
                                    v.findViewById(R.id.article_body).startAnimation(fadeOut);
                                }
                                mCurrentPage = mCurrentPage + 1;
                            }
                        });

                        mEndsInSpace = true;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        mTextSwitcherThread.start();
    }

    private void addStoryToLibrary(){

    }

    private void refresh() {
        startService(new Intent(this, UpdaterService.class));
    }

    @Override
    protected void onStart() {
        super.onStart();
        registerReceiver(mRefreshingReceiver, new IntentFilter(UpdaterService.BROADCAST_ACTION_STATE_CHANGE));
    }

    @Override
    protected void onStop() {
        super.onStop();
        unregisterReceiver(mRefreshingReceiver);
    }

    private boolean mIsRefreshing = false;

    private BroadcastReceiver mRefreshingReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (UpdaterService.BROADCAST_ACTION_STATE_CHANGE.equals(intent.getAction())) {
                mIsRefreshing = intent.getBooleanExtra(UpdaterService.EXTRA_REFRESHING, false);
                updateRefreshingUI();
            }
        }
    };

    private void updateRefreshingUI() {
        mSwipeRefreshLayout.setRefreshing(mIsRefreshing);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
        return ArticleLoader.newAllArticlesInstance(this);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
        mAdapter = new Adapter(this,cursor);
        mAdapter.setHasStableIds(true);
        mRecyclerView.setAdapter(mAdapter);
        int columnCount = getResources().getInteger(R.integer.list_column_count);
        StaggeredGridLayoutManager sglm = new StaggeredGridLayoutManager(columnCount, StaggeredGridLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(sglm);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        mRecyclerView.setAdapter(null);
    }

    private class Adapter extends RecyclerView.Adapter<ViewHolder> {
        private Cursor mCursor;
        private Context mContext;

        public Adapter(Context context,Cursor cursor) {
            mContext = context;
            mCursor = cursor;
        }

        @Override
        public long getItemId(int position) {
            mCursor.moveToPosition(position);
            return mCursor.getLong(ArticleLoader.Query._ID);
        }

        @Override
        public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
            View view = getLayoutInflater().inflate(R.layout.list_item_article, parent, false);
            final ViewHolder vh = new ViewHolder(view);
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(final View view) {
                    mTextSwitcherThread.interrupt(); // interrupt text cycle thread as we go to detail views
                    for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
                        View v = mRecyclerView.getChildAt(i);
                        if(v != view) {
                            v.findViewById(R.id.article_body).startAnimation(fadeOut);
                            v.setAnimation(mNewspaperClipSlideDownAnimation);
                            v.startAnimation(mNewspaperClipSlideDownAnimation);
                        }
                    }

                    mNewspaperClipSlideDownAnimation.setAnimationListener(new Animation.AnimationListener() {
                        @Override
                        public void onAnimationStart(Animation animation) {

                        }

                        @Override
                        public void onAnimationEnd(Animation animation) {
                            for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
                                View v = mRecyclerView.getChildAt(i);
                                if(v != view) {
                                    v.setVisibility(View.INVISIBLE);
                                }
                            }
                        }

                        @Override
                        public void onAnimationRepeat(Animation animation) {

                        }
                    });

                    ExpandingCardViewAnimation animation = new ExpandingCardViewAnimation(getApplicationContext(),parent,view);
                    animation.configureAnimation();
                    view.setAnimation(mNewspaperClipSelectedAnimation);
                    view.startAnimation(mNewspaperClipSelectedAnimation);

                    mNewspaperClipSlideDownAnimation.setAnimationListener(new Animation.AnimationListener() {
                        @Override
                        public void onAnimationStart(Animation animation) {

                        }

                        @Override
                        public void onAnimationEnd(Animation animation) {
                            view.getViewTreeObserver().addOnPreDrawListener(
                                    new ViewTreeObserver.OnPreDrawListener() {
                                        @Override
                                        public boolean onPreDraw() {
                                            view.getViewTreeObserver().removeOnPreDrawListener(this);
                                            startPostponedEnterTransition(vh);
                                            return true;
                                        }
                                    });
                        }

                        @Override
                        public void onAnimationRepeat(Animation animation) {
                        }
                    });
                }
            });
            return vh;
        }

        public void startPostponedEnterTransition(ViewHolder vh){
            String transitionName = getString(R.string.transition_list_item);
            Activity activity = (Activity) mContext;
            ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, mRecyclerView,transitionName);
            ActivityCompat.startActivity(activity, new Intent(Intent.ACTION_VIEW, ItemsContract.Items.buildItemUri(getItemId(vh.getAdapterPosition()))), options.toBundle());
        }

        @Override
        public void onBindViewHolder(final ViewHolder holder, int position) {
            mCursor.moveToPosition(position);
            holder.titleView.setText(mCursor.getString(ArticleLoader.Query.TITLE));
            holder.subtitleView.setText(Html.fromHtml(
                    DateUtils.getRelativeTimeSpanString(
                            mCursor.getLong(ArticleLoader.Query.PUBLISHED_DATE),
                            System.currentTimeMillis(), DateUtils.HOUR_IN_MILLIS,
                            DateUtils.FORMAT_ABBREV_ALL).toString()
                            + " by <font color='#ffffff'>"
                            + mCursor.getString(ArticleLoader.Query.AUTHOR)
                            + "</font>"));
            holder.thumbnailView.setImageUrl(
                    mCursor.getString(ArticleLoader.Query.THUMB_URL),
                    ImageLoaderHelper.getInstance(ArticleListActivity.this).getImageLoader());
            holder.thumbnailView.setAspectRatio(mCursor.getFloat(ArticleLoader.Query.ASPECT_RATIO));

            mbodyText = mCursor.getString(ArticleLoader.Query.BODY);
            mMaxChars = mbodyText.length();
            mTotalPages = mMaxChars/mWordBuffer;
            holder.bodyView.setText(mbodyText.substring(mTextPostion, mTextPostion + mWordBuffer));

            holder.pagesview.removeAllViews();
            for(int i = 0; i < mTotalPages; i++){
                TextView mPageText = new TextView(getApplicationContext());
                mPageText.setLayoutParams(new RelativeLayout.LayoutParams(RecyclerView.LayoutParams.WRAP_CONTENT, RecyclerView.LayoutParams.WRAP_CONTENT));
                mPageText.setText(Integer.toString(i + 1));
                mPageText.setPadding(mPagePadding,mPagePadding,mPagePadding,0);
                mPageText.setTextSize(19);

                if(mCurrentPage == i)
                    mPageText.setTextColor(getResources().getColor(R.color.highlited_page_color));
                else
                    mPageText.setTextColor(getResources().getColor(R.color.blue_page_number_color));

                mPageText.setTag(i);
                mPageText.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        for (int i = 0; i < mTotalPages; i++) {
                            TextView pageView = (TextView) holder.pagesview.getChildAt(i);
                            pageView.setTextColor(getResources().getColor(R.color.blue_page_number_color));
                        }
                        ((TextView)v).setTextColor(getResources().getColor(R.color.highlited_page_color));
                        mTextPostion = (int) v.getTag() * mWordBuffer;
                        mCurrentPage = (int) v.getTag();
                        v.startAnimation(fadeOut);
                    }
                });
                holder.pagesview.addView(mPageText);
            }

            holder.libraryfabbutton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    addStoryToLibrary();
                    Snackbar addToLibrarySnackbar = Snackbar.make(mMainContainer,getString(R.string.story_added_to_library),Snackbar.LENGTH_LONG);
                    addToLibrarySnackbar.show();
                }
            });

            holder.facebooklikebutton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    addStoryToLibrary();
                    Snackbar addToLibrarySnackbar = Snackbar.make(mMainContainer,getString(R.string.story_added_to_library),Snackbar.LENGTH_LONG);
                    addToLibrarySnackbar.show();
                }
            });
        }

        @Override
        public int getItemCount() {
            return mCursor.getCount();
        }
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public DynamicHeightNetworkImageView thumbnailView;
        public TextView titleView;
        public TextView subtitleView;
        public TextView bodyView;
        public LinearLayout pagesview;
        public ImageButton libraryfabbutton;
        public ImageButton facebooklikebutton;

        public ViewHolder(final View view) {
            super(view);
            thumbnailView = (DynamicHeightNetworkImageView) view.findViewById(R.id.thumbnail);
            titleView = (TextView) view.findViewById(R.id.article_title);
            subtitleView = (TextView) view.findViewById(R.id.article_subtitle);
            bodyView = (TextView) view.findViewById(R.id.article_body);
            pagesview = (LinearLayout) view.findViewById(R.id.newspaper_clip_pages);
            libraryfabbutton = (ImageButton) view.findViewById(R.id.add_to_lib_fab);
            facebooklikebutton = (ImageButton) view.findViewById(R.id.face_book_like_button);
        }
    }
}

这会将您的数据输出为JSON字符串。

http://php.net/manual/fr/function.json-encode.php

上的文档

修改

Guzzle有一个$data = array( "key" => "value", "key2" => "value", ); $response = $client->request('POST', 'itemupdate', [ 'auth' => [$username, $password], 'json' => $data, ]); // ... echo json_encode($data); 和一个Request类(以及许多其他类) Response实际上有一个Request方法,该方法将包含您getQuery()的对象作为私有对象返回,与所有其他成员相同。
你也无法访问它。

这就是为什么我认为手动编码它是更容易的解决方案。 如果你想知道Guzzle做了什么,它还有一个data类来转换数据并在请求中发送它。

答案 3 :(得分:1)

我的 Laravel 5.7版本的解决方案

MessageFormatter可用于变量替换,请参见:https://github.com/guzzle/guzzle/blob/master/src/MessageFormatter.php

     $stack = HandlerStack::create();
        $stack->push(
            Middleware::log(
                Log::channel('single'),
                new MessageFormatter('Req Body: {request}')
            )
     );

    $client = new Client();
    $response = $client->request(
        'POST',
        'https://url.com/go',
        [
            'headers' => [
                "Content-Type" => "application/json",
                'Authorization' => 'Bearer 123'
            ],
            'json' => $menu,
            'handler' => $stack
        ]
    );