Phalcon: Inheritance of controllers with modules and common controllers - php

I hope that someone will be able to help me as I've been going a little crazy trying to get this to work. I have done numerous searches online and find tidbits of information, but unfortunately, I can't seem to get to a solution.
I'm trying to achieve the following in Phalcon with multiple modules.
MasterController extends Controller
BackendController extends MasterController
ModuleController extends BackendController
ClientsController extends ModuleController
The folder structure I have is this:
apps
|->crm
|-->controllers
|--->ModuleController
|--->ClientsController
common
|->controllers
|-->MasterController
|-->BackendController
Now in my Modules.php file under CRM I have the following:
$loader->registerNamespaces(
array(
'Multiple\Crm\Controllers' => __DIR__ . '/controllers/',
'Multiple\Crm\Models' => __DIR__ . '/models/',
'Multiple\Crm\Plugins' => __DIR__ . '/plugins/',
'Multiple\Common\Controllers' => __DIR__ . '/../../common/controllers/'
)
);
My ModuleController file looks like this:
class ModuleController extends Multiple\Common\Controllers\BackendBase
{
public function onConstruct()
{
echo "hello";
}
}
Whenever I run the code, I end up with the following fatal error:
Fatal error: Class 'Mulitple\Common\Controllers\BackendBase' not found in /var/www/phalcon/html/apps/crm/controllers/ModuleController.php on line 8
I have tried numerous things, but I cannot seem to get it to work. Can anyone shed some light on this and tell me what I'm doing wrong?
Many thanks in advance.

After reviewing the comments by #cvsguimaraes and #NikolaosDimoploulos I took the option to "start again". I used the phalcon devtools to generate the basis of the structure using the apps option.
Based on this I was then able to "build" the structure up from there.
In order to have the inheritance I was after this is what I ended up with:
#File: apps/crm/controllers/ClientsController.php
namespace myApp\CRM\Controllers
class ClientsController extends ControllerBase {...}
#File: apps/crm/controllers/ControllerBase.php
namespace myApp\CRM\Controllers
class ControllerBase extends \myApp\common\Controllers\FrontendBase {...}
#File: common/controllers/FrontendBase.php
namespace myApp\common\Controllers
class FrontendBase extends \myApp\common\Controllers\MasterBase {...}
#File: common/controllers/MasterBase.php
namespace myApp\common\Controllers
class MasterBase extends \Phalcon\Mvc\Controller {...}
Then in the file: apps/crm/Module.php I have the following:
namespace myApp\CRM;
class Module implements ModuleDefinitionInterface
{
public function registerAutoloaders()
{
$loader = new Loader();
$loader->registerNamespaces(array(
'myApp\CRM\Controllers' => __DIR__ . '/controllers',
'myApp\CRM\Models' => __DIR__ . '/models',
'myApp\common\Controllers' => __DIR__ . '/../../common/Controllers',
'myApp\common\Models' => __DIR__ . '/../../common/Models'
));
$loader->register();
}
}
This then works as you would expect. You can have functions in the MasterBase that you can call from the higher levels and you can also run functions such as adding css and JS to the output at the different levels, allowing you to separate out the control as you need.

Related

Extending h5p renderer

