Custom directory in src/ folder in ZF3 - zend-framework

I have mvc zf3 skeleton with forms. Form and fieldset classes are located in src/Form directory.
Above works fine.
I tried to make the Form directory lighter and clearer so I created src/Fieldset directory and moved fieldset classes there. Now the fieldset classes are not found by form classes.
<?php
namespace Application\Form;
use Zend\Form\Element;
use Zend\Form\Form;
use Zend\Hydrator\ClassMethods as ClassMethodsHydrator;
use Zend\InputFilter\InputFilter;
class MyForm extends Form
{
public function __construct()
{
parent::__construct('my_form');
$this->setAttribute('method', 'post');
$this->setHydrator(new ClassMethodsHydrator(false));
$this->setInputFilter(new InputFilter());
$this->add([
'type' => AbcFieldset::class,
'name' => 'abcEntity',
'options' => [
'use_as_base_fieldset' => true,
],
]);
The error message is
A plugin by the name "Application\Form\AbcFieldset" was not found in the plugin manager Zend\Form\FormElementManager\FormElementManagerV3Polyfill
What to do to make the form see the fieldset classes in new location?

The first problem is that the PSR-4 autoloader is looking for the Application\Form\AbcFieldset class in the file src/Form/AbcFieldset.php directory.
You could write a custom autoloader that would look in the src/Fieldset directory, but it's better to stick with the PSR standard and instead change the namespace of the fieldset to Application\Fieldset (you will then need to add use Application\Fieldset\AbcFieldset; at the top of the form class in your example).
The second 'problem', and the source of the error message is that the fieldset class has not been explicitly registered with the form element manager, so you might also add to your module.config.php
'form_elements' => [
'factories' => [
\Application\Fieldset\AbcFieldset::class => \Zend\ServiceManager\Factory\InvokableFactory::class,
]
]
But this isn't necessary unless you need to write a custom factory for the fieldset - the namespace change above should fix the problem.

Related

Set Module name, Controller name, and Action name in Zend framework?

I recently started programming with Zend Framework.I want to change module name, controller name and action name of a module in my framework through coding, while coding in the same framework.
Its name is Application(module & controller) and I want to change it to Institute. Is this possible through coding?
I searched through Google for help, but either i couldn't find it or understand it properly. Any help would be appreciated.
This is really just a case of renaming things:
Update all namespaces from Application to Institute in all the classes in the module including the Module.php
Update the name of the controller and it's entry in config/module.config.php
Make sure you update the name of your view directory if you have one in the module, ie view/application/index etc to view/institute/index and make sure you update the entry in module.config.php to the same path
Update name of Application directory to Institute
Update the name in the array of modules in modules.config.php or if you are using an earlier version application.config.php from under the modules key.
That's all I can think of you would need to do
******** EDIT ********
So the basic idea would be as follows:
Add a console in a new module (I've used zend mvc console but you should probably use https://github.com/zfcampus/zf-console as mvc console is deprecated)
module.config.php
<?php
namespace Rename;
use Zend\ServiceManager\Factory\InvokableFactory;
return [
'console' => array(
'router' => array(
'routes' => array(
'rename-module' => array(
'options' => array(
'route' => 'module rename <moduleNameOld> <moduleNameNew>',
'defaults' => array(
'controller' => Controller\IndexController::class,
'action' => 'rename'
)
)
)
)
)
),
'controllers' => [
'factories' => [
Controller\IndexController::class => InvokableFactory::class,
],
],
];
IndexController.php
<?php
namespace Rename\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\Console\Request as ConsoleRequest;
use Zend\Mvc\Console\Controller\AbstractConsoleController;
class IndexController extends AbstractConsoleController
{
public function renameAction()
{
$request = $this->getRequest();
// Make sure that we are running in a console and the user has not tricked our
// application into running this action from a public web server.
if (!$request instanceof ConsoleRequest) {
throw new \RuntimeException('You can only use this action from a console!');
}
$moduleNameOld = $request->getParam('moduleNameOld');
$moduleNameNew = $request->getParam('moduleNameNew');
$module = file_get_contents(getcwd() . "/module/$moduleNameOld/src/Module.php", 'r+');
$updatedModule = str_replace($moduleNameOld, $moduleNameNew, $module);
file_put_contents(getcwd() . "/module/$moduleNameOld/src/Module.php", $updatedModule);
rename("module/$moduleNameOld", "module/$moduleNameNew");
}
}
This can be run like
php public/index.php module rename Application Institute
I've only done renaming the module here and renaming the namespace in the Module.php
to finish this off you would need to recursively find all .php files in the Application directory and loop over applying the string replace (which should be improved really). Then you could update the view and application level config too with similar logic and using the steps above.
The code I've written is pretty bad and probably insecure but might help you along the way

No object manager was set zf2 fieldset

Can someone explain to me how to fix this error "No object manager was set"
Here is the fieldset:
namespace Trunk\Form;
use Trunk\Entity\Category;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterProviderInterface;
class CategoryFieldset extends Fieldset implements InputFilterProviderInterface
{
public function __construct($objectManager)
{
parent::__construct('category');
$this->setHydrator(new DoctrineHydrator($objectManager, 'Trunk\Entity\Category'));
$this->add(array(
'type' => 'DoctrineORMModule\Form\Element\DoctrineEntity',
'name' => 'title',
'object_manager' => $objectManager,
'target_class' => 'Trunk\Entity\Category',
'property' => 'title',
'is_method' => false,
'find_method' => array(
'name' => 'findBy',
'params' => array(
'criteria' => array('parentid' => 0),
'orderBy' => array('title' => 'ASC'),
),
)
));
}
}
Here is the error message:
F:\xampp\htdocs\travelltheworld\vendor\doctrine\doctrine-module\src\DoctrineModule\Form\Element\Proxy.php:535
No object manager was set
I have injected the entity manager in the factory into my form which is called ProductForm. Inside that form I have base fieldset called ProductFieldset and inside ProductFieldset I inserted CategoryFieldset where I need to select the categories from the Database and display them in the select box.
If you need more code or explanation please ask me.
Fieldset object can hydrate your entities with an Hydrator.
Here is a complete example of a fieldset
https://github.com/Grafikart/BlogMVC/blob/master/ZendFramework2/module/Blog/src/Blog/Form/Fieldset/CommentFieldset.php
As you can see the fieldset can have the Object manager by an "awareInterface" named ObjectManagerAwareInterface,
use DoctrineModule\Persistence\ObjectManagerAwareInterface;
and the trait : use ProvidesObjectManager;
use DoctrineModule\Persistence\ProvidesObjectManager as ProvidesObjectManager ;
you have miss those in your fieldset, this should correct your problem.
Your form, and his factory are completely different than the fieldset so it can't work that way for you construct injection.
Are there any working examples of form hydration or extraction and form binding using Laminas & the Doctrine hydrator? I have been searching everywhere and the Doctrine hydrator docs don't really explain how this is down on a one to one relation like a User & an Address.

Zend 1.12 - autoloading models without Model_ Namespace

I'm using a standard out of the box Zend 1 directory structure and have a model:
applications
/models
/Menu
Core.php
Now I'd like to autoload Core but without having to name the class as Model_Menu_Core but just Menu_Core similar to how Zend libraries are being named from within library directory i.e. Zend_xxxx and not Library_Zend_....
I don't really want to register each namespace separately but just have automatic autoload similar to standard PHP __autoload()
Also, how can I achieve the same for the global library directory
How can I achieve that? Thanks
Use Zend_Loader_Autoloader_Resource and add resouce type without namespace, for example:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
/* ... */
protected function _initAutoloaderResource()
{
$resourceLoader = new Zend_Loader_Autoloader_Resource(array(
'namespace' => '',
'basePath' => APPLICATION_PATH));
$resourceLoader->addResourceType('model', 'models/', '');
}
/* ... */
}

Why does not work short names when I create custom form elements in Zend Framework 2?

I create custom element like here: ZF2Docs: Advanced use of Forms
1.Create CustomElement class in Application/Form/Element/CustomElement.php
2.Add to my Module.php function
public function getFormElementConfig()
{
return array(
'invokables' => array(
'custom' => 'Application\Form\Element\CustomElement',
),
);
}
If I use FQCN it works fine:
$form->add(array(
'type' => 'Application\Form\Element\CustomElement',
'name' => 'myCustomElement'
));
But if I use short name:
$form->add(array(
'type' => 'Custom',
'name' => 'myCustomElement'
));
throws Exception:
Zend\ServiceManager\ServiceManager::get was unable to fetch or create
an instance for Custom
Problem
The error is probably due to how you are instantiating the $form object. If you just use the new Zend\Form\Form expression or something similar the form will not be set up with the correct service locator.
$form = new \Zend\Form\Form;
$form->add(array(
'type' => 'custom',
'name' => 'foobar',
));
Solution
The trick here is to use the FormElementManager service locator to instantiate the form.
// inside a controller action
$form = $this->getServiceLocator()->get('FormElementManager')->get('Form');
$form->add(array(
'type' => 'custom',
'name' => 'foobar',
));
Better yet, define a form() method in your controller as a shortcut to do this for you:
class MyController extends AbstractActionController
{
public function form($name, $options = array())
{
$forms = $this->getServiceLocator()->get('FormElementManager');
return $forms->get($name, $options);
}
public function createAction()
{
$form = $this->form('SomeForm');
// ...
}
}
Explanation
Each form object is attached to a form factory which is in turn attached to a service locator. This service locator is in charge of fetching all the classes used to instantiate new form/element/fieldset objects.
If you instantiate a new form object (all by itself), a blank service locator is instantiated and used to fetch later classes within that form. But each subsequent object is then attached to that same service locator.
The problem here is that getFormElementConfig configures a very specific instance of this service locator. This is the FormElementManager service locator. Once it's configured, all forms pulled from this service locator will then be attached to this service locator and will be used to fetch other elements/fieldsets etc.
Hope this solves your issue.

zendframework autoloading query

I am writing my own log class in zendframework based application. I was wondering as it's my own lib class where to keep it in application. I decided to keep this class parallel to "Zend" folder inside /library folder
-library
- Zend
- Helper [ custom lib classes]
In bootstrap.php I have _initAutoload function where in I have added following
$autoloader=new Zend_Loader_Autoloader_Resource(array(
'basePath' => dirname(__FILE__),
'namespace' => 'Demo',
));
$autoloader->addResourceType('model', 'models/', 'Model');
$autoloader->addResourceType('helper', APPLICATION_PATH.'/library/Helper', 'Helper');
but I get error Demo_Helper_Logger class not found.
Whats could be wrong here? Any idea?
Thanks
If you are using ZF 1.9+ you can handle this inside your application.ini
Put your custom "library" into:
../library/Helper/Log.php
Name your class like:
class Helper_Log {}
Add
autoloadernamespaces.1 = "Helper_"
to your application.ini
$log = new Helper_Log();