是什么导致 "No Request object configured. Cannot invoke action" 错误?
What is causing the "No Request object configured. Cannot invoke action" error?
我正在尝试使用 CakePHP 在我的 YouTube 帐户上上传视频,我尝试了简单的 PHP 并且工作正常但是,当我将代码转换为 CakePHP 报错了,求大神指点。
Erro is : No Request object configured. Cannot invoke action
以下是UploadController.php
<?php
namespace App\Controller;
/**
*
*/
use Google_Client;
use Google_Service_YouTube;
use Google_Service_YouTube_VideoSnippet;
use Google_Service_YouTube_VideoStatus;
use Google_Service_YouTube_Video;
use Google_Http_MediaFileUpload;
use Google_Exception;
/**
*
*/
/**
*
*/
class UploadController extends AppController
{
private $access_token;
private $OAUTH2_CLIENT_ID;
private $OAUTH2_CLIENT_SECRET;
public function __construct ($access_token)
{
$this->access_token = $access_token;
$this->OAUTH2_CLIENT_ID =
'replace here';
$this->OAUTH2_CLIENT_SECRET = 'replace here';
}
public function index()
{
if($this->request->is('post')){
$title = $this->request->getData('title');
$video = $this->request->getData('video');
$path = $this->request->getData('path');
$description = $this->request->getData('description');
$results = [];
if(empty($title)){
$this->Flash->error('Title cant be empty');
}else{
if(empty($video)){
$this->Flash->error('Please select a video');
}
}
$results = $this->upload($title, $video, $path, $description);
}
$this->set(compact('title','video','path','description'));
}
/**
* @param $video_file : name of the video file to be uploaded
* @param $file_path : path directory of video file to be uploaded
* @return bool
*/
public function test($video_path, $video_file)
{
$full_path = Configure::read('video.upload.video.path') . $video_path . DS . $video_file;
if($full_path){
return $full_path;
}
return $this->access_token;
}
/**
* @param $file
* @param $path
* @param $title
* @param $description
* @return mixed
*/
public function upload($title, $video, $path, $description){
$videoPath = WWW_ROOT . '../'. $path . $video;
if(!file_exists($videoPath)){
$response['status'] = 'false';
$response['message'] = 'Video does not Exists';
return $response;
}
$client = new Google_Client();
$client->setClientID($this->OAUTH2_CLIENT_ID);
$client->setClientSecret($this->OAUTH2_CLIENT_SECRET);
$client->setAccessToken($this->access_token);
$youtube = new Google_Service_YouTube($client);
try{
// REPLACE this value with the path to the file you are uploading.
$videoPath = WWW_ROOT . '../' . $path . $video;
// Create a snippet with title, description, tags and category ID
// Create an asset resource and set its snippet metadata and type.
// This example sets the video's title, description, keyword tags, and
// video category.
$snippet = new Google_Service_YouTube_VideoSnippet();
$snippet->setTitle($title);
$snippet->setDescription($description);
// Numeric video category. See
// https://developers.google.com/youtube/v3/docs/videoCategories/list
$snippet->setCategoryId("22");
// Set the video's status to "public". Valid statuses are "public",
// "private" and "unlisted".
$status = new Google_Service_YouTube_VideoStatus();
$status->privacyStatus = "private";
// Associate the snippet and status objects with a new video resource.
$video = new Google_Service_YouTube_Video();
$video->setSnippet($snippet);
$video->setStatus($status);
// Specify the size of each chunk of data, in bytes. Set a higher value for
// reliable connection as fewer chunks lead to faster uploads. Set a lower
// value for better recovery on less reliable connections.
$chunkSizeBytes = 1 * 1024 * 1024;
// Setting the defer flag to true tells the client to return a request which can be called
// with ->execute(); instead of making the API call immediately.
$client->setDefer(true);
// Create a request for the API's videos.insert method to create and upload the video.
$insertRequest = $youtube->videos->insert("status,snippet", $video);
// Create a MediaFileUpload object for resumable uploads.
$media = new Google_Http_MediaFileUpload(
$client,
$insertRequest,
'video/*',
null,
true,
$chunkSizeBytes
);
$media->setFileSize(filesize($videoPath));
// Read the media file and upload it chunk by chunk.
$status = false;
$handle = fopen($videoPath, "rb");
while (!$status && !feof($handle)) {
$chunk = fread($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk);
}
fclose($handle);
// If you want to make other calls after the file upload, set setDefer back to false
$client->setDefer(false);
}catch (Google_Service_Exception $e) {
$response['status'] = false;
$response_message = json_decode($e->getMessage());
//debug($response_message);
$response['message'] = $response_message->error->errors[0]->message;
} catch (Google_Exception $e) {
$response['status'] = false;
$response_message = json_decode($e->getMessage());
$response['message'] = $response_message->error->errors[0]->message;
}
}
}
以下是index.ctp
<?php
?>
<div class="user form large-12 medium-12 columns content">
<?= $this->Form->create(null,['type'=>'post']) ?>
<fieldset>
<legend><?= __('Upload Video')?></legend>
<?php
echo $this->Form->control('title',[
'value'=> isset($_GET['title']) ? $_GET['title'] : '',
]);
echo $this->Form->input('video',['type'=>'file'],[
'value'=> isset($_GET['video']) ? $_GET['video'] : '',
]
);
echo $this->Form->control('path',[
'value'=> isset($_GET['path']) ? $_GET['path'] : ''
]);
echo $this->Form->control('description',[
'value'=> isset($_GET['description']) ? $_GET['description'] : '',
]);
?>
</fieldset>
<?= $this->Form->button(__('Upload')) ?>
<?= $this->Form->end() ?>
</div>
您不应该手动创建控制器,因此没有理由修改控制器构造函数,尤其是考虑到您在那里所做的事情会扰乱其签名和功能,即接受所需的请求和响应对象(因此出现“未配置请求对象”错误),以及可选的名称、事件管理器和组件注册表对象。
所以,不要触及构造函数,从其他地方读取您的令牌,或者通过 setter.
注入它
此外,正如 Alimon Karim 在评论中提到的,表单助手的正确 type
选项是 file
。并且不要让用户为您的文件存储指定任意路径,这可能是一个路径遍历漏洞。
最后但同样重要的是,不要直接用 CakePHP 访问像 $_GET
这样的超全局变量,使用请求对象来检索请求数据,如果是表单助手,它应该能够为你做这件事自动(顺便说一句,设置文件输入的值是不可能的)。
另见
我正在尝试使用 CakePHP 在我的 YouTube 帐户上上传视频,我尝试了简单的 PHP 并且工作正常但是,当我将代码转换为 CakePHP 报错了,求大神指点。
Erro is : No Request object configured. Cannot invoke action
以下是UploadController.php
<?php
namespace App\Controller;
/**
*
*/
use Google_Client;
use Google_Service_YouTube;
use Google_Service_YouTube_VideoSnippet;
use Google_Service_YouTube_VideoStatus;
use Google_Service_YouTube_Video;
use Google_Http_MediaFileUpload;
use Google_Exception;
/**
*
*/
/**
*
*/
class UploadController extends AppController
{
private $access_token;
private $OAUTH2_CLIENT_ID;
private $OAUTH2_CLIENT_SECRET;
public function __construct ($access_token)
{
$this->access_token = $access_token;
$this->OAUTH2_CLIENT_ID =
'replace here';
$this->OAUTH2_CLIENT_SECRET = 'replace here';
}
public function index()
{
if($this->request->is('post')){
$title = $this->request->getData('title');
$video = $this->request->getData('video');
$path = $this->request->getData('path');
$description = $this->request->getData('description');
$results = [];
if(empty($title)){
$this->Flash->error('Title cant be empty');
}else{
if(empty($video)){
$this->Flash->error('Please select a video');
}
}
$results = $this->upload($title, $video, $path, $description);
}
$this->set(compact('title','video','path','description'));
}
/**
* @param $video_file : name of the video file to be uploaded
* @param $file_path : path directory of video file to be uploaded
* @return bool
*/
public function test($video_path, $video_file)
{
$full_path = Configure::read('video.upload.video.path') . $video_path . DS . $video_file;
if($full_path){
return $full_path;
}
return $this->access_token;
}
/**
* @param $file
* @param $path
* @param $title
* @param $description
* @return mixed
*/
public function upload($title, $video, $path, $description){
$videoPath = WWW_ROOT . '../'. $path . $video;
if(!file_exists($videoPath)){
$response['status'] = 'false';
$response['message'] = 'Video does not Exists';
return $response;
}
$client = new Google_Client();
$client->setClientID($this->OAUTH2_CLIENT_ID);
$client->setClientSecret($this->OAUTH2_CLIENT_SECRET);
$client->setAccessToken($this->access_token);
$youtube = new Google_Service_YouTube($client);
try{
// REPLACE this value with the path to the file you are uploading.
$videoPath = WWW_ROOT . '../' . $path . $video;
// Create a snippet with title, description, tags and category ID
// Create an asset resource and set its snippet metadata and type.
// This example sets the video's title, description, keyword tags, and
// video category.
$snippet = new Google_Service_YouTube_VideoSnippet();
$snippet->setTitle($title);
$snippet->setDescription($description);
// Numeric video category. See
// https://developers.google.com/youtube/v3/docs/videoCategories/list
$snippet->setCategoryId("22");
// Set the video's status to "public". Valid statuses are "public",
// "private" and "unlisted".
$status = new Google_Service_YouTube_VideoStatus();
$status->privacyStatus = "private";
// Associate the snippet and status objects with a new video resource.
$video = new Google_Service_YouTube_Video();
$video->setSnippet($snippet);
$video->setStatus($status);
// Specify the size of each chunk of data, in bytes. Set a higher value for
// reliable connection as fewer chunks lead to faster uploads. Set a lower
// value for better recovery on less reliable connections.
$chunkSizeBytes = 1 * 1024 * 1024;
// Setting the defer flag to true tells the client to return a request which can be called
// with ->execute(); instead of making the API call immediately.
$client->setDefer(true);
// Create a request for the API's videos.insert method to create and upload the video.
$insertRequest = $youtube->videos->insert("status,snippet", $video);
// Create a MediaFileUpload object for resumable uploads.
$media = new Google_Http_MediaFileUpload(
$client,
$insertRequest,
'video/*',
null,
true,
$chunkSizeBytes
);
$media->setFileSize(filesize($videoPath));
// Read the media file and upload it chunk by chunk.
$status = false;
$handle = fopen($videoPath, "rb");
while (!$status && !feof($handle)) {
$chunk = fread($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk);
}
fclose($handle);
// If you want to make other calls after the file upload, set setDefer back to false
$client->setDefer(false);
}catch (Google_Service_Exception $e) {
$response['status'] = false;
$response_message = json_decode($e->getMessage());
//debug($response_message);
$response['message'] = $response_message->error->errors[0]->message;
} catch (Google_Exception $e) {
$response['status'] = false;
$response_message = json_decode($e->getMessage());
$response['message'] = $response_message->error->errors[0]->message;
}
}
}
以下是index.ctp
<?php
?>
<div class="user form large-12 medium-12 columns content">
<?= $this->Form->create(null,['type'=>'post']) ?>
<fieldset>
<legend><?= __('Upload Video')?></legend>
<?php
echo $this->Form->control('title',[
'value'=> isset($_GET['title']) ? $_GET['title'] : '',
]);
echo $this->Form->input('video',['type'=>'file'],[
'value'=> isset($_GET['video']) ? $_GET['video'] : '',
]
);
echo $this->Form->control('path',[
'value'=> isset($_GET['path']) ? $_GET['path'] : ''
]);
echo $this->Form->control('description',[
'value'=> isset($_GET['description']) ? $_GET['description'] : '',
]);
?>
</fieldset>
<?= $this->Form->button(__('Upload')) ?>
<?= $this->Form->end() ?>
</div>
您不应该手动创建控制器,因此没有理由修改控制器构造函数,尤其是考虑到您在那里所做的事情会扰乱其签名和功能,即接受所需的请求和响应对象(因此出现“未配置请求对象”错误),以及可选的名称、事件管理器和组件注册表对象。
所以,不要触及构造函数,从其他地方读取您的令牌,或者通过 setter.
注入它此外,正如 Alimon Karim 在评论中提到的,表单助手的正确 type
选项是 file
。并且不要让用户为您的文件存储指定任意路径,这可能是一个路径遍历漏洞。
最后但同样重要的是,不要直接用 CakePHP 访问像 $_GET
这样的超全局变量,使用请求对象来检索请求数据,如果是表单助手,它应该能够为你做这件事自动(顺便说一句,设置文件输入的值是不可能的)。
另见