PHP namespace error? - php

PHP 5.6
This code:
<?php
namespace Database
{
abstract class Model
{
}
}
namespace Models
{
use Database\Model as DbModel;
class Model extends DbModel
{
}
}
namespace Models
{
use Database\Model;
class Brand extends Model
{
}
}
namespace
{
$m = new \Models\Model();
}
causes an error:
"Fatal error: Cannot use Database\Model as Model because the name is already in use in D:\OpenServer\domains\localhost\index.php on line 23".
This code:
<?php
namespace Models
{
use Database\Model as DbModel;
class Model extends DbModel
{
}
}
namespace Models
{
use Database\Model;
class Brand extends Model
{
}
}
namespace Database
{
abstract class Model
{
}
}
namespace
{
$m = new \Models\Model();
}
has no errors.
Why is this happening? Because the code has not been changed.

The ordering of your namespace clauses makes the difference here; in the first example, the Database namespace clause is declared before the clause that defines the class Models\Model.
A similar example of that difference can be found in the documentation:
(...) However, the next example causes a fatal error on name conflict because MyClass is defined in the same file as the use statement.
Separate files or same file here is simulated by moving the Database namespace below or above, respectively.
That said, the documentation also states:
It is strongly discouraged as a coding practice to combine multiple namespaces into the same file. The primary use case is to combine multiple PHP scripts into the same file.
Update
Interestingly, this problem is what Drupal 8 developers recently found out as well, but according to this bug report it has been reported more than two years ago.
A pull request has been submitted to address this issue for the next major version (it may be back ported to 5.x as well).

After few tests: PHP file with few namespaces behave difficult to understand, try to do not use more then one namespace in one file.
(It's because of linking to not existing classes while parsing [of one file!] that change order of PHP parsing, C++ things [pointers] - I can't explain that.)
As PHP doc says:
"It is strongly discouraged as a coding practice to combine multiple namespaces into the same file."
More about tests I did and documentation we studied to find it out:
https://chat.stackoverflow.com/rooms/71776/discussion-between-axiac-and-jack

Related

Multiple classes in a file but order matters when calling them

I'm making the design choice of having an enum and class in the same file. The class has existed for a while, but I have just added the enum for the first time.
namespace App\Models;
enum ProcessType: string
{
//...
}
class Process extends Illuminate\Database\Eloquent\Model
{
//...
}
If I call the ProcessType enum, I get an error, Class "App\Models\ProcessType" not found
// This code produces an error
dump(ProcessType::AGENT_UPLOAD);
dump(Process::query());
However, If I use the Process class first in the code, there is no error and the enum works as intended.
// This code is okay
dump(Process::query());
dump(ProcessType::AGENT_UPLOAD);
I have tried running composer dump-autoload because I thought it might have something to do with the class mapping, but that didn't help. All I want to do is call the ProcessType enum independently of the Process class.

PHP Symfony error: "did you forget to use a use statement", regardless of class/function

