How to use namespace and use in PHP? - 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
}
}

Related

PHP autoload within namespace

So, I'm converting some old code into a namespace, and trying to get autoload working. I've managed to follow the many good answers on this site about how to account for the namespace part of an autoloaded class (How do I use PHP namespaces with autoload?) - no problem.
Here's a different wrinkle, though. How do I autoload classes within the same namespace?
My autoload function (defined in a global include) is something like this:
function app_autoload($class)
{
$path = __DIR__.'/'.str_replace("\\", DIRECTORY_SEPARATOR, $class).'.php';
if (file_exists($path))
{
require_once($path);
}
}
spl_autoload_register('app_autoload');
If I have a class defined in the namespace app\nstest, I can autoload it just fine from most of my system:
namespace app\nstest;
class Test1
{
function hello()
{
echo "Hello world";
}
}
However, another class in the same namespace has issues:
namespace app\nstest;
class Test2
{
function callMe()
{
$test1 = new Test1();
}
}
If I explicitly include/require the Test1 file at the top of Test2, no problems, but the autoloader doesn't seem to be aware of the namespace, so it's loading "Test1.php" instead of "app/nstest/Test1.php".
I also tried checking the __NAMESPACE__ inside the autoloader, but it's empty.

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

Why does PHP not find my class within the namespace

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.

Autoload parent class from a different directory

I´m having a hard time trying to autoload parent classes
this is my directory structure
controllers
--- Homepage.php
core
--- Controller.php
index.php
This is the content of my index.php
function __autoload($class_name)
{
$file_name = str_replace("\\", DIRECTORY_SEPARATOR, $class_name) . '.php';
include $file_name;
}
$homepage = new \Controllers\Homepage();
$homepage->index();
This is the content of my controllers/Homepage.php file
namespace Controllers;
class Homepage extends Controller
{
public function index()
{
echo 'Homepage::index';
}
}
and this is my core/Controller.php
namespace Core;
class Controller
{
protected function something()
{
echo 'blablabla';
}
}
when i run index.php the autoloader loads Hompege correctly but is looking for Controller.php in the controllers directory I tried extending from class Homepage extends Core\Controller but now is trying to get it from controllers/core
This is how the namespaces are resolved:
class Homepage extends Controller
Controller is resolved to Controller\Controller because it is a non-qualified class name (like a relative file path), and the current namespace is used.
class Homepage extends Core\Controller
Core/Controller is resolved to Controller\Core\Controller because it also is a non-qualified class name and a sub-namespace of the current namespace is used
class Homepage extends \Core\Controller
\Core\Controller is a fully qualified class name and will be resolved to Core\Controller
use Core\Controller; class Homepage extends Controller
Here the use statement specifies that a non-qualified Controller is treated as Core\Controller
Variants 3 and 4 will work as intended.

call different namespace or class from one in PHP

on index.php I have below code
require 'Bootstrap.php';
require 'Variables.php';
function __autoload($class){
$class = str_replace('Control\\', '', $class);
require_once 'class/'.$class.'.php';
}
$bootstratp = new Control\Bootstrap();
on Bootstrap.php
namespace Control;
class Bootstrap{
function __construct(){
Constructor::load_html();
self::same_namespace_different_class();
}
static function same_namespace_different_class(){
Variables::get_values();
}
}
in class/Constructor.php
class Constructor{
static function load_html(){
echo 'html_loaded';
}
static function load_variables(){
echo 'load variables';
}
}
and on Variables.php
namespace Control;
class Variables{
static function get_values(){
Constructor::load_variables();
}
}
Assume, In total I have 4 PHP files including 3 Class files of 2 different namespaces. I also have a __autoload function on index.php that will call classes from 'class' folder but my 'Control' namespace files are in root folder.
When I echo the class name in __autoload i get the all the class names starting with 'Control\' even when I am calling a class from global namespace.
I am getting below error
Warning: require_once(class/Variables.php): failed to open stream: No such file or directory in _____________ on line 10
what is wrong with my code??
When I echo the class name in __autoload i get the all the class names starting with 'Control\' even when I am calling a class from global namespace.
This is because in Bootstrap.php all the code is in Control namespace (namespace Control). So when you use:
Variables::get_values();
you call
\Control\Variables::get_values();
if you want to use Variables from global namespace you should use here:
\Variables::get_values();
Of course, the same happens for in Variables.php file:
Constructor::load_variables();
As Constructor is defined in global namespace (in class/Constructor.php there is no namespace used), you should access it here using:
\Constructor::load_variables();
If it's still unclear you could also look at this question about namespaces in PHP.
You should also notice that using __autoload is not recommended. You should use spl_autoload_register() now. Documentation about autoloading

Categories