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);
Related
I need to add the Telegram madelineproto library to my Laravel project. How can I do it via composer and How can I call it in my controllers
composer require danog/madelineproto
https://docs.madelineproto.xyz/docs/INSTALLATION.html#composer-from-existing-project
Register \danog\MadelineProto\API class to Laravel Service Container
Or use ready wrapper
https://github.com/setiawanhu/laravel-madeline-proto
You can't add it via composer.
https://packagist.org/packages/danog/madelineproto
It's not a package. It's whole project.
If you look at https://github.com/danog/MadelineProto/blob/master/composer.json
You will see it's not a package.
{
"name": "danog/madelineproto",
"description": "PHP implementation of telegram's MTProto protocol.",
"type": "project",
}
for faster code, use these steps:
Step 1:
download the danog/MadelineProto as a zip file, export the content of the zip file on a folder named 'lib/MadelineProto-master',
Step 2:
use terminal to compose the MadelineProto venders
cd lib/MadelineProto-master
composer install --ignore-platform-reqs
--ignore-platform-reqs is needed to ignore the PHP version and so on.
the composer will download all the vender on lib/MadelineProto-master/vendor
Step 3:
on your controller call the project lib like this:
require_once '../lib/MadelineProto-master/vendor/autoload.php';
//*/
class TelegramController extends Controller
{
private function sendMessage()
{
$settings['app_info']['api_id'] = '##';
$settings['app_info']['api_hash'] = '####';
$MadelineProto = new \danog\MadelineProto\API('session.madeline', $settings);
$MadelineProto->start();
$me = $MadelineProto->getSelf();
if (!$me['bot']) {
$sendMessage = $MadelineProto->messages->sendMessage([
'peer' => '#mansourcodes',
'message' => "Hi! <3"
]);
}
}
}
Slow Solution:
this solution will take 3-4s per call:
if (!file_exists('madeline/madeline.php')) {
copy('https://phar.madelineproto.xyz/madeline.php', 'madeline/madeline.php');
}
require_once 'madeline/madeline.php';
class TelegramController extends Controller
{
// ....
I am trying to get the google api client for php to work in Lumen, however trying to create a client results in my api to give a 'Oops, something went wrong' error with no further useful information.
I think it is something to do with the way im trying to import the google api client into Lumen, i used composer to install it. But i am not sure if i am using the right thing for Lumen. If i change my require_once it would state that it could not find the 'autoload.php' in the current path. I've also tried the composer update -vvv
The Google folder is present in my vendor folder, and the composer.json also has a entry for the google/apiclient
"require": {
"php": ">=7.1.3",
"google/apiclient": "2.0",
"laravel/lumen-framework": "5.8.*"
},
<?php
namespace App\Http\Controllers;
require_once dirname(__DIR__).'\..\..\vendor\autoload.php';
use App\Author;
use Illuminate\Http\Request;
class AccessController extends Controller
{
private function getToken()
{
$credentialsFilePath = 'service_account.json';
$client = new Google_Client();
$client->setAuthConfig($credentialsFilePath);
$client->addScope('https://googleapis.com/auth/analytics.readonly');
$client->setApplicationName("GoogleAnalytics");
$client->refreshTokenWithAssertion();
$token = $client->getAccessToken();
$accessToken = $token['access_token'];
return $accessToken;
}
public function showAccess()
{
$at = getToken();
return response('Token: ');
}
}
As you can see im trying to get the service account access token from a json that is saved at the server (no problems). but whenever the line $client = new Google_Client();
is called, i get the 'woops, something went wrong' error from Lumen
It appears i forgot the use Google_Client; Pretty simple but something i completely overlooked.
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
I've been following the Stripe documentation and I am unable to create a "charge".
Charge.php
require('/var/www/stripe-php-2.1.1/lib/Stripe.php');
\Stripe\Stripe::setApiKey("KEY_HERE");
\Stripe\Charge::create(array(
"amount" => 400,
"currency" => "usd",
"source" => "TOKEN_HERE", // obtained with Stripe.js
"description" => "Charge for test#example.com"
));
?>
I'm able to process the first command "\Stripe\Stripe::setApiKey("KEY_HERE");" but receive an error when processing the next and receive the following error:
"Class 'Stripe\Charge' not found in /var/www/charge.php"
Here is an updated answer to this question.
From Dana at Stripe:
If you prefer not to use Composer, our latest PHP bindings (>=2.x)
include a init.php file that you can add to your project. Download and
unzip the folder whereever you'd like, then include this init.php at
the top of your scripts you use to communicate with the Stripe API,
changing the path to the location of this file. Just like this:
require_once('/path/to/stripe-php/init.php')
And that's what worked for me.
If you don't use composer to install the Stripe library you will need to manually include all of the Stripe classes.
Composer is the preferred way as it will handle the autoloading of classes. Here is a sample composer file:
{
"require": {
"stripe/stripe-php": "2.*"
}
}
And then from a command line you would need to run composer update while in the directory for your project. Afterwards, just add require 'vendor/autoload.php'; to the top of your php file.
Otherwise, replace require('/var/www/stripe-php-2.1.1/lib/Stripe.php');with this code to include all of the classes:
$stripeClassesDir = __DIR__ . '/stripe-php-2.1.1/lib/';
$stripeUtilDir = $stripeClassesDir . 'Util/';
$stripeErrorDir = $stripeClassesDir . 'Error/';
set_include_path($stripeClassesDir . PATH_SEPARATOR . $stripeUtilDir . PATH_SEPARATOR . $stripeErrorDir);
function __autoload($class)
{
$parts = explode('\\', $class);
require end($parts) . '.php';
}
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.