vipin
vipin

Reputation: 2510

Error while importing Quickbook library in Laravel 5.3

I am integrating quickbooks with my laravel app. After integration I got this error,

PHP Warning: require_once(../QuickBooks.php): failed to open stream: No such file or directory in /home/vipin/projects/development/Quickbook/config/app.php on line 2 PHP Fatal error: require_once(): Failed opening required '../QuickBooks.php' (include_path='.:/usr/share/php:/home/ubuntu/projects/development/Quickbook/vendor/consolibyte/quickbooks') in /home/ubuntu/projects/development/Quickbook/config/app.php on line 2

Here is my controller Quickbook.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
// require_once '../QuickBooks.php';

use App\Http\Requests;

class QuickBooksController extends Controller
{
private $IntuitAnywhere;
private $context;
private $realm;

public function __construct(){
  if (!\QuickBooks_Utilities::initialized(env('QBO_DSN'))) {
      // Initialize creates the neccessary database schema for queueing up requests and logging
      \QuickBooks_Utilities::initialize(env('QBO_DSN'));
  }
  $this->IntuitAnywhere = new \QuickBooks_IPP_IntuitAnywhere(env('QBO_DSN'), env('QBO_ENCRYPTION_KEY'), env('QBO_OAUTH_CONSUMER_KEY'), env('QBO_CONSUMER_SECRET'), env('QBO_OAUTH_URL'), env('QBO_SUCCESS_URL'));
}

public function  qboConnect(){
  if ($this->IntuitAnywhere->check(env('QBO_USERNAME'), env('QBO_TENANT')) && $this->IntuitAnywhere->test(env('QBO_USERNAME'), env('QBO_TENANT'))) {
      // Set up the IPP instance
      $IPP = new \QuickBooks_IPP(env('QBO_DSN'));
      // Get our OAuth credentials from the database
      $creds = $this->IntuitAnywhere->load(env('QBO_USERNAME'), env('QBO_TENANT'));
      // Tell the framework to load some data from the OAuth store
      $IPP->authMode(
          \QuickBooks_IPP::AUTHMODE_OAUTH,
          env('QBO_USERNAME'),
          $creds);

      if (env('QBO_SANDBOX')) {
          // Turn on sandbox mode/URLs
          $IPP->sandbox(true);
      }
      // This is our current realm
      $this->realm = $creds['qb_realm'];
      // Load the OAuth information from the database
      $this->context = $IPP->context();

      return true;
  } else {
      return false;
  }
}

public function qboOauth(){
  if ($this->IntuitAnywhere->handle(env('QBO_USERNAME'), env('QBO_TENANT')))
  {
      ; // The user has been connected, and will be redirected to QBO_SUCCESS_URL automatically.
  }
  else
  {
      // If this happens, something went wrong with the OAuth handshake
      die('Oh no, something bad happened: ' . $this->IntuitAnywhere->errorNumber() . ': ' . $this->IntuitAnywhere->errorMessage());
  }
}

public function qboSuccess(){
  return view('qbo_success');
}

public function qboDisconnect(){
  $this->IntuitAnywhere->disconnect(env('QBO_USERNAME'), env('QBO_TENANT'),true);
  return redirect()->intended("/yourpath");// afer disconnect redirect where you want

}

public function createCustomer(){

  $CustomerService = new \QuickBooks_IPP_Service_Customer();

  $Customer = new \QuickBooks_IPP_Object_Customer();
  $Customer->setTitle('Ms');
$Customer->setGivenName('Shannon');
$Customer->setMiddleName('B');
$Customer->setFamilyName('Palmer');
$Customer->setDisplayName('Shannon B Palmer ' . mt_rand(0, 1000));
  // Terms (e.g. Net 30, etc.)
  $Customer->setSalesTermRef(4);

  // Phone #
  $PrimaryPhone = new \QuickBooks_IPP_Object_PrimaryPhone();
  $PrimaryPhone->setFreeFormNumber('860-532-0089');
$Customer->setPrimaryPhone($PrimaryPhone);

  // Mobile #
  $Mobile = new \QuickBooks_IPP_Object_Mobile();
  $Mobile->setFreeFormNumber('860-532-0089');
$Customer->setMobile($Mobile);

  // Fax #
  $Fax = new \QuickBooks_IPP_Object_Fax();
  $Fax->setFreeFormNumber('860-532-0089');
$Customer->setFax($Fax);

  // Bill address
  $BillAddr = new \QuickBooks_IPP_Object_BillAddr();
  $BillAddr->setLine1('72 E Blue Grass Road');
$BillAddr->setLine2('Suite D');
$BillAddr->setCity('Mt Pleasant');
$BillAddr->setCountrySubDivisionCode('MI');
$BillAddr->setPostalCode('48858');
$Customer->setBillAddr($BillAddr);

  // Email
  $PrimaryEmailAddr = new \QuickBooks_IPP_Object_PrimaryEmailAddr();
  $PrimaryEmailAddr->setAddress('[email protected]');
  $Customer->setPrimaryEmailAddr($PrimaryEmailAddr);

  if ($resp = $CustomerService->add($this->context, $this->realm, $Customer))
  {
      //print('Our new customer ID is: [' . $resp . '] (name "' . $Customer->getDisplayName() . '")');
      //return $resp;
      //echo $resp;exit;
      //$resp = str_replace('{','',$resp);
      //$resp = str_replace('}','',$resp);
      //$resp = abs($resp);
      return $this->getId($resp);
  }
  else
  {
      //echo 'Not Added qbo';
      print($CustomerService->lastError($this->context));
  }
}

public function addItem(){
  $ItemService = new \QuickBooks_IPP_Service_Item();

  $Item = new \QuickBooks_IPP_Object_Item();

  $Item->setName('My Item');
$Item->setType('Inventory');
$Item->setIncomeAccountRef('53');

  if ($resp = $ItemService->add($this->context, $this->realm, $Item))
  {
      return $this->getId($resp);
  }
  else
  {
      print($ItemService->lastError($this->context));
  }
}

public function addInvoice($invoiceArray,$itemArray,$customerRef){

  $InvoiceService = new \QuickBooks_IPP_Service_Invoice();

  $Invoice = new \QuickBooks_IPP_Object_Invoice();

  $Invoice = new QuickBooks_IPP_Object_Invoice();

$Invoice->setDocNumber('WEB' . mt_rand(0, 10000));
$Invoice->setTxnDate('2013-10-11');

$Line = new QuickBooks_IPP_Object_Line();
$Line->setDetailType('SalesItemLineDetail');
$Line->setAmount(12.95 * 2);
$Line->setDescription('Test description goes here.');

$SalesItemLineDetail = new QuickBooks_IPP_Object_SalesItemLineDetail();
$SalesItemLineDetail->setItemRef('8');
$SalesItemLineDetail->setUnitPrice(12.95);
$SalesItemLineDetail->setQty(2);

$Line->addSalesItemLineDetail($SalesItemLineDetail);

$Invoice->addLine($Line);

$Invoice->setCustomerRef('67');


  if ($resp = $InvoiceService->add($this->context, $this->realm, $Invoice))
  {
      return $this->getId($resp);
  }
  else
  {
      print($InvoiceService->lastError());
  }
}

public function getId($resp){
  $resp = str_replace('{','',$resp);
  $resp = str_replace('}','',$resp);
  $resp = abs($resp);
  return $resp;
}

}

