How to upload excel file to google drive in Yii2

Hi, I am using Yii2 basic. I want to upload an excel file to google drive. How to do it. I am refering the link on youtube PHP Google Drive API | List, Create Folders, Sub Folders and Upload Files - YouTube. Based on this link can any one guide me where should I create the google-drive.php file

I have following code in google-drive.php file. I have stored this files in views/ascteacherreport/

<?php

function getClient()
{
    $client = new Google_Client();

    $client->setApplicationName('Google Drive API PHP Quickstart');
    $client->setRedirectUri('http://localhost/test-examples/php/google-drive-api/oauth2callback.php');

    $client->setScopes(Google_Service_Drive::DRIVE_METADATA_READONLY);
    $client->setAuthConfig('credentials.json');
    $client->setAccessType('offline');
    $client->setPrompt('select_account consent');

    // Load previously authorized token from a file, if it exists.
    // The file token.json stores the user's access and refresh tokens, and is
    // created automatically when the authorization flow completes for the first
    // time.
    $tokenPath = 'token.json';
    if (file_exists($tokenPath)) {
        $accessToken = json_decode(file_get_contents($tokenPath), true);
        $client->setAccessToken($accessToken);
    }

    // If there is no previous token or it's expired.
    if ($client->isAccessTokenExpired()) {
        // Refresh the token if possible, else fetch a new one.
        if ($client->getRefreshToken()) {
            $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
        } else {
            // Request authorization from the user.
            $authUrl = $client->createAuthUrl();
            printf("Open the following link in your browser:\n%s\n", $authUrl);
            print 'Enter verification code: ';
            $authCode = trim(fgets(STDIN));

            // Exchange authorization code for an access token.
            $accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
            $client->setAccessToken($accessToken);

            // Check to see if there was an error.
            if (array_key_exists('error', $accessToken)) {
                throw new Exception(join(', ', $accessToken));
            }
        }
        // Save the token to a file.
        if (!file_exists(dirname($tokenPath))) {
            mkdir(dirname($tokenPath), 0700, true);
        }
        file_put_contents($tokenPath, json_encode($client->getAccessToken()));
    }
    return $client;
}

// Get the API client and construct the service object.
$client = getClient();

Now when I open command prompt and try to do php google-drive.php from views/ascteacherreport then it gives the error as

Uncaught error : class Google_Client not found in 


F:\xampp\htdocs\lwa\basic\views\ascteacherreport>php .\google-drive.php
PHP Warning:  Module 'openssl' already loaded in Unknown on line 0
Warning: Module 'openssl' already loaded in Unknown on line 0
PHP Fatal error:  Uncaught Error: Class 'Google_Client' not found in 

Which name space should I use?

Thanks

You need to load the Google Drive PHP SDK via composer

composer require google/apiclient:^2.0

Then initialize the Google Client:

$client = new Google\Client();

For more reading:

Hi

I have installed the plugin througu the composer. It got installed and working fine.
I have file called google-drive.php which contains all Google client api codes. Similarly I have form.php where there is a code to generate the file upload window for user to select a file to upload. Another php file where code is there to upload a file to google drive. It iw working. I also have a folder where the file is uploaded first to local folder and then to google drive folder. Now in Yii2 where should I arrange or keep all these files because now I have kept all these files in basic folder. I have installed the google client api through composer. If I move the google-drive.php any where and use the required statement to include the autoload then error generates. So I have kept google-drive.php before vendor directory and also all other files before vendor directory and in basic directory. Where should I place or keep all these files in order to perform efficiently. Should I use a model, controller for this

Yii2 is an MVC framework.

Your file uploading logic can be in a Model file, e.g app\models\GoogleDriveUpload.php

Your form.php will be in a view file, e.g form.php, this will be inside the views folder

The code to access the form view will be in a controller file, e.g app\controllers\GoogleDriveUploadController.php

I hope you know the basis of Yii2?

1 Like

Yes I have created a model called Upload, controller called UploadController and view called upload.

Upload Model

<?php

namespace app\models;

use Yii;
include __DIR__ . '/vendor/autoload.php';
use yii\helpers\ArrayHelper;

class Upload extends \yii\base\Model
{
	public $filepath;

