Multiple classes in a file but order matters when calling them - php

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.

Related

Trouble in paradise with namespaces. Class is accessible in methods but not on extends

I have trouble understanding the import behavior. Let me explain, I have a class B outside of any namespace (for some reason I have double autoload, a proprietary one, and the classic PSR-4, I guess this can have something to do with my issue, I'm ready to gather more information on this tidbit if necessary). In this class I import a class A from a namespace, and it turns out when in a method of my children class I can use the A class to instantiate an object, but when I try to tell class B to extend class A it says the FQN is not found.
<?php
use \App\Services\AbstractController as BaseController;
class BarController extends BaseController
{
public function test() {
$foo = new BaseController();
}
}
There I would have an error on the "class BarController extends BaseController" line saying BaseController can't be found, but if I delete the extends part, the test method will run smoothly with its instantiation (I did try to manipulate the object, it sure works well).
so I guess my question is, is there any difference on the treatment of a class to extend vs. using it to instantiate an object.
Thanks in advance for your thoughts, and I'm ready to answer any additional question.
I did manage to deal with the issue. The controller class was instantiated inside the proprietary autoloader but the method was called later on the process. I switched both autoloader order (ie. first psr-4 then proprietary one) in the init and it works well.

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 namespace error?

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

PHP: Interfaces and inheritance in a name spaced environment

I am trying to use a interface or child class to work in a situation where I am using class hints on a method argument and keep getting the following warning:
$print_r(class_parents($listing));
$propertyTable -> getPhotos($listing);
Array ( [Tools\Object\Property] => Tools\Object\Property )
Catchable fatal error: Argument 1 passed to Tools\Db\PhotoTable::getPhotos() must be an
instance of Tools\Db\Property, instance of Tools\Object\Listing given, called in ...
and defined in ...
This is strange as you can see when tested listing extends property (see below). Why would I get this error?
I have set up a very basic test case and have figured out that type hints should accept a child class or a class that implements the required class where that class is an interface. However, in a name spaced Zend Framework 2 environment I cannot get this to work.
My code for the various classes looks like this:
namespace Tools\Db;
class PhotoTable
{
public function getPhotos(Property $propertyObject )
{
//code goes here
}
}
namespace Tools\Object;
use Tools\Object\PhotoInterface as PhotoInterface;
class property //implements photoInterface
{
public function getUrl(){ code goes here}
public function getPhotos(){ code goes here}
}//end class
use Tools\Object\PhotoInterface as PhotoInterface;
class Listing extends Property implements PhotoInterface
{
//code goes here
}
namespace Tools\Object;
interface PhotoInterface
{
public function getUrl();
public function getPhotos();
}
I can get the code above to work if I copy this all into a single file and eliminate the namespaces. Basically:
if I require property in PhotoTable I can pass Listing as it extends property.
If I require PhotoInterface I can pass Listing as it implements this interface.
But I get this weird error when I have essentially the same classes in a different files in a name spaced Zend Framework 2 environment.
Is there an extra complication in a name spaced environment I need to take into account of or am I missing something really basic.
It appears that the issue involved the name-spaced files included in the head of the script. Specifically, it appears you need to include not only the class being am passed, but also the specified parent classes or any Interface classes if they are specified in the type hint.
To give an example if my class type hint suggests I need 'property' class, then if I am sending it the 'Listing' object, it seems I need to include property in the header like this:
namespace Tools\Object;
use Tools\Object\Property; //the parent class
use Tools\Object\Listing; //the child class
This eliminates the fatal error, but it seems strange that PHP cannot automatically determine the class automatically. I assume it is something to do with the complexities of a name spaced environment.

Categories