I have started building a new Web App using Symfony, but am having issues using classes.
PhpStorm is able to find the functions within the classes (due to the fact that it gives suggestions when you type $className->.
Also, to prove this is not the same as the other similar questions, I have over simplified it, and even so, the error still occurs.
I have the below in my DefaultController:
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use testBundle;
use AppBundle\domainionClasses\firstlevelchecks;
class DefaultController extends Controller
{
/**
* #Route("/register",name="register")
*/
public function registerAction(){
$testClass = new firstlevelchecks();
$testing = $testClass->donothing(); //the IDE knows that the function donothing() exists, in fact it suggests it.
return new Response('');
}
}
The below is the php class located in AppBundle/domainionClasses/test1.php
<?php
namespace AppBundle\domainionClasses;
class firstlevelchecks
{
function donothing(){
return null;
}
}
When loading the /register route, the below Symfony error is displayed:
Attempted to load class "firstlevelchecks" from namespace "AppBundle\domainionClasses".
Did you forget a "use" statement for another namespace?
It is attempting to load the class from the correct name space, and I have used a use statement.
Is there anything I am missing here, or is there a problem with Symfony? This is the first time I used the new version of PhpStorm, and have just downloaded the plugin, also the first time I have experienced this issue :(
Because your file is named test1.php, how can the autoloader know which file to include ?
You shoud rename it to firstlevelchecks.php (= the name and case of your class).

Custom Exception not found in Cakephp3

I want to create and use a custom exception class in my CakePhp Application.
So I created a DuplicateConfigurationException.php with the following class skeleton:
<?php
namespace Cake\Exception;
class DuplicateConfigurationException extends Exception{
} ?>
I a controller, where I wish to raise the Exception, I added
use Cake\Exception\DuplicateConfigurationException;
and within a function I call
throw new DuplicateConfigurationException();
Following suggestions throughout the interwebs, I have tried to place the php file in the following locations, but neither of them seems to work:
src/Exception
src/Exceptions
src/Lib
src/Lib/Error
src/Lib/Error/Exceptions
I always get an error:
Error: Class 'Cake\Exception\DuplicateConfigurationException' not found
File /host/var/www/src/Controller/StructuresController.php
Line: 246
What else do I need to do to make Cake recognize my custom exception?
I'm well aware of Loading custom class in CakePHP3, but since this exception is not a separate library I would rather not place it within vendor?
A bit late but I think it might be useful for other users with the same question to have some further explanations.
In fact, with your solution, you rely on native PHP SPL Exception class located in global namespace.
To use Cake's basic Exception class, you missed to add
use Cake\Core\Exception\Exception;
in src/Exceptions/DuplicateConfigurationException.php for loading Cake Exception class constructor. See Cake's book
Your code is working because Cake is handling SPL exceptions the same way than its own Exception class. If you've wanted to go further with a custom handler for instance, it may have broken logic.
Note that class IniPermissionsException extends \Cake\Core\Exception\Exception {}; is also working. In this case, you must prepend \ as the root namespace when calling a class in an extends statement because you need to provide full namespace path.
To swim like a dolphin in Cake's namespaces, just go to API reference.
Full updated code for src/Exceptions/DuplicateConfigurationException.php :
<?php
namespace App\Exceptions;
use Cake\Core\Exception\Exception;
class DuplicateConfigurationException extends Exception {}
?>
Ok, after some fiddling I managed to get it working:
in src/Exceptions/DuplicateConfigurationException.php
<?php
namespace App\Exceptions;
class DuplicateConfigurationException extends \Exception{
} ?>
in the controller:
use App\Exceptions\DuplicateConfigurationException;
...
function somefunction(){
throw new DuplicateConfigurationException();
}
Apparently the namespace should be App\<Folder> and App\<Folder>\<Classname>, respectively.
And I had to prepend Exception with a backslash, since it is used in a namespaced context: http://www.php.net/manual/en/language.namespaces.global.php
Still, I'm not sure where the namespace conventions for CakePhp 3 are documented.

PHP namespace confusion, class not found

I have two classes in the same folder in own files. But when I am trying to extends one to another it is giving namespace and class not found error.
Info: It is the first time I am extending class using namespace. Also nested namespace is new to me. DB\CRUD So may be I am doing
completely wrong with namespace.
Error message:
Fatal error: Class 'DB\AT_Database' not found in /var/www/...
DB class
File: AT_Database.php
namespace DB;
class AT_Database
{
...
}
CRUD class
File: AT_CRUD.php
namespace DB\CRUD;
use DB\AT_Database;
class AT_CRUD extends AT_Database
{
public function __construct()
{
}
}
This may be silly mistake or may be I have overlooked it (which I should not as a programmer) and that is loading sequence of the class.
May be it's not worth to have as an answer but just adding so by chance in future it can help to someone who make such mistake.
As I mentioned in one of my comment, I am using glob to auto load all class files to include.
foreach ( glob( $this->classes_dir . "/*.php" ) as $class ) {
include_once $class;
}
Now my file names are AT_CRUD.php and AT_Database.php. Here I realized that php loads files in alphabetical order. So when I extends AT_Database class into AT_CRUD its never found.
This is just because php loads AT_CRUD first than AT_Database so either I have to instantiate the class into or to use something like dependancy injection as #prehfeldt mention in his comment.

php psr autoload ambiguity

I am working on a php sdk rewrite project and the client wants to get PSR standards done. I am looking at the standards page here
https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
One thing what i am not able to understand, if i use name spaces in my class do i still need to use include or require or use. I mean the whole reason of autoload beats the purpose right ?
For example, say i have a class this way,
namespace Employee\Department;
Class Department
{
//code
}
and i have another class which uses this class by extending it,
namespace Employee\community;
Class Community extends Department
{
//code
}
so does the above code make it to psr-0 standard considering that i have an autoload function exactly thats on the link above.
The second example is going to assume Department is in the Community namespace so in this case you would need a use statement. Also both of your examples would use the namespace Employee not Employee\Whatever for example lets assume the following layout:
Employee/
Community.php
Community/
Manager.php
Department.php
Department/
Manager.php
Then we would see the class/namespaces like the following
namespace Employee;
class Department {
}
///////////
namespace Employee;
class Community extends Department {
}
/////////////
namespace Employee\Department;
class Manager {
}
/////////////
namespace Employee\Community;
use Employee\Department\Manager as BaseManager;
Class Manager extends BaseManager {
}
For your understanding, autoloading works by registering the autoload function in the autoload stack via spl_autoload_register; this allows the function to be invoked whenever a new Class() statement is executed (more info).
On the other hand, the FIG standard for autoloading, PSR-0, defines how a namespace will be translated into a filename by a PSR-0 autoloader function. For example, given the namespace Vendor\Foo, the autoloader will look for the file Vendor/Foo.php having the following code
namespace Vendor;
class Foo
{
public function do()
{
echo "Foo";
}
}
Therefore, following the mandatory requirements, a PSR-0 compliant namespace resolves to the correct PHP file which could otherwise have been included using a require or include.
If I read your intentions correctly, you just need the following namespace in both code snippets:
namespace Employee;
Of course, this is not a PSR-0 namespace because there is no vendor name (unless your vendor name is 'Employee'). Anyway, using this namespace in your two code snippets will work fine.
However, if you intended to keep them in separate namespaces, then the autoloader won't figure out Department in extends Department in the second snippet. You will have to either import the namespace or explicitly specify it as so:
namespace Employee\community;
class Community extends Employee\Department\Department
{
//code
}
I imagine that you did not expect the full class names from your snippets to be Employee\Department\Department, and that is why I first suggested keeping the same namespace for your purposes.

Categories