    public function rules()
    {
        return [
			[['filepath'],'required'],
			[['filepath'], 'file', 'extensions' => 'xlsx'],

        ];
    }
	public function attributeLabels()
    {
        return [
            'filepath' => 'File',

        ];
    }


function getClient()
{
    $client = new Google_Client();

    $client->setApplicationName('Google Drive API PHP Quickstart');
    $client->setRedirectUri('http://localhost/lwa/basic/web');

    $client->setScopes(Google_Service_Drive::DRIVE);

    $client->setAuthConfig('credentials.json');
    $client->setAccessType('offline');
    $client->setPrompt('select_account consent');

    // Load previously authorized token from a file, if it exists.
    // The file token.json stores the user's access and refresh tokens, and is
    // created automatically when the authorization flow completes for the first
    // time.
    $tokenPath = 'token.json';
    if (file_exists($tokenPath)) {
        $accessToken = json_decode(file_get_contents($tokenPath), true);
        $client->setAccessToken($accessToken);
    }

    // If there is no previous token or it's expired.
    if ($client->isAccessTokenExpired()) {
        // Refresh the token if possible, else fetch a new one.
        if ($client->getRefreshToken()) {
            $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
        } else {
            // Request authorization from the user.
            $authUrl = $client->createAuthUrl();
            printf("Open the following link in your browser:\n%s\n", $authUrl);
            print 'Enter verification code: ';
            $authCode = trim(fgets(STDIN));

            // Exchange authorization code for an access token.
            $accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
            $client->setAccessToken($accessToken);

            // Check to see if there was an error.
            if (array_key_exists('error', $accessToken)) {
                throw new Exception(join(', ', $accessToken));
            }
        }
        // Save the token to a file.
        if (!file_exists(dirname($tokenPath))) {
            mkdir(dirname($tokenPath), 0700, true);
        }
        file_put_contents($tokenPath, json_encode($client->getAccessToken()));
    }
    return $client;


// Get the API client and construct the service object.
$client = getClient();
}

}

Upload Controller

<?php

namespace app\controllers;

use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\filters\VerbFilter;
use app\models\Upload;

error_reporting(E_ERROR | E_PARSE);
use yii\web\ForbiddenHttpException;


class UploadController extends Controller
{
    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
			'access' => [
			'class' => \yii\filters\AccessControl::className(),
			'only' => ['index'],
			'rules' => [

          // allow all actions to Admin role users
			[
				  'allow' => true,
				  'actions' => ['index','result','records'],
				  'roles' => ['@'],
			],




			],
       ],

            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'logout' => ['post'],
                ],
            ],
        ];
    }

    /**
     * @inheritdoc
     */
    public function actions()
    {
        return [
            'error' => [
                'class' => 'yii\web\ErrorAction',
            ],
            'captcha' => [
                'class' => 'yii\captcha\CaptchaAction',
                'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
            ],
        ];
    }

    public function actionIndex()
    {

		return $this->render('index');

    }
	 public function actionCreate()
    {

		$model = new Upload();

        if ($model->load(Yii::$app->request->post())) {




  
}

            //return $this->redirect(['view', 'id' => $model->ASCId]);


        else{
			return $this->render('create', [
            'model' => $model,
        ]);
		}


    }

}

So how shall I call or use this getClient function of Upload Model in the Upload controller

Kindly go through the Yii2 guide Getting Started: Saying Hello | The Definitive Guide to Yii 2.0 | Yii PHP Framework

This is controller code. It goes in the controller.

However, when your program starts to get quite complicated like this, then the controller isn’t really the right place either. When you find that your code has many functions and a lot of re-usable actions it is better to create a “Component”.

Then in your controller, you create an instance of your component. You can then call all of the functions in your component. This keeps your Controller code simple and allows you to re-use your component in multiple controllers.

Components let you write your own classes that implement the Google API. Your “getClient” function can then be used in any controller.

I have created a component class called Upload. Following is the component upload in comppnents directory inside basic directory.

<?php

namespace app\components;
include __DIR__ . '/vendor/autoload.php';

use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;

class Upload extends Component
{
	public $client;
public function getClient()
{
    $client = new Google_Client();

    $client->setApplicationName('Google Drive API PHP Quickstart');
    $client->setRedirectUri('http://localhost/lwa/basic/web');

    $client->setScopes(Google_Service_Drive::DRIVE);

    $client->setAuthConfig('credentials.json');
    $client->setAccessType('offline');
    $client->setPrompt('select_account consent');

    // Load previously authorized token from a file, if it exists.
    // The file token.json stores the user's access and refresh tokens, and is
    // created automatically when the authorization flow completes for the first
    // time.
    $tokenPath = 'token.json';
    if (file_exists($tokenPath)) {
        $accessToken = json_decode(file_get_contents($tokenPath), true);
        $client->setAccessToken($accessToken);
    }

    // If there is no previous token or it's expired.
    if ($client->isAccessTokenExpired()) {
        // Refresh the token if possible, else fetch a new one.
        if ($client->getRefreshToken()) {
            $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
        } else {
            // Request authorization from the user.
            $authUrl = $client->createAuthUrl();
            printf("Open the following link in your browser:\n%s\n", $authUrl);
            print 'Enter verification code: ';
            $authCode = trim(fgets(STDIN));

            // Exchange authorization code for an access token.
            $accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
            $client->setAccessToken($accessToken);

            // Check to see if there was an error.
            if (array_key_exists('error', $accessToken)) {
                throw new Exception(join(', ', $accessToken));
            }
        }
        // Save the token to a file.
        if (!file_exists(dirname($tokenPath))) {
            mkdir(dirname($tokenPath), 0700, true);
        }
        file_put_contents($tokenPath, json_encode($client->getAccessToken()));
    }
    return $client;
}

// Get the API client and construct the service object.
$client = getClient();

}

