Why does PHP not find my class within the namespace - php

I basically have the following directory structure
MiniCrawler
Scripts/
htmlCrawler.php
index.php
This is the index.php
use Scripts\htmlCrawler;
class Main
{
public function init()
{
$htmlCrawler = new htmlCrawler();
$htmlCrawler->sayHello();
}
}
$main = new Main();
$main->init();
And this is the /Scripts/htmlCrawler.php
namespace Scripts;
class htmlCrawler
{
public function sayHello()
{
return 'sfs';
}
}
The code throws the following error
Fatal error: Class 'Scripts\htmlCrawler' not found in
/mnt/htdocs/Spielwiese/MiniCrawler/index.php on line 9

You forgot to include the file /Scripts/htmlCrawler.php in your index.php file.
require_once "Scripts/htmlCrawler.php";
use Scripts\htmlCrawler;
class Main
{
public function init()
{
$htmlCrawler = new htmlCrawler();
$htmlCrawler->sayHello();
}
}
$main = new Main();
$main->init();
Your index file cannot find the definition of the htmlCrawler file if you never provide the file defining this class, and the use of namespaces doesn't automatically include the required classes.
The reason why frameworks don't require you to include manually the file and you can simply add the use statement is because they're handling the inclusion of required classes for the developer. Most of the frameworks are using composer to handle the automatic inclusion of the files.
You can obtain a somewhat similar functionality using autoloading.

Related

Using class methods in another file not working in WordPress

I'm trying to include a class in PHP and to use the methods from this class in another file. My code looks like that (small reproducable example). By the way: I'm working on a WordPress environment.
Main file:
include 'class-file.php';
$cars = new Cars();
var_dump($cars->getCars());
File class-file.php:
class Cars {
public function getCars() {
return "No Cars";
}
}
I get the following error:
Fatal error: Uncaught Error: Call to undefined method Cars::load() in /..../wp-content/themes/builder/includes/elements.php
Seems that my class instance is connected with another class from the theme. But why? Can I disconnect the class from any others? If yes, how?
Maybe the theme doesn't use namespaces, which makes all its classes discoverable from the global namespace, and by defining your own Cars class, you override the theme's class.
Try to define your namespace, and check if the conflict is gone.
Main file:
include 'class-file.php';
$cars = new \mycode\Cars();
var_dump($cars->getCars());
File class-file.php:
namespace mycode;
class Cars {
public function getCars() {
return "No Cars";
}
}

How to use namespace and use in PHP?

I have file index.php in directory Main;
There are also directory Helpers inside Main with class Helper.
I tried to inject class Helpers\Helper in index.php as:
<?
namespace Program;
use Helpers\Helper;
class Index {
public function __construct()
{
$class = new Helper();
}
}
But it does not work.
How to use namespace and use in PHP?
With Your Description, Your Directory Structure should look something similar to this:
Main*
-- Index.php
|
Helpers*
--Helper.php
If You are going by the book with regards to PSR-4 Standards, Your Class definitions could look similar to the ones shown below:
Index.php
<?php
// FILE-NAME: Index.php.
// LOCATED INSIDE THE "Main" DIRECTORY
// WHICH IS PRESUMED TO BE AT THE ROOT OF YOUR APP. DIRECTORY
namespace Main; //<== NOTICE Main HERE AS THE NAMESPACE...
use Main\Helpers\Helper; //<== IMPORT THE Helper CLASS FOR USE HERE
// IF YOU ARE NOT USING ANY AUTO-LOADING MECHANISM, YOU MAY HAVE TO
// MANUALLY IMPORT THE "Helper" CLASS USING EITHER include OR require
require_once __DIR__ . "/helpers/Helper.php";
class Index {
public function __construct(){
$class = new Helper();
}
}
Helper.php
<?php
// FILE NAME Helper.php.
// LOCATED INSIDE THE "Main/Helpers" DIRECTORY
namespace Main\Helpers; //<== NOTICE Main\Helpers HERE AS THE NAMESPACE...
class Helper {
public function __construct(){
// SOME INITIALISATION CODE
}
}

Importing custom class inside a controller

