PHP Use Keyword Namespace Not Finding Class - php

Weirdness. Any ideas why it can't find the class?
Directory Tree:
test2.php
- src
- Google
- Spreadsheet
DefaultServiceRequest.php
ServiceRequestInterface.php
Google_Client.php
...
test2.php:
namespace src\Google\Spreadsheet;
require_once 'src/Google/Spreadsheet/ServiceRequestInterface.php';
require_once 'src/Google/Spreadsheet/DefaultServiceRequest.php';
require_once 'src/Google/Spreadsheet/Google_Client.php';
use Google\Spreadsheet\ServiceRequestInterface;
use Google\Spreadsheet\DefaultServiceRequest;
use Google\Spreadsheet\ServiceRequestFactory;
function getGoogleTokenFromKeyFile($clientId, $clientEmail, $pathToP12File) {
require 'src/Google/Spreadsheet/Google_Client.php';
$client = new Google_Client();
$client->setClientId($clientId);
$cred = new Google_Auth_AssertionCredentials(
$clientEmail,
array('https://spreadsheets.google.com/feeds'),
file_get_contents($pathToP12File)
);
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$service_token = json_decode($client->getAccessToken());
return $service_token->access_token;
}
$serviceRequest = new DefaultServiceRequest(getGoogleTokenFromKeyFile(..., ..., ...));
ServiceRequestFactory::setInstance($serviceRequest);
Not sure if this is Google API related or what. Something weird is the ServiceRequest classes wouldn't work until I required them. When I didn't, it said it couldn't find it... And when I tried adding src/ to the use path, didn't work, and I tried removing the path all together, all did nothing.
Error: Fatal error: Class 'src\Google\Spreadsheet\Google_Client' not found in test2.php on line 15

looks like you are using this library
if you used composer to install the library you need to include the vendor/autoload.php file in your code
require 'vendor/autoload.php';
it is recomneded that you use composer to install this library but if you don't want to use composer, you need to create autoloader and require it in your code

Related

PHP - How to access Twilio in a composer namespace environment

I've been working with Rachet WebSockets and created a simple chat application. The example uses a WebSocket namespace. This is my first time using namespace. Now I'm trying to add Twilio service but can seem to add Twilio to my namespace.
I know it is autoloaded in the autoload_files.php
<?php
// autoload_files.php #generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
$vendorDir . '/twilio/sdk/Services/Twilio.php',
);
In the composer.json file
{
"autoload": {
"psr-0": {
"Websocket": "src"
}
},
"require": {
"cboden/ratchet": "^0.3.3",
"twilio/sdk": "^4.5"
}
}
I followed the steps from this website : https://www.twilio.com/docs/libraries/php#using-without-composer
I'm calling twilio inside a method of my class like this:
$AccountSid = "xxxxxxxxxxxxxxxxx";
$AuthToken = "xxxxxxxxxxxxxxxxx";
$client = new Client($sid, $token);
$message = $client->account->messages->create(array(
'To' => "+555555555",
'From' => "+555555555",
'Body' => "This is a test",
));
Keep getting this error: Uncaught Error: Class 'Websocket\Client' not found in ......
I'm very new to composer and namespace, hope this is enough information to help me.
I had to update Twilio,
ran composer require twilio/sd
- Removing twilio/sdk (4.12.0)
- Installing twilio/sdk (5.4.1)
Downloading: 100%
Now I'm able to use Twilio\Rest\Client; since it was missing before.
When using namespaces, PHP will always start looking for classes which aren't prepended with their own namespace in the current one.
In your case the current namespace would be Websocket, thus PHP is trying to autoload the class Websocket\Client, to prevent this, you have two options :
1) Tell PHP where to look by using use :
use Twilio\Rest\Client;
2) Prepend the correct namespace
$client = new \Twilio\Rest\Client($sid, $token);

How to implement php packages

Ok so I have been learning vanilla php and wanted to delve into making use of packages. so I tried implementing fabpot\Goutte to the teeth.
I did install the package using Composer and placed the src code in the root folder where the Composer-generated files sit. As I run the script, I get an initializing class not found error.
How do I get around with this? I have followed the instructions and it's making me crazyyyyyyyyyyyy
Code I got:
<?php
use Goutte\Client;
// Initialize object
$client = new Client();
// Issue GET request to URI
$crawler = $client->request("GET", "http://www.symfony.com/blog");
$client->getClient()->setDefaultOption("config/curl".CURLOPT_TIMEOUT, 60);
// Navigate the client through the use of links
$link = $crawler->selectLink("Security Advisories")->link();
$crawler = $client->click($link);
// Extract data
$crawler->filter("h2 > a")->each(function($node) {
print $node->text()."\n";
});
?>
The error I am getting:
Fatal error: Class 'Goutte\Client' not found in **line 6**
On top of your script.. You need to include composer's autoloader like this:
require __DIR__ . "/vendor/autoload.php";