I have been trying to extend the class of h5p renderer but to no avail.
I guess there could be tons of 'renderer' classes in the system, that is why I get the error.
What I do:
require the main class file:
require_once($CFG->dirroot . '/h5p/classes/output/renderer.php');
The class looks like this:
namespace core_h5p\output;
use plugin_renderer_base;
class renderer extends plugin_renderer_base {
Then in my theme I try to extend this class:
class theme_mytheme_renderer extends renderer {
but this generates an error Exception - Class 'renderer' not found
How can I make it work?

Phalcon php namespaces cant use

So I have Users model namespaced:
namespace App\Models;
use Phalcon\Mvc\Model;
class Users extends Model
{
And Controller:
use \Phalcon\Mvc\Controller;
use \App\Models\Users;
class LoginController extends Controller
{
...
public function postLoginAction() {
$user = Users::findFirst([ ...
}
...
Always getting error Fatal error: Uncaught Error: Class 'App\Models\Users' not found in no matter what, tried every variation no idea what's wrong with it. even my IDEA resolving this class correctly.
Everything is working if I remove my namespacing.
UPDATE:
So if you generated project with phalcon dev tools and then started generate other things (model, controllers) you will need to provide namespace for model and it will not work, you will also need to update app/config/loader.php like this:
<?php
$loader = new \Phalcon\Loader();
/**
* We're a registering a set of directories taken from the configuration file
*/
$loader->registerDirs(
[
$config->application->controllersDir,
$config->application->modelsDir
]
)->register();
$loader->registerNamespaces(
[
'App\Controller' => $config->application->controllersDir,
'App\Model' => $config->application->modelsDir,
]
)->register();
In other words register namespace, I don't know why this not clearly stated in documentation but it seams this framework have many such "black holes" or I don't understand this framework fundamentals (came from codeigniter and Laravel background).
Try this in your bootstrap file:
// registers namespaces
$loader = new Loader();
$loader->registerNamespaces([
'App\Controllers' => APP_PATH . '/controllers/',
'App\Models' => APP_PATH . '/models/'
]);
$loader->register();
Btw, APP_PATH could be a constant to your app's directory, or whatever you want/need.

Namespace with extends or interface causes Fatal Error without autoloader

Why doesn't this work?
web/index.php (Not web/src/App/App.php)
<?php
namespace App;
// web/index.php
require_once __DIR__ . '/../vendor/autoload.php';
$app = new App();
class App extends \Silex\Application {
public function __construct()
{
parent::__construct();
echo 'Worked!';
}
}
I also tried namespace App {...}, no change. It throws this exception:
Fatal error: Uncaught Error: Class 'App\App' not found in /path/to/web/index2.php:8
Stack trace:
#0 {main}
thrown in /path/to/web/index2.php on line 8
As long as I remove the extends ... and the parent call part, it works. I also noticed interface does the same thing (trying to use Serializable). Is this an issue with the autoloader being confused? Is there a way to do this without putting the App\App class into a file in src\App\App.php?
Note: this is an exercise to build a single-file application with Silex, so "just put it in a file" isn't an answer. I want to know why this doesn't work, which has an answer.
The problem in your code is,
In namespace, You are initiating class object before it being declared and loaded. In your above code you are doing same thing,
1. You are initiating App class object which lies in App namespace
2. You are initiating class object at the moment class when is not yet declared(As it is defined below in your code).
In your above code, not even your loader be called. It will be called if you initiate App\App class object after its declaration. and If your loader does not work fine then afterwards you will possibly get this error.
Fatal Error: Silex\Application class not found
Please checkout some examples and findings.
Example 1 Here loader is expected to be called but not called, because you have registered after initialization of class($app = new App();).
Example 2 Here, calling class will look for autoloading class because here initialization takes place after registration of loader and declaration of class, which is probably answers your question.
Change your code with this to get it fix:
<?php
namespace App;
require_once __DIR__ . '/../vendor/autoload.php';
class App extends \Silex\Application {
public function __construct()
{
parent::__construct();
echo 'Worked!';
}
}
$app = new App();

Zf2 extending the class giving the error class not found

I am trying to create the library inside the vendor folder in ZF2. Here is the structure:
/Vendor
/Mylib
/Mylib.php
/MylibStore.php
/MylibError.php
....
I have declared the same lib in Applicaiotion/Module.php:
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
'Mylib' => __DIR__ . '/../../vendor/Mylib',
),
),
);
}
Now I am calling Mylib class in controller it is working but when I am trying to instantiate other class in controller it is giving the error. Here is snap of code:
Mylib.php
namespace Mylib;
abstract class Mylib
{
MylibStore.php
namespace MylibStore;
use \Mylib\MylibError;
class MylibStore extends MylibError
{
MylibError.php
namespace MylibError;
class MylibError
{
I am getting the following error :
Fatal error: Class 'MylibStore\MylibError' not found in
C:\xampp\htdocs\coxaxle\vendor\Mylib\MylibStore.php on line 5
Please let me know what I am doing wrong? And how can I resolve this issue?
Problem is in your namespaces. All your files inside Mylib directory should have same namespace- Mylib.
That's why only Mylib class works, because it has correct namespace.
If you put your classes in separate directories then you have to update namespace about this directory.
Example:
/Vendor
/Mylib
/Service
/MylibService.php
/Mylib.php
....
Class Mylib should have namespace Mylib
Class MylibService should have namespace Mylib\Service

twig: How to add Twig extension file whilst NOT using symfony

I am currently using v1.12.2 Twig as a standalone templating engine.
I wrote a Twig extension called Utility_Twig_Extension in a file called UtilityExtension.php
and an index.php
//index.php
require_once '../vendor/twig/twig/lib/Twig/Autoloader.php';
Twig_Autoloader::register();
$loader = new Twig_Loader_Filesystem(OEBPS);
$twig = new Twig_Environment($loader, array(
'cache' => APP . DS . 'cache',
));
require_once '../vendor/twig/twig/ext/utility/UtilityExtension.php';
$twig->addExtension(new Utility_Twig_Extension());
Here is the UtilityExtension.php
//UtilityExtension.php
namespace UtilityTwigExtension;
class Utility_Twig_Extension extends Twig_Extension
{
public function getName()
{
return "utility";
}
}
Here is my directory structure:
src
|__app
| |__ index.php
|__vendor
|__twig
|__twig
|__ext
|__lib
I cannot even load the file properly.
I have traced the issue to the fact that the extension class tries to extend Twig_Extension.php.
So I require_once the Twig_Extension which is the Extension.php file in UtilityExtension.php. However, still not working.
Most documentation talks about adding a custom Twig Extension in the context of Symfony.
I am using Twig standalone, so I have yet to find any documentation on that.
Please advise.
UPDATE1:
By not working, I meant that I get the 500 server error. I ran error_reporting(E_ALL) was to no avail.
The error was relieved the moment I removed the words extends Twig_Extension from the extension class.
UPDATE2:
I realized it was a namespace issue. because I removed the namespace UtilityTwigExtension; from the UtilityExtension.php and the server 500 error was gone.
So I put the namespace UtilityTwigExtension; back and then call
require_once '../vendor/twig/twig/ext/utility/UtilityExtension.php';
$twig->addExtension(new UtilityTwigExtension\Utility_Twig_Extension());
the error came back.
Question: How do I call the TwigExtension if I insist on using the namespace? Is there a better way of using namespace?
UPDATE3:
I still get server 500 after trying Luceos answer.
error_reporting(E_ALL);
require_once 'constants.php';
require_once 'ZipLib.php';
require_once '../vendor/twig/twig/lib/Twig/Autoloader.php';
Twig_Autoloader::register();
$loader = new Twig_Loader_Filesystem(OEBPS);
$twig = new Twig_Environment($loader, array(
'cache' => APP . DS . 'cache',
));
require_once '../vendor/twig/twig/ext/utility/UtilityExtension.php';
use UtilityTwigExtension\Utility_Twig_Extension;
$twig->addExtension(new Utility_Twig_Extension());
the UtilityExtension.php
namespace UtilityTwigExtension;
class Utility_Twig_Extension extends Twig_Extension
{
/**
* Returns the name of the extension.
*
* #return string The extension name
*/
public function getName() {
return 'utility';
}
}
So let's put the comments in an answer and move on from there without crowding the comments:
First of call the extension from the correct namespace:
use UtilityTwigExtension\Utility_Twig_Extension;
$twig->addExtension(new Utility_Twig_Extension());
Use and namespaces calls are normally placed at the top of the file.
You can also try calling the namespace + object directly by using:
$twig->addExtension(new UtilityTwigExtension\Utility_Twig_Extension());
Update 3
The Utility_Twig_Extension extends Twig_Extension from the namespace UtilityTwigExtension, which does not exist. I assume Twig_Extension is not in any namespace so you'll use \Twig_Extension:
namespace UtilityTwigExtension;
class Utility_Twig_Extension extends \Twig_Extension
{
/**
* Returns the name of the extension.
*
* #return string The extension name
*/
public function getName() {
return 'utility';
}
}

Categories