I am new to php and have just installed my first package via composer. I'm now trying to call a function from the package I installed as follows:
<?php
require_once 'vendor/autoload.php';
$value = 1;
$aws = AmazonGiftCode::make()->buyGiftCard($value);
echo $aws;
?>
But I get the following error:
PHP Fatal error: Uncaught Error: Class 'AmazonGiftCode' not found in
/public_html/php/test.php:4 Stack trace:
#0 {main} thrown in /public_html/php/test.php on line 4
Based on my (albeit limited) experience with other languages, I'm guessing I have to load the package that contains the class first. The package folder is in the same directory as the test.php file, in the subfolder vendor/kamerk22/AmazonGiftCode/. But I think this is where I don't know enough to troubleshoot it based on the information I could find.
Your directory structure should look like this.
test.php
composer.json
vendor
└───autoload.php
└───kamerk22
└───AmazonGiftCode
Make sure you installed the package using composer, and not by downloading it.
I'm guessing I have to load the package that contains the class first.
Unlike what you would normally expect when importing stuff, when using composer you only have to import the autoload.php file, and composer will take care of loading other packages as needed. By as needed what I mean is that as soon as composer sees you use the AmazonGiftCode class it will import the AmazonGiftCode package, but if one of your REST endpoints doesn't use anything from the AmazonGiftCode package it won't ever load it. This allows you to not have to worry about slowing down the entire application when you want to use a composer package for only a few endpoints. At least that's the way I understand how composer works.
Just run composer dump-autoload once and the class should known then.
You could also get verbose and use kamerk22\AmazonGiftCode\AmazonGiftCode;
But that AmazonGiftCode looks quite Laravel specific... that's why it may still fail, even if it may be found by auto-load. One needs to setup Laravel framework in the first place; just see this query (just in case if you may wonder where all these missing classes may come from).
Related
first of all I am new to this topic, so I hope my question is not too stupid.
I want my website to have PHP access to Google Analytics metrics. I followed every step of this description from google. Unfortunately when I upload everything on my server and try to run the test-site, I always get the following error-message:
Fatal error: Uncaught exception 'Exception' with message 'This library
must be installed via composer or by downloading the full package. See
the instructions at
https://github.com/google/google-api-php-client#installation.' in
/home/users/myftp/dev.mywebsite.com/dashboard/google-api-php-client-master/src/Google/autoload.php:14
Stack trace: #0
/home/users/myftp/dev.mywebsite.com/dashboard/HelloAnalytics.php(8):
require_once() #1
/home/users/myftp/dev.mywebsite.com/dashboard/HelloAnalytics.php(104):
getService() #2 {main} thrown in
/home/users/myftp/dev.mywebsite.com/dashboard/google-api-php-client-master/src/Google/autoload.php
on line 14
So apparently there is something wrong with the embedding of the Google client library. In the error message it says I have to use Composer, but in the GitHub documentation they say, manual download would be fine as well. I think in the end this shouldn't make any difference? I am not familiar with composer or GitHub, this is why i downloaded it manually.
I uploaded it on the server and put it into the same directory like the HelloAnalytics.php. I address it in HelloAnalytics.php via
require_once 'google-api-php-client-master/src/Google/autoload.php'
From the looks of it you are using the wrong autoloader.
src/Google/autoload.php looks for the composer autoloader and if it doesn't exist it throws the exception you are getting. Since you didn't install using Composer it is not found and that exception is thrown.
If you clone the repository using git you will have the correct SPL autoloader. If you download the package it uses the composer autoloader.
Try downloading using:
git clone -b v1-master https://github.com/google/google-api-php-client.git
Or switch to the v1-master branch and use this autoloader instead. You will see that file differs between the master branch and the v1-master branch.
to avoid AUTOLOADer error, install MASTER-V1 version:
https://github.com/google/google-api-php-client/tree/v1-master
p.s. if you will get other error, then ensure that you have correctly included the "SERVICE EMAIL" (that is like: xxxxxx#analytics-xxxxx.iam.gserviceaccount.com ).
Introduction
I've never worked with a framework before (Zend, CakePHP, etc) and finally decided to sit down and learn one. I'm starting with Laravel because the code looks pretty and unlike some other frameworks I tried to install, the "Hello, World!" example worked on the first try.
The Goal
For the time being, I want my app to do something very simple:
User submits a request in the form of: GET /dist/lat,lng
The app uses the remote IP address and MaxMind to determine $latitude1 and $longitude1
This request path is parsed for $latitude2 and $longitude2
Using these two positions, we calculate the distance between them. To do this I'm using Rafael Fragoso's WorldDistance PHP class
Since I plan to re-use this function in later projects, it didn't seem right to throw all of the code into the /app directory. The two reusable parts of the application were:
A service provider that connects to MaxMind and returns a latitude and longitude
A service provider that takes two points on a globe and returns the distance
If I build facades correctly then instead of my routes.php file being a mess of closures within closures, I can simply write:
Route::get('dist/{input}', function($input){
$input = explode( "," , $input );
return Distance::getDistance( GeoIP::getLocation(), $input );
});
What I've tried
Initial Attempt
For the first service provider, I found Daniel Stainback's Laravel 5 GeoIP service provider. It didn't install as easily as it should have (I had to manually copy geoip.php to the /config directory, update /config/app.php by hand, and run composer update and php artisan optimize) however it worked: A request to GET /test returned all of my information.
For the second service provider, I started by trying to mimic the directory structure and file naming convention of the GeoIP service provider. I figured that if I had the same naming convention, the autoloader would be able to locate my class. So I created /vendor/stevendesu/worlddistance/src/Stevendesu/WorldDistance\WorldDistanceServiceProvider.php:
<?php namespace Stevendesu\WorldDistance;
use Illuminate\Support\ServiceProvider;
class WorldDistanceServiceProvider extends ServiceProvider {
protected $defer = false;
public function register()
{
// Register providers.
$this->app['distance'] = $this->app->share(function($app)
{
return new WorldDistance();
});
}
public function provides()
{
return ['distance'];
}
}
I then added this to my /config/app.php:
'Stevendesu\WorldDistance\WorldDistanceServiceProvider',
This fails with a fatal error:
FatalErrorException in ProviderRepository.php line 150:
Class 'Stevendesu\WorldDistance\WorldDistanceServiceProvider' not found
Using WorkBench
Since this utterly failed I figured that there must be some other file dependency: maybe without composer.json or without a README it gives up. I don't know. So I started to look into package creation. Several Google searches for "create package laravel 5" proved fruitless. Either:
They were using Laravel 4.2, in which case the advice was "run php artisan workbench vendor/package --resources"
Or
They were using Laravel 5, in which case the docs were completely useless
The official Laravel 5 docs give you plenty of sample code, saying things like:
All you need to do is tell Laravel where the views for a given namespace are located. For example, if your package is named "courier", you might add the following to your service provider's boot method:
public function boot()
{
$this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');
}
This makes the assumption that you have a service provider to put a boot method in
Nothing in the docs says how to create a service provider in such a way that it will actually be loaded by Laravel.
I also found several different resources all of which assume you have a repository and you just want to include it in your app, or assume you have "workbench". Nothing about creating a new package entirely from scratch.
PHP Artisan did not even have a "workbench" command, and there was no "workbench.php" file in /config, so anything I found related to workbench was worthless. I started doing some research on Workbench and found several different questions on StackOverflow.
After a long time and some experimentation, I managed to get laravel/workbench into my composer.json, composer update, composer install, manually build a workbench.php config file, and finally use the PHP Artisan Workbench command to make a new package:
php artisan workbench Stevendesu/WorldDistance --resources
This created a directory: /workbench/stevendesu/world-distance with a number of sub-directories and only one file: /workbench/stevendesu/world-distance/src/Stevendesu/WorldDistance/WorldDistanceServiceProvider.php
This service provider class looked essentially identical to the file I created before, except that it was in the /workbench directory instead of the /vendor directory. I tried reloading the page and I still got the fatal error:
FatalErrorException in ProviderRepository.php line 150:
Class 'Stevendesu\WorldDistance\WorldDistanceServiceProvider' not found
I also tried php artisan vendor:publish. I don't really know what this command does and the description wasn't helpful, so maybe it would help? It didn't.
Question
How do I create a new service provider as a package so that in future projects I can simply include this package and have all the same functionality? Or rather, what did I do wrong so that the package I created isn't working?
After two days of playing with this I managed to find the solution. I had assumed that the directory structure mapped directly to the autoloader's path that it checked (e.g. attempting to access a class Stevendesu\WorldDistance\WorldDistanceServiceProvider would look in vendor/stevendesu/world-distance/WorldDistanceServiceProvider)... This isn't the case.
Reading through the composer source code to see how it actually loads the files, it builds a "classmap" - essentially a gigantic array mapping classes to their respective files. This file is built when you run composer update or composer install - and it will only be built correctly if composer knows the details of your package. That is - if your package is included in your project's composer.json file
I created a local git repository outside of my app then added my package to my app's composer.json file then ran composer update -- suddenly everything worked perfectly.
As for the:
It didn't install as easily as it should have
the secret sauce here was first add the service provider to /config/app.php then, second run php artisan vendor:publish
I'm using this library to implement the Nexmo SMS service on my server. I required the library using Composer like so:
"require" : {
"prawnsalad/nexmo": "dev-master"
}
which I found here and followed the instructions included in the README like so:
require 'vendor/autoload.php';
use NexmoMessage;
$phone = '123456789';
$sms = new NexmoMessage(NEXMO_KEY, NEXMO_SECRET);//defined in another file
$sms->sendText($phone, 'from', "yo");//$phone is a valid number in actual case
However I keep getting the error in the title of this question. I see that Composer has imported the library successfully and I see the class and constructor for NexmoMessage, yet for some reason this error keeps happening no matter what I do. I'm not sure if this is due to an issue with the library or with how I'm using Composer. I've never had an issue with Composer in the past so I'm boggled why this is happening here. Thanks
Well, that library states that it supports PSR-4, which means they absolutely MUST use PHP namespaces, but they don't. That last commit 8 months ago https://github.com/prawnsalad/Nexmo-PHP-lib/commit/8e422c4f8f43c52acb70ebd5f9e7c6ff81a1f352 broke the autoloading. And nobody noticed up to today.
You can easily tell by looking at the source code: There is no namespace being used.
Your best action now would be to fix this issue and send a pull request! Github allows to edit files in the browser! Second best action would be to create an issue and let the authors know.
I've developed a small project on a machine, using CakePHP 3.0, and I need it to run on another machine. I've tried to install it on several other machines.
If I run the composer to install the CakePHP 3.0, then I copy my stuff to overwrite it, the project works. I've tried this on two machines and had no problem so far. If I don't run the composer, and just copy the stuff to the target machine, it gives me the following error. I've tried this on 3 machines, and every machine gives me this:
Fatal error: Class 'Locale' not found in /home/u113681897/public_html/vendor/cakephp/cakephp/src/I18n/I18n.php on line 229
Fatal error: Class 'Locale' not found in /home/u113681897/public_html/vendor/cakephp/cakephp/src/I18n/I18n.php on line 229
I've copied the whole project to this server to test.
I told you this because I thought it has something to do with my problem. The point is that I have to run this on a machine that is not mine, and I can't install composer on it. The /public_html/vendor/cakephp/cakephp/src/I18n/ has files related to internationalization and localization, but my project will never be translated, so a workaround to make the project ignore those files would be enough to solve my problem.
The following code is an excerpt from the (...)/I18n/I18n.php that might be relevant:
<?php
namespace Cake\I18n;
use Aura\Intl\FormatterLocator;
use Aura\Intl\PackageLocator;
use Aura\Intl\TranslatorFactory;
use Cake\I18n\Formatter\IcuFormatter;
use Cake\I18n\Formatter\SprintfFormatter;
use Locale;
class I18n {
// lots of code here
public static function defaultLocale() {
if (static::$_defaultLocale === null) {
static::$_defaultLocale = Locale::getDefault() ?: 'en_US';
// the line above is the Line 229
}
return static::$_defaultLocale;
}
// many code here too
}
I've checked that another file also tries to access this Locale class, but I don't know if there are other files trying to access it as well. Many files from everywhere inside the project tries to access methods from I18n.php. I need it running but I can't figure out how to make it run.
Any help will be greatly appreciated.
As I just found out, prior to CakePHP 3.0, the installation must be done by composer, as stated in the 3.0 migration guide:
CakePHP should be installed with Composer
Since CakePHP can no longer easily be installed via PEAR, or in a shared
directory, those options are no longer supported. Instead you should use
Composer to install CakePHP into your application.
So it won't run on regular free web hosting services.
Im kind of new with Travis, and I am expreimenting with it right now. I uploaded have my PHP Project on Github and when I let it test via Travis it fails and gives me this error.
PHP Fatal error: Class 'controllers\Welcome' not found in /home/travis/build/ezylot/PHPSkeleton/tests/controllers/welcomeTest.php on line 4
I use a autoloader to load the classes, and it is no problem on my local machine. I include the autoloader in bootsrap.php with the bootstrap in the PHPUnit Konfiguration-XML File.
<?php
if (!#include __DIR__ . '/../vendor/autoload.php') {
die('You must set up the project dependencies, run the following commands:
wget http://getcomposer.org/composer.phar
php composer.phar install');
}
?>
You are most likely developing on OSX which has case insensitive filesystem and tests pass. Travis uses case sensitive file system. Try renaming app/controllers/welcome.php to app/controllers/Welcome.php.
In general it is good idea to follow PSR-1 standard to avoid autoloading issues.
I had a short php open tag at the top of the class file.
<?
as opposed to
<?php
This broke it on the remote, but not on my local. Which is weird, because I would've expected it to break locally too.
Putting this out there in case someone else is in the same odd situation.