I created a class at Controller folder of Cake project like this:
<?php
class Hi
{
function __construct(){ }
public function hi()
{
echo "hi!";
exit;
}
}
Then in a controller, I tried to include it:
<?php
namespace App\Controller;
use App\Controller\AppController;
include_once "Hi.php";
class MyController extends AppController
{
public function sayHi()
{
$a = new Hi();
$a.hi();
}
}
Here is the error I'm having:
Fatal error: Cannot declare class Hi, because the name is already in use in path\api\src\Controller\Hi.php on line 2
What's going on?
MyController.php and Hi.php are in the same folder. I'm using PHP 7.
Including a file won't make the classes in that file part of the current namespace, as namespaces are a per-file functionality.
http://php.net/...namespaces.importing.php#language.namespaces.importing.scope
Your Hi class will be declared in the global namespace, and your new Hi() will cause PHP to look for it in the current namespace, ie it will look for App\Controller\Hi, which doesn't exist, hence the composer autoloader kicks in, and will map this via a PSR-4 namespace prefix match to src/Controller/Hi.php, which will include the file again, and that's when it happens.
http://www.php-fig.org/psr/psr-4/
Long story short, while using new \Hi() would fix this, you better not include class files manually, or declare them in paths where they do not belong. Instead declare your files and classes in a proper autoloading compatible fashion, that is for example with a proper namespace in a path that matches that namespace, like
namespace App\Utils;
class Hi {
// ...
}
in
src/Utils/Hi.php

Class not found by Phalcon autoloader

I'm trying to inject a third-party authentication library into my Phalcon application. The file exists at /lib/Foo_Bar_AuthProvider.php:
<?php
namespace Foo\Bar;
class AuthProvider
{
public function authenticate()
{
return true;
}
}
I register this directory with the Phalcon autoloader in my bootstrapper, located at /public/index.php, and add it to the DI:
<?php
try {
//Register an autoloader
$loader = new \Phalcon\Loader();
$loader->registerDirs(array(
'../app/controllers/',
'../app/models/',
'../lib/'
))->register();
//Create a DI
$di = new \Phalcon\DI\FactoryDefault();
$di->set('authProvider', function() {
return new \Foo\Bar\AuthProvider();
});
// ...
}
Then I try to use this component in /app/controllers/AccountController.php:
<?php
class AccountController extends \Phalcon\Mvc\Controller
{
public function loginAction()
{
if (!$this->request->isPost()) {
return;
}
$success = $this->authProvider->authenticate();
if (!$success) {
$this->flash->error('Authentication failed.');
return;
}
$this->flash->success('Authentication succeeded. Welcome!');
return $this->dispatcher->forward(array('controller' => 'index', 'action' => 'index'));
}
}
This throws an exception:
Fatal error: Class 'Foo\Bar\AuthProvider' not found in /public/index.php on line 44
I am pretty new at using PHP namespaces so I'm probably missing something obvious, but I haven't been able to figure it out. I tried adding a backslash before the namespace declaration in Foo_Bar_AuthProvider.php like this:
namespace \Foo\Bar;
This didn't change anything. I also tried removing this backslash from the bootstrapper:
$di->set('authProvider', function() {
return new Foo\Bar\AuthProvider();
});
No dice here either. Finally, I tried adding the use statement to AccountController.php:
use \Foo\Bar;
Also:
use Foo\Bar;
I believe the purpose of the autoloader is to avoid such things, but adding the use statements didn't work anyways.
Read about the PSR-0 standard. Phalcon applies most of their conventions and others PHP Frameworks as well.
From my understanding the _ is only meaningful in the class name, elsewhere underscores are literal. For example...
A class name Foo_Bar_AuthProvider means: in each registered dir search for the Foo/Bar path then check for the AuthProvider.php file. AFAIK, that's useful if you need the file to be under the Foo/Bar path but not necessarily in the Foo/Bar namespace.
Id recommend you to use the "namespace=path" approach that PSR-0 describes.
Try to rename Foo_Bar_AuthProvider.php to AuthProvider.php then put this file into /lib/Foo/Bar. With this done you'll be able to register this lib like this:
$di->set('authProvider', 'Foo\Bar\AuthProvider');

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);
}
//...
}

Categories