I have a few PHP classes which are defined like this:
module1Model.php
namespace App\Modules\module1\models;
class module1Model
{
//... methods etc.
}
module2Model.php
namespace App\Modules\module2\models;
class module2Model
{
//... methods etc.
}
In some other class i want to use those namespaces. So i placed the following lines at the top of my page:
someClass.php
namespace App\Modules\someClass\controllers;
use App\Modules\module1\models; // Works
use App\Modules\module2\models; // Fails
use Core\Logger\TextLogger; // Works
class somceClass
{
//... methods etc.
}
So in someClass i'm trying to use both module1 and module2 models. Which are technically not in the same namespace. Just partially. But why is it giving me an error about it then..??
And what would be a good way to solve this problem? I know i can add this to the second line:
use App\Modules\module2\models as module2; // Now works
But i don't really like to do it that way, since i didn't do it like that in all my other classes (using the as keyword). That feels so inconsistent.
Is there any other way to make this work..? Or am i really forced to use the as keyword in all my use declarations...? :-(
I guess you want to use the model classes, not their whole namespace. If so, then the following just works:
use App\Modules\module1\models\module1Model;
use App\Modules\module2\models\module2Model;
Example:
namespace App\Modules\module1\models {
class module1Model
{
//... methods etc.
}
}
namespace App\Modules\module2\models {
class module2Model
{
//... methods etc.
}
}
namespace App\Modules\someClass\controllers {
use App\Modules\module1\models\module1Model;
use App\Modules\module2\models\module2Model;
use Core\Logger\TextLogger;
class somceClass
{
//... methods etc.
}
}
Related
I'm trying to understand how to use USE in base and extended classes. I have searched around but I don't think I have the correct terminology.
Let's say my base class looks like
namespace App\Classes;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\Legend;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
class ExcelReport
{
public $spreadsheet;
public function __construct()
{
$this->spreadsheet = null;
}
}
and then I extended that class
namespace App\Classes;
class MonthlyExcelReport extends ExcelReport
{
public $id;
public function __construct(int $id)
{
parent::__construct();
$this->id = $id;
}
public function build()
{
$reader = IOFactory::createReader('Xlsx');
}
}
What do I have to do to get the call to IOFactory in the extended class to recognize that use PhpOffice\PhpSpreadsheet\IOFactory; is present in the base class?
I currently get this error Class 'App\Classes\Gap\IOFactory' not found and I don't want to have to repeat all of those use statements in the extended class.
TL;DR;
Namespace is there to allow you to have two classes named the same, but in a different namespace.
Imagine the class Animal\Bear\Claw and Machinery\Compactor\Claw, are things possible with namespaces, when we needed ugly class names like Animal_Bear_Claw and Machinery_Compactor_Claw before the introduction of namespaces in PHP.
Now when you instanciate or use those classes, you don't want to allways have to go in the extends and say
new \Animal\Bear\Claw();
You want to be able to say: "I am in the context of an Animal Factory Pattern and will basically act upon the classes under the Animal namespace, not the Machinery's ones"
So you go:
use Animal\Bear\Claw;
new Claw();
Or
use Animal\Bear;
new Bear\Claw();
Or even, with aliases
use Animal\Bear as MyTeddyBear;
new MyTeddyBear\Claw();
And so, inheriting another class from another containing uses, just does nothing, you'll have to repeat your uses, maybe simplifying them, and most likely, not add uses for class you actually do not use in the said class (did you know that good IDE does prompt you about unused use statement present in your classes and help you add the good ones to your use statements?).
The use statement are not like an include like you seems to believe it.
It is just there to say: "thanks to namespaces, I can have multiple classes with the same name, now the class I want to use is actually under the namespace defined by use"
You are not forced to state a full namespace either in your use statements.
For example:
namespace App\Classes;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
class MonthlyExcelReport extends ExcelReport
{
public function __construct()
{
$reader = IOFactory::createReader('Xlsx');
$workSheet = new Worksheet();
}
}
Could be shortened this way:
namespace App\Classes;
use PhpOffice\PhpSpreadsheet; // This means "all the classes that I am going to use, if not in the same namespace as the current class (App\Classes) would come from the namespace PhpOffice\PhpSpreadsheet"
class MonthlyExcelReport extends ExcelReport
{
public function __construct()
{
$reader = PhpSpreadsheet\IOFactory::createReader('Xlsx');
$workSheet = new PhpSpreadsheet\Worksheet\Worksheet();
}
}
Further reading:
https://www.php.net/manual/en/language.namespaces.faq.php
https://www.php.net/manual/en/language.namespaces.rules.php
Use operator is used to "include" a class.
If you don't use "Use" operator, than you can include as "full path".
In your case:
$reader = IOFactory::createReader('Xlsx');
Should be:
$reader = PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');
I am converting from c# to php and I'm having trouble transitioning in some places. Particularly namespaces. The problem I am having is I have to fully qualify every namespace when calling a class from another namespace. Is this normal?
<?php
namespace Lib\Things;
class TheThings
{
}
then in the other class
<?php
namespace App;
use Lib\Things;
class DoStuff
{
public function doStuff()
{
$things = new TheThings();
}
}
That doesn't work... I end up having to do
new Lib\Things\TheThings();
Or
<?php
namespace App;
use Lib\Things as T;
class DoStuff
{
public function doStuff()
{
$things = new T\TheThings();
}
}
I've also got this in my composer.json file
"psr-4": {
"App\\": "app/",
"Lib\\": "lib/"
}
Is that normal or am I doing something wrong here?
In the PHP manual the use keyword is referred to as importing or aliasing.
This means that
use Lib\Things;
and
use Lib\Things as Things;
are the same. This results that you don't have to use the fully qualified names to instantiate classes from a namespace, you can use only the alias of the imported namespace. So in your case, the following would have worked:
<?php
namespace App;
use Lib\Things;
// same as:
// use Lib\Things as Things; // explicit alias
class DoStuff
{
public function doStuff()
{
$things = new Things\TheThings();
}
}
(Note that this is the same as your second example, the only difference is that the alias is not explicitly set here to T (and defaults to Things).
To be able to use the class name without any namespace prefix, you will have to set the alias of the actual class:
<?php
namespace App;
use Lib\Things\TheThings;
// same as:
// use Lib\Things\TheThings as TheThings; // explicit alias
class DoStuff
{
public function doStuff()
{
$things = new TheThings();
}
}
In conclusion, if you start thinking about the use operator as setting an alias for a namespace or class (or other), you will get the hang of it.
PS 1:
Before PHP 7, if you wanted to import multiple classes from the same namespace, you had to write:
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;
From PHP 7.0 onwards, classes, functions and constants being imported from the same namespace can be grouped together in a single use statement:
use some\namespace\{ClassA, ClassB, ClassC as C};
PS 2:
composer helps in automagically including/loading the actual php files, based on some PSR* rule, it does not have any role in how namespaces work in bare PHP.
When you do:
$things = new TheThings();
Class is searched on the current namespace (App in your example), thats why not worked.
So, you need to specify full class namespace, so interpreter know which class are you refering, you could also have a namepsace2/TheThings and this/is/another/namespace/TheThings classes.
Just include full class namespace
use Lib\Things\TheThings;
Have encountered an issue I can't seem to figure out now by myself.
Using Symfony autoload module.
Here's my factory:
namespace Core\Factories;
use \Core\Gateway;
class DatabaseAccessFactory {
// Define client type
const DEF = 'mongo';
public function createObject($type) {
switch($type) {
case self::DEF:
return new MongoClientGateway();
break;
default:
return false;
}
}
}
Example of /Core/Gateway/MongoClientGateway.php
<? namespace Core\Gateway;
class MongoClientGateway implements MongoDbGateway {
public function setUp(){
}
public function query(){
}
public function save(){
}
}
So, basically I'm using "use" keyword to load gateway namespace into my current one, and then I try to instantiate a class that is under \Core\Gateway namespace, but it says class is not found. Am I missing something?
You need to specifcy the class as well
use Core\Gateway\MongoClientGateway
or access the class with the namespace you used
new Gateway\MongoClientGateway
Btw, there's no need for the first "\" in use \Core\Gateway
It's use Foo\Bar, without leading backslash.
use Foo\Bar does not mean that every Class implicitly resolves to Foo\Bar\Class now. use Foo\Bar is shorthand for use Foo\Bar as Bar, so you can reference the namespace Foo\Bar using merely Bar. use is not "importing a namespace", it's aliasing a namespace to a shorter name.
Therefore you need to write Gateway\MongoClientGateway, or use Core\Gateway\MongoClientGateway explicitly if you want to be able to write just MongoClientGateway.
you used "use" wrong.
waht "use" does, is to tell your code where class comes from.
sample code:
use \my\namespace\className
new ClassName();
this will make the className accassible without a namespace.
My current code is as following:
namespace Libraries;
class_alias('Libraries\ORM', 'ORM');
class ORM
{
public function __construct() {}
static public function someMethod()
{
// do something
}
}
I thought I could shortcut the namespace as you can see above, so I only needed to call the ORM::someMethod(); instead of \Libraries\ORM::someMethod();
(I am using the ORM class in another namespace, lets says 'Project')
Is this possible or what is the right solution?
I know that I could store the class in a global namespace, but then I still need to use the global slash like: \ORM::someMethod();.
Thanks!
Simply alias the classname when you are importing it:
namespace SomethingEntirelyDifferent;
use Libraries\ORM as ORM;
ORM::someMethod();
I have been searching websites to try and get a handle on using PHP namespaces, but they all seem quite vague but what they're trying to do is easy to understand!
My question is: I have a file called people.php and in it is defined class called people. If I create another file called managers.php in the same folder can I define a class again called people which extends the original people class but in the namespace of managers, if so do I have to 'include' the original people.php and if so do I put the include after the writing: namespace managers?
Namespaces are a way to group your related classes in packages. What you describe could best be put under a single namespace like
<?php // people.php
namespace com\example\johnslibrary\people;
abstract class People {
}
and then
<?php // manager.php
namespace com\example\johnslibrary\people;
require_once 'path/to/People.php'; // can better use autoloading though
class Manager extends People {
}
because a Manager is a subclass of People, so there is not much of a reason to put them into their own namespace. They are specialized People.
If you want to Managers to be in their own namespace, you can do so, but have to use the fully qualified name when using the extends keyword, e.g.
<?php // manager.php
namespace com\example\johnslibrary\managers;
require_once 'path/to/People.php';
class Manager extends \com\example\johnslibrary\people\People {
}
or import the People class first
<?php // manager.php
namespace com\example\johnslibrary\managers;
use com\example\johnslibrary\People as People;
require_once 'path/to/People.php';
class Manager extends People {
}
See the PHP Manual on Namespaces for extensive documentation.
// people.php
<?php
namespace People;
class People {}
// managers.php
<?php
namespace Managers;
require_once __DIR__.'/people.php';
class People extends \People\People {}
I have old PHP Class and i need to use it in new PHP file as for example:index.php has to use iClass.php. But before using the OLD iClass.php i have to modify it as below, so that i can use it in index.php.
iClass.php:
namespace ic;
class iClass {
public static function callMeFromClass() {
echo 'OK - you have called me!';
exit;
}
}
index.php
namespace inex;
require_once 'iClass.php';
use ic\iClass;
iClass::callMeFromClass();