Error when using SplClassLoader - php

First off, I'm trying my hand using the following SplClassLoader -https://gist.github.com/221634
Here is my file structure:
/root/f1/f2/APS/Common/Group.php
/root/f1/f2/index.php
/root/f1/f2/SplClassLoader.php
Here is my test class called Group (Group.php)
namespace APS\Common;
class Group{
...
}
Here is the index.php file that is calling everything:
require "SplClassLoader.php";
$classLoader = new SplClassLoader('APS', 'APS/Common');
$classLoader->register();
I'm getting the following error:
Fatal error: Class 'Group' not found in /root/f1/f2/index.php on line 17
I've tried every conceivable combination when passing the namespace and path to the loader. It never works.
Update #1 - Line 17 in index.php:
16: use APS\Common;
17: $x = new Group();
Update #2 - Configuration info
Apache/2.2.15 (Red Hat)
PHP 5.3.3
Update #3 - I'm getting a different error message now.
The code in place:
require "SplClassLoader.php";
$classLoader = new SplClassLoader('APS', '/root/f1/f2');
$classLoader->register();
use APS\Common;
$x = new Common\Group();
Error message that I'm getting:
Warning: require(/f1/f2/APS/Common/Group.php): failed to open stream: No such file or directory in /root/f1/f2/SplClassLoader.php on line 133

When using the use statement (no pun intended), you simply create an alias for the used namespace or class. According to the PHP manual, use \Foo\Bar; is equivalent to use \Foo\Bar as Bar;.
So, in your case, you import the APS\Common namespace with the alias Common. This means that you can refer to the Group class within this namespace as Common\Group instead of APS\Common\Group. Without using the namespace alias (as you did), the classloader will expect the Group class to be in the global namespace (and expect the class to be stored in /root/f1/f2/Group.php).
Edit: Another possibility would be to simply put namespace \APS\Common; into your file. If you reference a class without a namespace specification (i.e. Group instead of \Group or \APS\Common), PHP will expect the class to be in the current namespace.

In my case, here is the solution that seems to work.
require "SplClassLoader.php";
$classLoader = new SplClassLoader('APS\Common', __DIR__);
$classLoader->register();
use APS\Common;
$x = new Common\Group();
I had to use the magic constant DIR for it to work. The second parameter seems to need to point to the physical path of the root of where the classes reside. Then, the namespace gets added to locate them in the file system.

Related

PHP - Fatal error: Uncaught Error: Class 'Contentful\Delivery\Client' not found [duplicate]

