Namespace with extends or interface causes Fatal Error without autoloader - php

Why doesn't this work?
web/index.php (Not web/src/App/App.php)
<?php
namespace App;
// web/index.php
require_once __DIR__ . '/../vendor/autoload.php';
$app = new App();
class App extends \Silex\Application {
public function __construct()
{
parent::__construct();
echo 'Worked!';
}
}
I also tried namespace App {...}, no change. It throws this exception:
Fatal error: Uncaught Error: Class 'App\App' not found in /path/to/web/index2.php:8
Stack trace:
#0 {main}
thrown in /path/to/web/index2.php on line 8
As long as I remove the extends ... and the parent call part, it works. I also noticed interface does the same thing (trying to use Serializable). Is this an issue with the autoloader being confused? Is there a way to do this without putting the App\App class into a file in src\App\App.php?
Note: this is an exercise to build a single-file application with Silex, so "just put it in a file" isn't an answer. I want to know why this doesn't work, which has an answer.

The problem in your code is,
In namespace, You are initiating class object before it being declared and loaded. In your above code you are doing same thing,
1. You are initiating App class object which lies in App namespace
2. You are initiating class object at the moment class when is not yet declared(As it is defined below in your code).
In your above code, not even your loader be called. It will be called if you initiate App\App class object after its declaration. and If your loader does not work fine then afterwards you will possibly get this error.
Fatal Error: Silex\Application class not found
Please checkout some examples and findings.
Example 1 Here loader is expected to be called but not called, because you have registered after initialization of class($app = new App();).
Example 2 Here, calling class will look for autoloading class because here initialization takes place after registration of loader and declaration of class, which is probably answers your question.
Change your code with this to get it fix:
<?php
namespace App;
require_once __DIR__ . '/../vendor/autoload.php';
class App extends \Silex\Application {
public function __construct()
{
parent::__construct();
echo 'Worked!';
}
}
$app = new App();

Related

Unable to load vendor classes from other namespace

I'm having some hard time wrapping around namespaces in PHP, especially when you code needs to interact with scripts residing in another namespace. I downloaded a Shopify API toolkit and trying to get it working. Everything was fine before I started adding namespaces to my code (which is required or threre is script collisition with other Wordpress plugins on my site). Also, the weird namespace {} bit at the top is because in this same file I want a globally accessible function for making the class a singleton.
Looking forward to learning more about how this works.
#### FILE BEING CALLED
namespace {
function SomeFunctionToBeAccessedGlobally() {
return 'Hello';
}
}
namespace MySpecialApp {
class ShopifyImport {
public function __construct() {
// Do Whatever
$this->doImport();
}
public function doImport() {
require __DIR__ . '/vendor/autoload.php';
$credential = new Shopify\PrivateAppCredential('standard_api_key', 'secret_api_key', 'shared_api_key');
$client = new Shopify\Client($credential, 'shop_url', [ 'metaCacheDir' => './tmp' ]);
}
}
}
#### FILE '/vendor/autoload.php'
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit73503f8de5d68cdd40a9c0dfd8a25b44::getLoader();
I do noice that some of the files which where part of the repository cloned into vendor have namespace Slince\Shopify; declarations. I tried to do a use with that namespace within my original namespace but it also didn't work.
The PHP Error being reported is:
Fatal error: Uncaught Error: Class
'MySpecialApp\Shopify\PrivateAppCredential' not found in
/.../ShopifyImporter.php:139 Stack trace: #0 (Blah Blah Blah)
Your code tries to create a new Shopify\PrivateAppCredential() object in the current namespace. However, this class does not exist in your namespace since it is part of the "vendor" namespace.
You can "reset" (read fallback) to the global namespace for your object creations by adding a \ in front of them, as described in the documentation:
$credential = new \Shopify\PrivateAppCredential('standard_api_key', 'secret_api_key', 'shared_api_key');
You can check the difference here without \ and with \.

PHP Fatal error: Interface 'App\\PluginContract' not found

In the same direcory I have:
html/app
Plugin.php
PluginContract.php
GetUid.php
On GetUid.php i have this code:
<?php
namespace App;
include_once "Plugin.php";
include_once "PluginContract.php";
use Carbon\Carbon;
use TeamSpeak3\Ts3Exception;
class GetUid extends Plugin implements PluginContract
{
public function isTriggered()
{
...
}
}
And this is PluginContract.php:
<?php
namespace App;
interface PluginContract
{
public function isTriggered();
}
It seems all ok, but I got this error:
PHP Fatal error: Interface 'App\PluginContract' not found in /var/www/html/app/GetUid.php on line 11
The weird thing is that it can load Plugin.php without problem but it gets this error for PluginContract.php which is in the same folder.
What I'm doing wrong?
What I was tring to do is add a web interface to a PHP application, I though that I don't need the autoload because it automatically start with the server, but I discovered that adding again the autoload to my index.php I resolved the problem.

PHP Symfony- How to inherit multiple classes from one php file