Config/app.php

<?php
require_once '../QuickBooks.php';

return [


    'qbo_token' => env('QUICKBOOK_TOKEN'),
    'qbo_consumer_key' => env('QBO_OAUTH_CONSUMER_KEY'),
    'qbo_consumer_secret' => env('QBO_CONSUMER_SECRET'),
    'qbo_sandbox' => env('QBO_SANDBOX'),
    'qbo_encryption_key' => env('QBO_ENCRYPTION_KEY'),
    'qbo_username' => env('QBO_USERNAME'),
    'qbo_tenant' => env('QBO_TENANT'),
    'qbo_auth_url' => 'http://app.localhost:8000/qbo/oauth',
    'qbo_success_url' => 'http://app.localhost:8000/qbo/success',
    'qbo_mysql_connection' => 'mysqli://'. env('DB_USERNAME') .':'. env('DB_PASSWORD') .'@'. env('DB_HOST') .'/'. env('DB_DATABASE'),

Upvotes: 1

Views: 880

Answers (3)

abhishek kumar
abhishek kumar

Reputation: 466

Add this line in footer of Config/app.php

require_once '../QuickBooks.php';

Upvotes: 0

Leith
Leith

Reputation: 3299

There are several areas to improve on here with the given code & approach.

  1. As Anton correctly points out, you should not be directly requiring any of the quickbooks library files. If you've loaded this in via Composer then they will be automatically loaded because the Composer autoloader will load the QuickBooks file from the vendor. This is correct for Laravel as well as general Composer-based applications - the only difference with Laravel is that there isn't a specific Laravel Package ServiceProvider that's been written for this SDK, but that doesn't matter.
  2. The QuickBooks library tries to jump on top of autoloading any class that starts with 'QuickBooks', so you're better off making a QuickBooks folder for your controller class. This is more of a 'gotcha' and has been pointed out in the repo issues.
  3. The reason you're getting the Driver/.php error is because you have not specified your QBO_DSN, or have done so incorrectly - this DSN environment variable that you're passing to the initialisation is being run through parse_url() in the SDK code, coming up false or null and breaking the auto-loader for initalisation. If this was set to a proper connection string (e.g. mysqli://username:password@host:port/database and note that port must be a number or it's considered malformed), it would correctly process the DSN and continue to load the page. Be aware that initialisation will attempt to parse and fetch the network address of the host, so you can't just put a dummy value in there and expect it to work - this needs to exist first.
  4. You're mixing your environment variables and application configuration, without using either of them properly. If you wanted your DB connection string (a.k.a. QBO_DSN) to be constructed a particular way into the application configuration setting qbo_mysql_connection, then you should be using the configuration setting when trying to initialise/load/etc. Instead of using env('QBO_DSN'), you should be using config('app.qbo_mysql_connection') to load the constructed version from your app settings. Typically you would not be loading so many environment variables into a controller at all - that should be handled by the application, and then the controller calling the application configuration so it's agnostic of how they were defined.
  5. You shouldn't need to require anything from inside the app configuration file either - that file is just for configuration variables being set up.
  6. Since the QuickBooks SDK isn't properly namespaced (yet), there isn't a nice PSR-4 way of loading (and use-ing) the classes, but it's still good practice to use use clauses at the top of the file (e.g. use QuickBooks_Utilities;) so that you can use the classes without fear of forgetting the preceding backslash (i.e. no more \QuickBooks_Utilities, just QuickBooks_Utilities in usage) - there are several instances in the given code where this has been forgotten, and will not work because the Laravel application is namespaced and will look for those classes in the App\Http\Controllers namespace (e.g. errors like "Cannot find class App\Http\Controllers\QuickBooks_Utilities").
  7. Indentation - pick a style (e.g. tabs, 2-space, PSR-2, etc) and then stick to it. Run phpcs or some other clean-up tool over all of your code before committing to your repository or posting on SO - readability is important!

Upvotes: 0

kopaty4
kopaty4

Reputation: 2296

Using require instead of autoloader is a bad practice in modern frameworks (and generally in modern PHP). I highly recommend using the package manager (eg composer) to properly add modules to the project.

For example, to add a quickbooks library into the project using composer, you need to run only one command:

composer require consolibyte/quickbooks

Upvotes: 0

Related Questions