I am trying to call my model file from another folder. I have provided both of these file structure.
I am getting this error:
Uncaught Error: Class 'App\Models\Providers' not found in /Applications/XAMPP/xamppfiles/htdocs/pro/app/Scripts/Providers/1/Scrape.php:17
I am calling the model file from a script folder located :
app/Scripts/Providers/1/Scrape.php
In this class I have the below :
namespace App\Scripts\Providers\1;
use App\Models;
Model file is located :
app/Models/Providers.php
Within this file I have the below:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
I have not shared the full content that I have in both of these files. If you would like to see the full content of these files please let me know.
This is how the Scrape.php looks like
<?php
namespace App\Scripts\Providers\1;
use App\Models\Providers;
class Scrape {
public function __construct() {
$test = new \App\Models\Providers();
die(print_r($test, true));
}
}
$obj = new Scrape();
You can't have a namespace that starts with a number.
Namespaces follow the same basic rules for variable names:
A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores
(Emphasis mine).
Thus, your declaration
namespace App\Scripts\Providers\1
is basically invalid.
From that point forward, all bets are off.
First, change your namespace to a valid identifier (and I would advise choosing something more reasonable and recognizable than numbers, you can have descriptive names and there is simply no reason not to):
namespace App\Scripts\Providers\GroupWhatever
Logically, you'll have to rename the folder where this file resides. It used to be
app/Scripts/Providers/1/Scrape.php
so rename that directory to
app/Scripts/Providers/GroupWhatever/Scrape.php
(In both cases, replace GroupWhatever with something that makes sense for your application and domain).
From that point forward, if the class \App\Models\Providers exists at app/Models/Providers.php, it should work.
Important:
Another problem that there could exist, is that is not very clear what Scripts/Scrape.php is or how is it called.
This should work if you are executing Scrape.php from within Laravel, by calling a Laravel controller or console application.
If you are calling this script directly (e.g. by executing php app/Scripts/Providers/1/Scrape.php (or the corrected app/Scripts/Providers/GroupWhatever/Scrape.php) this simply won't work, since the autoloading logic is not run at all.
If you are executing your script manually, on top of the above changes you need to include composer autoload script, which is located at vendor/autoload.php.
Basically, add this line close to the top of your Scrape.php:
require_once dirname( __DIR__ ) . '/../../../vendor/autoload.php';
(I think I put the appropriate amount of go-up-one-dir path-segments, but you make sure it matches the correct path in your installation).
Once that is in place, the autoloader will be run, and classes will be found.
In your Scrape.php, change your namespace to:
<?php
namespace App\Scripts\Providers\p1;
From PHP manual comment,
namespace (even nested or sub-namespace) cannot be just a number, it
must start with a letter. For example, lets say you want to use
namespace for versioning of your packages or versioning of your API:
namespace Mynamespace\1; // Illegal
Instead use this: namespace
Mynamespace\v1; // OK

Composer autoload is called but loaded nothing

Project structure
/Test
composer.json
composer.lock
index.php
nfe.xml
vendor/
autoload.php
(more files)
PHP Code
And I am trying a snipped which I found at the library's README on github
<?php
require_once 'vendor/autoload.php';
// var_dump( get_declared_classes() );
echo 'a';
$nfeProc = NFePHPSerialize::xmlToObject(file_get_contents('nfe.xml'));
echo 'b';
//Capturando CNPJ do emitente
$cnpjEmitente = $nfeProc->getNFe()->getInfNFe()->getEmit()->getCNPJ();
echo $cnpjEmitente;
Results
But I am getting the following error:
PHP Fatal error: Class 'NFePHPSerialize' not found in /var/www/html/Test/index.php on line 7
PHP Stack trace:
PHP 1. {main}() /var/www/html/Test/index.php:0
Finally I have uncommented the var_dump( get_declared_classes() ); just to know whether something from the library nfephp-serialize (for tax purposes) is loaded but I found nothing.
Initialization
To init the Test directory, I have issued the following command:
$ composer require jansenfelipe/nfephp-serialize
How to solve?
What is missing is the path associated with the NFePHPSerialize class. It is JansenFelipe\NFePHPSerialize.
You may want to use the class NFePHPSerialize with its namespace, as so:
<?php
require 'vendor/autoload.php';
use JansenFelipe\NFePHPSerialize\NFePHPSerialize;
or simply write:
$nfeProc = JansenFelipe\NFePHPSerialize\NFePHPSerialize::xmlToObject(file_get_contents('nfe.xml'));
How I found the namespace?
You may want to search for the NFePHPSerialize class in the /vendor directory... and find the namespace statement, which is:
namespace JansenFelipe\NFePHPSerialize;
So, the class is available with namespace\class as so:
$var = new JansenFelipe\NFePHPSerialize\NFePHPSerialize(...);
But you can improve this by inserting the use statement as so:
<?php
use JansenFelipe\NFePHPSerialize\NFePHPSerialize;
// some code...
$var = new NFePHPSerialize(...);
I hope this helps you! :)

'Alias is never used' PHPStorm error message within my PHP file

I am following the installation instructions here to install PHP RAML Parser
I run composer install and created the index.php below but it isn't working, I get an error:
Class 'Raml\ParseConfiguration' not found in /cygdrive/c/src/myapp/Raml/Parser.php on line 83
When I hover over the line use \Raml\Parser I get the PHPStorm warning message (Alias never used)
My index.php:
<?php
require ('Raml/Parser.php');
use \Raml\Parser; // Alias \Raml\Parser is never used
$parser = new \Raml\Parser();
Can anyone suggest what I've done wrong?
Provided that the file Raml/Parser.php contains:
namespace Raml;
class Parser {}
You can either do this:
require ('Raml/Parser.php');
$parser = new \Raml\Parser();
or this:
require ('Raml/Parser.php');
use \Raml\Parser;
$parser = new Parser();
use imports a class/interface/trait into your current namespace and allows to use a shorter name instead of the fully qualified, backspaced name. It also allows to switch to a different class by only changing the use statement, and not every name reference in the whole class, but this benefit is very small because using PHPStorm brings some powerful renaming abilities itself.