Now what should I do?

I have modified the controller as

<?php

namespace app\controllers;

use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\filters\VerbFilter;
use app\models\UploadExcel;

error_reporting(E_ERROR | E_PARSE);
use app\components\Upload;
use yii\web\ForbiddenHttpException;
use Google_Client;
use Google_Service_Drive;

class UploadExcelController extends Controller
{
    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
			'access' => [
			'class' => \yii\filters\AccessControl::className(),
			'only' => ['index','create'],
			'rules' => [

          // allow all actions to Admin role users
			[
				  'allow' => true,
				  'actions' => ['index','create'],
				  'roles' => ['@'],
			],




			],
       ],

            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'logout' => ['post'],
                ],
            ],
        ];
    }

    /**
     * @inheritdoc
     */
    public function actions()
    {
        return [
            'error' => [
                'class' => 'yii\web\ErrorAction',
            ],
            'captcha' => [
                'class' => 'yii\captcha\CaptchaAction',
                'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
            ],
        ];
    }

    public function actionIndex()
    {

		return $this->render('index');

    }
	 public function actionCreate()
    {

		$model = new UploadExcel();

        if ($model->load(Yii::$app->request->post())) {


    $file_tmp  = $_FILES["file"]["tmp_name"];
    $file_type = $_FILES["file"]["type"];
    $file_name = basename($_FILES["file"]["name"]);
    $path = "uploads/".$file_name;

    move_uploaded_file($file_tmp, $path);


	function check_folder_exists( $folder_name ){

    $service = new Google_Service_Drive($GLOBALS['client']);

    $parameters['q'] = "mimeType='application/vnd.google-apps.folder' and name='$folder_name' and trashed=false";
    $files = $service->files->listFiles($parameters);

    $op = [];
    foreach( $files as $k => $file ){
        $op[] = $file;
    }

    return $op;
}


	function create_folder( $folder_name, $parent_folder_id=null ){

    $folder_list = check_folder_exists( $folder_name );

    // if folder does not exists
    if( count( $folder_list ) == 0 ){
        $service = new Google_Service_Drive( $GLOBALS['client'] );
        $folder = new Google_Service_Drive_DriveFile();

        $folder->setName( $folder_name );
        $folder->setMimeType('application/vnd.google-apps.folder');
        if( !empty( $parent_folder_id ) ){
            $folder->setParents( [ $parent_folder_id ] );
        }

        $result = $service->files->create( $folder );

        $folder_id = null;

        if( isset( $result['id'] ) && !empty( $result['id'] ) ){
            $folder_id = $result['id'];
        }

        return $folder_id;
    }

    return $folder_list[0]['id'];

}


    $folder_id = create_folder( "excel1" );


	function insert_file_to_drive( $file_path, $file_name, $parent_file_id = null ){
    $service = new Google_Service_Drive( $GLOBALS['client'] );
    $file = new Google_Service_Drive_DriveFile();

    $file->setName( $file_name );

    if( !empty( $parent_file_id ) ){
        $file->setParents( [ $parent_file_id ] );
    }

    $result = $service->files->create(
        $file,
        array(
            'data' => file_get_contents($file_path),
            'mimeType' => 'application/octet-stream',
        )
    );

    $is_success = false;

    if( isset( $result['name'] ) && !empty( $result['name'] ) ){
        $is_success = true;
    }

    return $is_success;
}

    $success = insert_file_to_drive( $path , $file_name, $folder_id);

    if( $success ){
        echo "file uploaded successfully";
    } else {
        echo "Something went wrong.";
    }



function dd( ...$d ){
    echo "<pre style='background-color:#000;color:#fff;' >";
    print_r($d);
    exit;
}



}

            //return $this->redirect(['view', 'id' => $model->ASCId]);


        else{
			return $this->render('create', [
            'model' => $model,
        ]);
		}


    }

}

Now when I run the program it gives me error as,

## Argument 1 passed to Google_Service::__construct() must be an instance of Google_Client, null given, called in F:\xampp\htdocs\basic\vendor\google\apiclient-services\src\Drive.php on line 83