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
Related
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.
I have a problem with Codeception/AspectMock.
When using custom autoloader and try to create an instance of a class which has parent form the same custom namespace I have this error:
PHP Fatal error: Uncaught InvalidArgumentException: Class [parent
class name] was not found by locator in
vendor/goaop/parser-reflection/src/ReflectionEngine.php:112
I have very simple setup:
<?php
require_once __DIR__ . '/vendor/autoload.php';
$kernel = AspectMock\Kernel::getInstance();
$kernel->init([
'debug' => true,
'includePaths' => [__DIR__. '/lib'],
]);
$kernel->loadFile(__DIR__ . '/autoload.php'); // custom autoloader
$b = new \lib\B();
Class \lib\B:
namespace lib;
class B extends A {}
Class \lib\A:
namespace lib;
class A
{
public function getName()
{
return static::class;
}
}
Class B is loaded via my custom autoloader, but then the locator tries to load parent class A via composer autoloader and returns this error. Is this a bug, or I'm doing something wrong?
The topic starter has already got an answer on GitHub.
In order to use custom autoloader you should re-init ReflectionEngine with composite class locator that will be able to locate your classes or you can use CallableLocator with closure for resolving paths.
Or, even better you could switch your code base to the PSR0/PSR-4
For example:
$kernel->loadFile(__DIR__ . '/autoload.php'); // custom autoloader
\Go\ParserReflection\ReflectionEngine::init(
new class implements \Go\ParserReflection\LocatorInterface {
public function locateClass($className) {
return (new ReflectionClass($className))->getFileName();
}
}
);
$b = new \lib\B(); // here you go
If you can easily do a find and replace on your codebase, maybe you could refactor your code to PSR-4 autoloading standards and do away with the need for a custom autoloader altogether.
This is the spec https://www.php-fig.org/psr/psr-4/. I'll try and explain it as simply as possible.
Imagine changing your lowercase namespace lib to Lib, and setting that namespace to the src/ directory in your composer.json:
"autoload": {
"psr-4": {
"Lib\\": "src/"
}
}
After setting that, run composer dumpautoload. Then all you need to do is search and replace namespace lib;, replacing with namespace Lib;.
An example class located in src/Form.php would have namespace Lib; at the top, followed by class Form.
<?php
namepace Lib;
class Form
{
// code
}
Namespaces use the folder naming convention. All classes directly in src/ have namespace Lib;. If there are subdirectories, the directory name becomes part of the namespace. For example a file in src/Form/Field/Text.php would have namespace Lib\Form\Field; class Text {}.
<?php
namepace Lib\Form\Field;
class Text
{
// code
}
You can see the full convention in the link above, but the general rule is make any folders begin with a capital letter, as with your classname, and the autoloader should be able to find all of your classes.
This is probably the best practice solution for you, and again as I said, only requires a little bit of file renaming and namespace tweaking. Good luck!
I have create Helpers folder inside app, then I have created php file amchelpers.php ---> app/Helpers/amchelpers.php
amchelpers.php code:
<?php namespace App;
class AmcHelper {
static function displayString($string){
return $string;
}
}
then added these lines to composer.json
"files": [
"app/Helpers/amchelpers.php"
]
then run this command:
composer dump-autoload
then added 'Helper' => app_path() . '\Helpers\AmcHelper' to aliases array in config/app.php file.
in my controller I have below action (this action defined in route.php):
use Helper;
class UserController extends Controller {
public function displayMyString(){
echo Helper::displayString('Hello');
}
}
when run the page http://localhost:8080/easy_marketing/public/displayMyString
I Got:
ErrorException in compiled.php line 6367: Class 'C:\wamp\www\easy_marketing\app\Helpers\AmcHelper' not found
you have written user Helper instead of use Helper
or
another way to achieve this is
Laravel 5 App directory is autoloaded by default with its folder, what you have to take care is add namespace followed by directory name,
so directory structure is App --> Helpers
so your name space must include App\Helpers
try following code
<?php namespace App\Helpers;
class AmcHelper {
static function displayString($string){
return $string;
}
}
and when you are using this class in another class write this after namespace declaration
use App\Helpers\AmcHelper as Helper;
class UserController extends Controller {
public function displayMyString(){
echo Helper::displayString('Hello');
}
}
Here is my app structure:
/application
/config
/library
/Foo
/Controler.php
/module
/User
/config
/src
/Bar
/Controler
/BarController.php
/public
/vendor
/init_autoloader.php
The Controler.php file...
namespace Foo_Controller;
use Zend\Mvc\Controller\AbstractRestfulController;
class Foo_Controller extends AbstractRestfulController {
protected $foo;
public function getFoo()
{
return "foooo";
}
function __construct()
{
parent::__construct();
$foo = $this->getFoo();
}
}
The BarController.php...
namespace Bar\Controler;
use Zend\Mvc\Controller\AbstractRestfulController;
use Foo_Controller\Foo_Controller;
use Zend\View\Model\JsonModel;
class BarController extends Foo_Controller {
.
..
....
}
Added the path /library folder in the init_autoloader.php
$loader = include 'vendor/autoload.php';
$zf2Path = 'vendor/zendframework/zendframework/library';
$loader->add('Zend', $zf2Path);
$loader->add('Julia', 'library'); // added the library folder
if (!class_exists('Zend\Loader\AutoloaderFactory')) {
throw new RuntimeException('Unable to load ZF2. Run `php composer.phar install` or define a ZF2_PATH environment variable.');
}
I get an error 500 with the following:PHP Fatal error: Class 'Foo_Controller\Foo_Controller' not found in /application/module/Bar/src/Bar/Controller/BarController.php on line #
I really don't know what to do now. I have been searching the internet for some time now for the correct way to extend a controller class in Zend Frazmework 2, but i can't seem to grasp it!
What am i doing wrong in the app?
Thank you
I would suggest you set this out slightly differently. Would really make more sense to create your own custom module which you can load into any project with directory structure like:
/zf2-MyCustomModule
/src
/MyCustomModule
/Controller
/Abstract
/MyAbstractController.php
namespace for MyAbstractController.php would be - MyCustomModule\Controller\Abstract
If it is specific to the project then why not just add
/Abstract
/MyAbstractController.php
to the User Module Controller dir.
but seems like what you have done is pretty much right you would just need to update namespace in Foo_Controller.php to:
namespace Julia\Foo\Controller;
not
namespace Foo_Controller;
Though I have never used the method you are using so am not 100% sure.
I would add a new local config to /config/autoload/
like /config/autoload/namespaces.global.php
Zend\Loader\AutoloaderFactory::factory(array(
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
'Julia' => __DIR__ . '/Library',
),
)
));
then your namespace should still be Julia\Foo\Controller;
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.