How to create object of class inside function in function.php of wordpress

I am integrating google spreadsheet in my project. I have to save form data into google spreadsheet.
For this i am using asimqt php-google-spreadsheet-client library.
I have single form on site that form is submitting using ajax. For this i have written function in function.php.
Getting error when initializing object of DefaultServiceRequest class.
Error: Fatal error: Class 'Google\Spreadsheet\DefaultServiceRequest' not found
require '/vendor/autoload.php';
use Google\Spreadsheet\DefaultServiceRequest;
use Google\Spreadsheet\ServiceRequestFactory;
function spreadsheet_feeds()
{
$access_tok = 'xyz-token';
$serviceRequest = new DefaultServiceRequest($access_tok); // Getting error
ServiceRequestFactory::setInstance($serviceRequest);
$spreadsheetService = new Google\Spreadsheet\SpreadsheetService();
$spreadsheetFeed = $spreadsheetService->getSpreadsheets();
}
add_action( 'wp_ajax_nopriv_spreadsheet_data', 'spreadsheet_feeds' );
add_action('wp_ajax_spreadsheet_data','spreadsheet_feeds');
Any help why this error is occurring because class is already include using "use" statement ?
This seems to be an issue with the location of your vendor folder.
Make sure that the vendor folder is accessible by the file
Considering your folder hierarchy to be
-wp-content
--themes
---your-theme
----functions.php
If you have your vendor folder in your-theme/vendor then in your functions.php
you should write
require 'vendor/autoload.php';
and if vendor is in the root directory of WP make sure you traverse back to the root folder using something like :
require __DIR__ .'/../../../../vendor/autoload.php';
Just replace require '/vendor/autoload.php'; to require_once('vendor/autoload.php');
Just now I tried this here for you myself and it works.

Fatal error: Class 'Google_Auth_AssertionCredentials' not found

I'm trying to migrate the old google api to the new one, so I can get the google analytics data. I'm trying with this example, but it fires this error
Fatal error: Class 'Google_Auth_AssertionCredentials' not found in
example.php
This is how I'm trying:
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
require_once 'google-api-php-client/vendor/autoload.php';
//$p12FilePath = '/path/to/key.p12';
$serviceClientId = '395545742105.apps.googleusercontent.com';
$serviceAccountName = '395545742105#developer.gserviceaccount.com';
$scopes = array(
'https://www.googleapis.com/auth/analytics.readonly'
);
$googleAssertionCredentials = new Google_Auth_AssertionCredentials(
$serviceAccountName,
$scopes
); // <- Fatal error here
$client = new Google_Client();
$client->setAssertionCredentials($googleAssertionCredentials);
$client->setClientId($serviceClientId);
$client->setApplicationName("Project");
$analytics = new Google_Service_Analytics($client);
And I did run a search for Google_Auth_AssertionCredentials in the library wich I download from here, and Just one result: upagrading.md
Google_Auth_AssertionCredentials removed use Google_Client::setAuthConfig instead,
But how should I use it in a contructor?
I tred
$googleAssertionCredentials = new Google_Client::setAuthConfig(
$serviceAccountName,
$scopes
);
With internal server error,
Any idea what I'm missing here?
It looks like you have a mixture of the old and new (Google PHP API Client 2.0) syntax. The message "use Google_Client::setAuthConfig instead" is meant to indicate the method to use, but not that it should be called statically.
It should look like this:
$client = new Google_Client();
// set the scope(s) that will be used
$client->setScopes(array('https://www.googleapis.com/auth/analytics.readonly'));
// this is needed only if you need to perform
// domain-wide admin actions, and this must be
// an admin account on the domain; it is not
// necessary in your example but provided for others
$client->setSubject('youradmin#example.com');
// set the authorization configuration using the 2.0 style
$client->setAuthConfig(array(
'type' => 'service_account',
'client_email' => '395545742105#developer.gserviceaccount.com',
'client_id' => '395545742105.apps.googleusercontent.com',
'private_key' => 'yourkey'
));
$analyticsService = new Google_Service_Analytics($client);
This syntax works for me with the current build as of this writing, which is 2.0.0-RC2.
This solution work for me:
The composer setup section in https://github.com/google/google-api-php-client/blob/master/README.md could mention both versions, something like:
composer require google/apiclient:^2.0.0#RC
Note the documentation at developers.google.com refers to V1 of this library. If you want to use the older version, instead use:
composer require google/apiclient:1.*
https://github.com/google/google-api-php-client/issues/748