I am using Symfony 2.4
I have a PHP file OAuth.php which has multiple classes inside that.
Code of OAuth.php is as below
<?php
namespace RT\AuthBundle\DependencyInjection\Vzaar;
use Exception;
class OAuthException extends Exception {
// pass
}
class OAuthConsumer {
//some code
}
class OAuthToken {
//some code
}
?>
I am inheriting above file in Vzaar.php file which is with in same namespace and it's code is as below
<?php
namespace RT\AuthBundle\DependencyInjection\Vzaar;
/*require_once 'OAuth.php';
require_once 'HttpRequest.php';
require_once 'AccountType.php';
require_once 'User.php';
require_once 'VideoDetails.php';
require_once 'VideoList.php';
require_once 'UploadSignature.php';*/
use RT\AuthBundle\DependencyInjection\Vzaar\OAuth;
use RT\AuthBundle\DependencyInjection\Vzaar\HttpRequest;
use RT\AuthBundle\DependencyInjection\Vzaar\AccountType;
use RT\AuthBundle\DependencyInjection\Vzaar\User;
use RT\AuthBundle\DependencyInjection\Vzaar\VideoDetails;
use RT\AuthBundle\DependencyInjection\Vzaar\VideoList;
use RT\AuthBundle\DependencyInjection\Vzaar\UploadSignature;
//use RT\AuthBundle\DependencyInjection\Vzaar\OAuth\OAuthConsumer;
Class Profile
{
public static function setAuth($_url, $_method = 'GET')
{
$consumer = new OAuthConsumer('', '');
//some code
}
}
?>
Creating new object of OAuthConsumer class throws error that
Fatal error: Class 'RT\AuthBundle\DependencyInjection\Vzaar\OAuthConsumer' not found in /var/temp/rt-web/src/RT/AuthBundle/DependencyInjection/Vzaar/Vzaar.php
1/1 ClassNotFoundException: Attempted to load class "OAuthConsumer" from namespace "RT\AuthBundle\DependencyInjection\Vzaar" in /var/temp/rt-web/src/RT/AuthBundle/DependencyInjection/Vzaar/Vzaar.php line 378. Do you need to "use" it from another namespace?
Because since 2.1 Symfony uses composer, and composer uses PSR-0/PSR-4 to autoloading the classes, you have to follow the namespace convention, so you have to create those classes in separate files and in the right directory structure, what is represented in the namespace.
EDIT
As Cerad mentioned in the comment, you can specify a class map in composer, although what is considered as a best practice with symfony projects, create every class in a separate file.

Symfony custom class autoloading doesn`t work

I use symfony 2.4.0. I want to use my custom class as discussed here: Autoloading a class in Symfony 2.1. I have created subfolder in src:
namespace Yur;
class MyClass {
public go() {
var_dump('hello!! 32');
}
}
In my controller, I made this:
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Yur\MyClass;
class WelcomeController extends Controller
{
public function indexAction()
{
$my = new MyClass();
$my->go();
die();
...
but it makes an exception:
ClassNotFoundException: Attempted to load class "MyClass" from namespace "Yur" in /var/www/shop.loc/src/Acme/DemoBundle/Controller/WelcomeController.php line 12. Do you need to "use" it from another namespace?
After I have got this exception, I decided consciously to make syntax error exception in my class to see if it loaded. I changed class MyClass ... to class4 MyClass ..., but doesnt got asyntax error` exception. And I decided, that my class is not loaded.
Is anyone knows why? And what I must to do to resolve?
A few things. First, in your code sample above, you have
public go() {
var_dump('hello!! 32');
}
which should be
public function go() {
var_dump('hello!! 32');
}
The former raises a parser error in PHP. and probably isn't what you want.
Second, the error
ClassNotFoundException: Attempted to load class "MyClass" from namespace "Yur" in /var/www/shop.loc/src/Acme/DemoBundle/Controller/WelcomeController.php line 12. Do you need to "use" it from another namespace?
is the error Symfony uses when it attempt to autoload a class, but can't find the file. This usually means your file is named incorrectly, or in the wrong folder. I'd tripped check that you have a file in the directory you think you do.
$ ls src/Yur/MyClass.php
You can also add some debugging to the composer autoload code to see what path it's cooking up for your custom class
#File: vendor/composer/ClassLoader.php
public function findFile($class)
{
//...
$classPath .= strtr($className, '_', DIRECTORY_SEPARATOR) . '.php';
//start your debugging code
if($class == 'Yur\MyClass')
{
//dump the generated path
var_dump($classPath);
//dump the default include paths
var_dump($this->fallbackDirs);
}
//...
}

namespaces and class extends

Im trying to figure out how namespaces works in PHP, but havent really been lucky
Hope somebody could tell me what Im doing wrong here :)
code
require_once 'Vatcode.php';
$Vatcode = new \resource\Vatcode();
Vatcode.php
namespace resource;
require_once Ini::get('path/class').'/Resource.php';
class Vatcode extends Resource {
public function __construct(){
echo 'works!';
}
}
Rescource.php
namespace resource;
class Resource {
}
error
Fatal error: Class 'resource\Ini' not found in Vatcode.php
it's just a problem of namespace.
Your class Vatcode is in namesapce ressource. If, in the file of VatCode declaration you use nameofclas::... or new nameofclass() it will try to get the class in namespace ressource.
If you want to use the class Ini inside your document you have two solutions :
first give the full qualified name :
require \namespace\of\ini\Ini::get('path/class').'/Resource.php';
second using the "use" keyworld before using the get method :
use \namespace\of\ini\Ini;
require_once Ini::get('path/class').'/Resource.php';
In any case, if Ini is in "no namespace" (global namespace is the accurate word) you just has to use the solutions I gave you but only with \Ini instead of \namespace\of\ini\Ini

Categories