php / composer not loading interface

I've banged my head against the wall for 3/4 of a day now and just can't see the error of my ways.
I'm creating (or trying to!) a simple package that consists of a couple of classes and 1 interface. This is in github at https://github.com/dnorth98/victoropsnotifier
Basically though, there's the following directory structure:
victoropsnotifer
src
Signiant
VictorOpsNotifier
Transport.php
VictorOpsNotifier.php
Transport is very simple:
<?php
namespace Signiant\VictorOpsNotifer;
interface Transport
{
// must POST the $message to the VictorOps REST endpoint
public function send(Messages\Message $message);
}
and the beginning of VictorOpsNotifier is
<?php
namespace Signiant\VictorOpsNotifer;
use GuzzleHttp\Client;
class VictorOpsNotifer implements Transport
{
protected $endpoint_url;
:
:
The problem comes when I try to instantiate a new object using
<?php
require_once 'vendor/autoload.php';
use Signiant\VictorOpsNotifier\Messages\CustomMessage;
use Signiant\VictorOpsNotifier\VictorOpsNotifier;
$voConfig = ['routing_key' => 'test',
'endpoint_url' => 'https://goo'];
$voHandle = new VictorOpsNotifier($voConfig);
I get back
PHP Fatal error: Interface 'Signiant\VictorOpsNotifer\Transport' not found in /tmp/djn/tests/vendor/signiant/
victoropsnotifier/src/Signiant/VictorOpsNotifier/VictorOpsNotifier.php on line 8
PHP Stack trace:
PHP 1. {main}() /tmp/djn/tests/test.php:0
PHP 2. spl_autoload_call() /tmp/djn/tests/test.php:12
PHP 3. Composer\Autoload\ClassLoader->loadClass() /tmp/djn/tests/test.php:0
PHP 4. Composer\Autoload\includeFile() /tmp/djn/tests/vendor/composer/ClassLoader.php:301
PHP 5. include() /tmp/djn/tests/vendor/composer/ClassLoader.php:412
What on EARTH am I missing? Composer is finding the package ok from my github repo and everying is in the vendor folder and looks ok. It looks like the namespaces match...so for some reason, it's just not loading the Transport.php file containing the interface.
It seems to be just a typo:
namespace Signiant\VictorOpsNotifer;
^ no `i` in here
but
use Signiant\VictorOpsNotifier\VictorOpsNotifier;
^ but here it is
same thing with the class name.
Also, you're declaring namespace Signiant as src/, but it's really src/Signiant
By the way, there's no need to declare this package as psr-0, better to use psr-4 insetad. Not a big deal, just for conformity.
P.S. The strange thing it was complaining about interface, while it shouldn't have to until it hit the class, and it certainly must not hit the class while there was a typo.
P.P.S You can easily avoid those typo errors by using a proper IDE, PHPStorm, for example. It would highlight name of the class as missing as long as there wre typos (and i don't even start talking about autocompletion).
class VictorOpsNotifer implements \Signiant\VictorOpsNotifer\Transport{}
try add namespace before your interface.

In php namespaces do I need to require each file

If I'm using namespace and for example I have the following directory tree
Test/someclass.php
Test/someotherclass.php
can I simply do
use \Test\someotherclass
or I need first to do
require 'Test/someotherclass.php'
and then I can actually use that class
because currently when I do that I get the following error
Fatal error: Class 'Test\someOtherClass' not found in
C:\xampp\htdocs\test\Test\someClass.php on line 10
As said in the comments the namespace and the use statement don't load anything by default.
But you can use an autoloader based on namespace. You have a standard called psr-0 for autoload.

Categories