Custom Exception not found in Cakephp3 - php

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.

Related

How can I correctly use/import an interface in a php class?

I can't make interfaces work in my php/laravel project. I have a series of Controllers, which I want to implement an interface. And PhpStorm seems happy with my syntax. But I get a runtime error that the interface is not found, when I make a check if the current object indeed has the interface:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use iTeamEntryController;
class TeamController extends Controller implements iTeamEntryController {...}
and then the Interface:
<?php
use Illuminate\Http\Request;
interface iTeamEntryController
{
public function saveTeam(Request $request);
}
Here I get an error on the line defining the class, saying that interface 'iTeamEntryController' is not found. Both the class and the interface exists in the same folder.
I've been trying to find an example online, but everyone either has both the interface and the class declaration in the same file, or uses 'include_once' or 'require_once', which to me seems to be referring to files, and not OOP. So what am I doing wrong here? Why can't my interface be found?
Remember that the use clause wants you to specify an absolute class/interface/trait name, not relative to your current namespace.
The below is wrong, unless your controller is in a global namespace (which I'm sure isn't the case):
use iTeamEntryController; // wrong
And this - below - is correct:
use App\Http\Controllers\iTeamEntryController;
If you keep your interface in app/Http/Controllers directory, don't forget to specify a namespace:
namespace App\Http\Controllers;
If you want, on the other hand, your interface to be in a root directory, make sure it is there. Then, the namespace is not needed and your use clause is correct. Except, I'm pretty sure you don't want your interfaces in the root directory of your Laravel app.

Defining new Exceptions on Yii2

I'm developing some web services with Yii2 framework.
When I was writting one of the functionalities of a controller, I defined a custom exception that extends Exception on the same file as controller.
class CustomException extends Exception {}
Then I saw that I need the same exception for other controllers.
And I think: DRY!
I created a file CustomExceptions.php on \components with:
namespace app\components;
The problem is that now I'm importing this exception with 'use' key:
use \app\components\CustomException;
It seems that everything works well, and my IDE (JetBrains) is able to find the custom exception code.
But then when I run this code It fails.
I don't know why but It seems that It can't find this class.
What I'm doing wrong?
Thanks!!
I found this: yii2: Proper way to throw new exception
So u can ovveride UserException:
<?php
namespace app\components;
use yii\base\UserException;
class CustomException extends UserException
{
}
Try to
use app\components\CustomException;
instead of
use \app\components\CustomException;

Laravel 4 Add Method to Class (IoC / Namespaces)

I'm trying to figure out how to add a method to a class in a Laravel package, so that all controllers and models that call that class can access the new method. How do I replace this class in the IoC?
This is the package in question, Angel CMS. The package is my creation, so I can modify it if we need to add aliases or anything to accomplish this.
Let's say I want to add a method to this class:
vendor/angel/core/src/models/PageModule.php
Okay, so I copy the class file to here:
app/models/PageModule.php
And then I modify the copied file, adding a namespace and the desired custom_function method:
<?php namespace MyModels;
use Eloquent;
class PageModule extends Eloquent {
protected $table = 'pages_modules';
public static function custom_function()
{
return 'It works!';
}
}
As you can see, I am using the MyModels namespace here.
Then, I run a composer dump-autoload.
Next, I open up my app/routes.php and register the binding and set up a test route:
App::bind('PageModule', function($app) {
return new \MyModels\PageModule;
});
Route::get('test-binding', function() {
return PageModule::custom_function();
});
But, when visiting the test route, I always receive the same error that the method is undefined.
What am I doing wrong here? Thank you in advance for any help.
To Clarify:
I am attempting to replace the class application-wide so that all other classes (controllers/models/etc.) that call PageModule will have access to the custom_function method. Thanks.
To be honest, I'm pretty new to all this IoC, dependency inversion/injection concept too. But I think I've gone through the same struggle before. What I would do, as much as my knowledge allows, is...
Add a constructor to src/controllers/admin/AdminPageController.php:
protected $pageModule;
public function __construct(PageModule $pageModule)
{
$this->pageModule = $pageModule;
}
Then where you did $module = new PageModule in the same file. You replace it with:
$module = $this->pageModule;
The two modifications above makes use of Laravel's IoC to allow injecting a different PageModule object into your controller, instead of strictly creating PageModule in your code.
Now at this point Laravel should know that when it constructs the AdminPageController, it should create a PageModule and inject into the controller for you.
Since your controller now expects a PageModule class, you can no longer do class PageModule extends Eloquent in your app anymore, because even though the name is the same, PHP does not think that it is! You'll need to extend it:
So let's rename your app/models/PageModule.php to app/models/CustomPageModule.php, and in the file change the class to:
class CustomPageModule extends \PageModule {
Up to this point, you also have a CustomPageModule class that is a child of your package's PageModule. All you need to do now is to let Laravel knows that if any controllers ask for PageModule, it should serve the controller with your MyModels\CustomPageModule instead.
So at the top of your app's routes.php file:
App::bind('PageModule', 'MyModels\CustomPageModule');
Your AdminPageController should now be using your CustomPageModule and can use whatever public methods that are in there!
I'm expecting to be editing this answer heavily since this will be quite a long discussion. My first try at answering above isn't the best code you can write, but I hope it takes the least amount of edit to the original code, and then we can work up from there.
Or fast track by reading up articles like http://culttt.com/2013/07/08/creating-flexible-controllers-in-laravel-4-using-repositories
You probably have a alias for the PageModule facade, you should override this alias using your class \MyModels\PageModule in your app/config/app.php file.
Be careful, it seems like you are overwriting the PageModule class instead of extending it. You should probably extend the parent class instead of Eloquent.

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.

Adding PHP namespaces into an existing ZF1 application

I'm trying to integrate PHP namespaces into an existing Zend Framework project (v1.12). When I add namespacing at the top of a working controller, it doesn't work anymore and the application throws an Invalid controller class error. Here's my controller definition :
namespace MyProject\Controller;
use MyProject\Controller\MyRestController;
class MyFooController extends MyRestController
{
}
and the init method within the Bootstrap.php:
protected function _initAutoload()
{
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('MyProject');
return $autoloader;
}
Just a guess (have not used ZF for quite some time): Zend will not accept any class as a controller, just those extended from the framework's base controller class. As you don't extend from the frameworks base controller class you see the error.
If that is the reason, take care you initially extended from the base framework controller class or you implemented the needed interface.
namespace MyProject\Controller;
class MyRestController extendes Zend_Framework_Base_Controller_Class_Name_Here
{
...
p.s. the use MyProject\Controller\MyRestController; looks superfluous as that class is in that namespace already. Let's review your code:
namespace MyProject\Controller;
This sets the namespace of the file. That means, non-FQCN will resolve into it. For example:
new MyRestController();
Resolves to the following FQCN:
new MyProject\Controller\MyRestController
Which - oha! - is exactly what you wrote in use:
use MyProject\Controller\MyRestController;
Which means, that this use clause is superfluous, the extend in:
class MyFooController extends MyRestController
Would go to it anyway at first. Because it's the same namespace.
I am facing similar problem now. For me this looks like that Zend cannot properly resolve namespaced controller name. So when I put for example IndexController into namespace \Basic\Controller, it will be not loaded because Zend want to load \IndexController class, which does not exist.
I am thinking about extending standard zend router class, which has method getControllerName.
Then I can set this in bootstrap by:
$router = new \My\Namespaced\Router();
$front = Zend_Controller_Front::getInstance();
$front->setRouter($router);
I didn't tried that code yet but this should work.

Categories