Компонент для расширенной работы с ВК API в YII2. Загрузка изображений, распознавание капчи, постановка очередей и многое другое.
Сайт с подробным описанием yii2 api vk GitHub
Предпочтительный способ установить это расширение через composer.
Либо запустить
php composer.phar require --prefer-dist jumper423/yii2-vk "*"
или добавить
"jumper423/yii2-vk": "*"
в файл composer.json
.
'components' => [
'vk' => [
'class' => 'jumper423\VK',
'clientId' => '11111',
'clientSecret' => 'n9wsv98svSD867SA7dsda87',
'delay' => 0.7, // Минимальная задержка между запросами
'delayExecute' => 120, // Задержка между группами инструкций в очереди
'limitExecute' => 1, // Количество инструкций на одно выполнении в очереди
'captcha' => 'captcha', // Компонент по распознованию капчи
],
],
'aliases' => [
'@actions' => '@backend/runtime/cron', // Папка куда будут складироваться очереди для cron-а
],
"Расшиненая" конфигурация
'components' => [
'captcha' => [
'class' => 'jumper423\Captcha',
'pathTmp' => '@imagescache/captcha',
'apiKey' => '42eab4119020dbc729f657',
],
'authClientCollection' => [
'class' => 'yii\authclient\Collection',
'clients' => [
'vkontakte' => [
'class' => 'jumper423\VK',
'clientId' => '11111',
'clientSecret' => 'n9wsv98svSD867SA7dsda87',
'delay' => 0.7,
'delayExecute' => 120,
'limitExecute' => 1,
'captcha' => 'captcha',
'scope' => 'friends,photos,pages,wall,groups,email,stats,ads,offline,notifications', //,messages,nohttps
'title' => 'ВКонтакте'
],
],
],
],
'aliases' => [
'@actions' => '@backend/runtime/cron', // Папка куда будут складироваться очереди для cron-а
],
Вызов следовательно
/**
* @var jumper423\VK $vk
*/
$vk = Yii::$app->vk;
или
$vk = Yii::$app->authClientCollection->getClient('vkontakte');
Создание альбома
$response = $vk->post('photos.createAlbum', ['group_id' => $groupId, 'title' => $title, 'upload_by_admins_only' => 1]);
Добавление инструкции в очередь
foreach ($images as $image) {
$vk->addAction('photos.edit', ['caption' => $caption, 'owner_id' => $ownerId, 'photo_id' => $image,]);
}
// Добавление в cron
$vk->addActionsInCron('photos.edit');
// Или начать выполнение очереди командой
// $vk->performAnAction();
Выполнение cron-а
$vk->performAnActionFromCron('photos.edit');
Загрузка изображения в альбом пользователя или группы
$imageId = $vk->loadImage($imagePath, $albumId, $groupId);
<?php
namespace jumper423;
use Yii;
use yii\authclient\clients\VKontakte;
use yii\base\Exception;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;
class VK extends VKontakte
{
public $delay = 0.7;
public $delayExecute = 120;
public $limitExecute = 1;
/**
* @var null|string|Captcha
*/
public $captcha = 'captcha';
private $lastRequest = null;
private $sleepRandMin = 0;
private $sleepRandMax = 500;
private $execute = [];
const MILLISECOND = 1000;
/**
* @inheritdoc
*/
public function __construct($config = [])
{
parent::__construct($config);
if (is_string($this->captcha)) {
if (Yii::$app->has($this->captcha) && Yii::$app->get($this->captcha) instanceof CaptchaInterface) {
$this->captcha = Yii::$app->get($this->captcha);
} else {
$this->captcha = null;
}
} elseif (is_object($this->captcha)) {
if (!($this->captcha instanceof CaptchaInterface)) {
$this->captcha = null;
}
} else {
$this->captcha = null;
}
}
/**
* @param bool|false $delay
*/
private function sleep($delay = false)
{
if ($delay === false) {
$delay = $this->delay;
}
if ($this->lastRequest === null) {
$this->lastRequest = microtime(true);
} else {
$microtime = microtime(true);
if ($this->lastRequest + $delay > $microtime) {
sleep($this->lastRequest + $delay - $microtime);
$this->lastRequest = microtime(true);
}
}
sleep(rand($this->sleepRandMin, $this->sleepRandMax) / self::MILLISECOND);
}
/**
* @inheritdoc
*/
public function api($apiSubUrl, $method = 'GET', array $params = [], array $headers = [], $delay = false)
{
$this->sleep($delay);
$response = parent::api($apiSubUrl, $method, $params, $headers);
if (ArrayHelper::getValue($response, 'error.error_code') == 14 && $this->captcha) {
if ($this->captcha->run(ArrayHelper::getValue($response, 'error.captcha_img'))) {
$response = $this->api($apiSubUrl, $method, ArrayHelper::merge($params,
[
'captcha_sid' => ArrayHelper::getValue($response, 'error.captcha_sid'),
'captcha_key' => $this->captcha->result()
])
, $headers);
} else {
throw new Exception($this->captcha->error());
}
} elseif (ArrayHelper::getValue($response, 'error')) {
throw new Exception(ArrayHelper::getValue($response, 'error.error_msg'), ArrayHelper::getValue($response, 'error.error_code'));
}
return $response;
}
/**
* @param $apiSubUrl
* @param array $params
* @param array $headers
* @param bool|false $delay
* @return array
* @throws Exception
*/
public function post($apiSubUrl, array $params = [], array $headers = [], $delay = false)
{
return $this->api($apiSubUrl, 'POST', $params, $headers, $delay);
}
/**
* @param $apiSubUrl
* @param array $params
* @param array $headers
* @param bool|false $delay
* @return array
* @throws Exception
*/
public function get($apiSubUrl, array $params = [], array $headers = [], $delay = false)
{
return $this->api($apiSubUrl, 'GET', $params, $headers, $delay);
}
/**
* @param $apiSubUrl
* @param array $params
*/
public function addAction($apiSubUrl, array $params = [])
{
$this->execute[] = "API.{$apiSubUrl}(" . Json::encode($params) . ")";
}
/**
* @param $method
*/
public function addActionsInCron($method)
{
$json = Json::decode(file_get_contents(Yii::getAlias("@actions/{$method}.json")));
$json = ArrayHelper::merge($json, $this->execute);
file_put_contents(Yii::getAlias("@actions/{$method}.json"), Json::encode($json));
}
/**
* @param $method
* @return array
*/
public function performAnActionFromCron($method)
{
$response = [];
do {
$execute = Json::decode(file_get_contents(Yii::getAlias("@actions/{$method}.json")));
if (count($execute)) {
$executeRow = array_shift($execute);
$response = ArrayHelper::merge($response, $this->post('execute', ['code' => "return \n [" . $executeRow . "];"]));
$execute = Json::decode(file_get_contents(Yii::getAlias("@actions/{$method}.json")));
$r = array_search($executeRow, $execute);
if ($r !== false) {
unset($execute[$r]);
file_put_contents(Yii::getAlias("@actions/{$method}.json"), Json::encode($execute));
}
sleep($this->delayExecute);
} else {
break;
}
} while (true);
return $response;
}
/**
* @return array
*/
public function performAnAction()
{
$executeCount = count($this->execute);
$response = [];
for ($i = 0; $executeCount > $i; $i += $this->limitExecute) {
$response = ArrayHelper::merge($response, $this->post('execute', ['code' => "return \n [" . implode(",\n", array_slice($this->execute, $i, $this->limitExecute)) . "];"]));
sleep($this->delayExecute);
}
$this->execute = [];
return $response;
}
/**
* @param $imagePath
* @param $albumId
* @param null|int $groupId
* @return int
* @throws Exception
*/
public function loadImage($imagePath, $albumId, $groupId = null)
{
$params = ['album_id' => $albumId];
if ($groupId) {
$params['group_id'] = $groupId;
}
$request = $this->post('photos.getUploadServer', $params);
$uploadUrl = ArrayHelper::getValue($request, 'response.upload_url');
if ($uploadUrl) {
$ch = curl_init($uploadUrl);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'file1' => "@" . $imagePath
]);
$paramsSave = Json::decode(curl_exec($ch));
curl_close($ch);
if (count($paramsSave)) {
return ArrayHelper::getValue($this->post('photos.save', $paramsSave), 'response.0.pid');
} else {
throw new Exception('Empty params save');
}
} else {
throw new Exception('Not upload_url');
}
}
/**
* @inheritdoc
*/
protected function initUserAttributes()
{
$response = $this->api('users.get.json', 'GET', [
'fields' => implode(',', $this->attributeNames),
]);
$attributes = array_shift($response['response']);
$accessToken = $this->getAccessToken();
if (is_object($accessToken)) {
$accessTokenParams = $accessToken->getParams();
$attributes = array_merge($accessTokenParams, $attributes);
}
return $attributes;
}
}
Чтобы увидеть комментарии, нужно быть участником сообщества
Регистрация