Reinit composer autoload

After updating via the Composer i want to initialize the application and send it events
"scripts": {
"post-update-cmd": [
"Acme\\Bundle\\DemoBundle\\Composer\\ScriptHandler::notify"
handler
public static function notify(CommandEvent $event)
{
// init app
require __DIR__.'/../../../../../../app/autoload.php';
require __DIR__.'/../../../../../../app/AppKernel.php';
$kernel = new \AppKernel('dev', true);
$kernel->boot();
// send event
$dispatcher = $kernel->getContainer()->get('event_dispatcher');
$dispatcher->dispatch('acme.installed', new Event())
}
If run the update through the composer.phar then everything works fine.
But I need to run the update from the application. I add composer to requirements and call bin\composer update.
In this case there is a conflict of autoloader. Composer connects the autoloader from the application, change it, and does not connect it again.
Need to destroy the old and create a new autoloader. I found out that the old autoloader can be accessed via $GLOBALS['loader'].
I came to this decision
public static function notify(CommandEvent $event)
{
// init loader
require __DIR__.'/../../../../../../vendor/composer/autoload_real.php';
$GLOBALS['loader']->unregister();
$GLOBALS['loader'] = require __DIR__.'/../../../../../../app/autoload.php';
// init app
require_once __DIR__.'/../../../../../../app/AppKernel.php';
// ...
But this option does not work because autoloading via file broadcast Composer in normal require and leads to connection conflict.
For example:
"name": "kriswallsmith/assetic",
"autoload": {
"files": [ "src/functions.php" ]
},
translate to
require $vendorDir . '/kriswallsmith/assetic/src/functions.php';
throw error
PHP Fatal error: Cannot redeclare assetic_init() (previously declared in /vendor/kriswallsmith/assetic/src/functions.php:20) in /vendor/kriswallsmith/assetic/src/functions.php on line 26
I create autoloader and duplicate the code of /vendor/composer/autoload_real.php and /app/autoload.php. Recommendation from Seldaek #2474
public static function notify(CommandEvent $event)
{
if (isset($GLOBALS['loader']) && $GLOBALS['loader'] instanceof ClassLoader) {
$GLOBALS['loader']->unregister();
}
$GLOBALS['loader'] = $this->getClassLoader();
require_once __DIR__.'/../../../../../../app/AppKernel.php';
$kernel = new \AppKernel('dev', true);
$kernel->boot();
// send event
$dispatcher = $kernel->getContainer()->get('event_dispatcher');
$dispatcher->dispatch('acme.installed', new Event())
}
protected function getClassLoader()
{
$loader = new ClassLoader();
$vendorDir = __DIR__.'/../../../../../../vendor';
$baseDir = dirname($vendorDir);
$map = require $vendorDir . '/composer/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$classMap = require $vendorDir . '/composer/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
$loader->register(true);
$includeFiles = require $vendorDir . '/composer/autoload_files.php';
foreach ($includeFiles as $file) {
require_once $file;
}
// intl
if (!function_exists('intl_get_error_code')) {
require_once $vendorDir.'/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs/functions.php';
$loader->add('', $vendorDir.'/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs');
}
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
return $loader;
}
I think I am a bit scared about what you are about to do: You want to update the components of a running application while these components are actively used. You hope that any update will run perfectly well so that after the update the application will continue to work - especially will continue to be able to do further updates.
I don't think this is a valid assumption! I have been using Composer for a while, and I have seen plenty of reasons why it did not update some parts of my dependencies, which most of the time were due to some network failure. Just think of using something from Github, and then Github is down.
What would happen then? You were probably able to download some parts, unable to download some more, and the autoloader was not updated. So the updated part now requires something new that got also downloaded, but cannot be autoloaded because some component after that failed to download. And this component is essential to repeat the update! You just broke your application, and you cannot fix it.
I can also think about very strange effects happening if the autoloader is partially loading old classes, then gets updated, and after that loads new classes that use new versions of the already loaded old classes that changed incompatible. So the assumption that you can change the components of the application during the runtime of one request seems to be very odd.
There is no way to unload a class in PHP. Once it is declared, it cannot be changed (not taking the "runkit" extension into account).
If you indeed want to get an update of your application, I think it is a better idea to duplicate everything, update the non-active copy of the application, then check if the update was successful, and after that copy it back, i.e. use symlinks to point to the current and next version and switch these.

Categories