extend functionality of Zend_Form_Element

123 views Asked by At

I'm still wondering when and where I have to register new classes and how to extend old ones. For example I found a nice code which extends Zend_Form_Element_Select so that I can use it in each form and pass my database specifications to.

Because I thought, it would be a good idea to have an own directory I added a folder src\Service at modulelevel.

First question: Is that clever to have it at modulelevel? Would it be more convenient to have it at rootlevel so that I could use it in several modules? Do I have to register it?

The class extends Zend_Form_Element_Select which I added with a use statement:

use Zend\Form\Element\Select;

This causes a fatal error :

Fatal error: Class 'Import\Service\Zend_Form_Element_Select' not found

This would be my next question: How can I add this Zend_Form_Element properly. I think the problem might be that Zend doesn't look in the Zend-Directory. But I used the Zend_Form_Element_Select in other forms so it is there. But my new class doesn't know it. How would I do it, if I want to use own classes which of course use Zend-Classes?

I'm searching basically for a way how to do it in general. The target would be to easy reuse classes in other projects.

EDIT1: additional code snippets

here is the class I found online:

Module\Import\src\Service\CU_Form_Element_DbSelect

<?php

namespace Import\Service;
use Zend\Form\Form;
use Zend\Form\Element\Select;
use Zend\Form\Element;

class CU_Form_Element_DbSelect extends Zend_Form_Element_Select {

    private $_dbAdapter;
    private $_dbSelect;

    private $_identityColumn = 'id';
    private $_valueColumn = '';

    /**
     * Set the database adapter used
     * @param Zend_Db_Adapter_Abstract $adapter
     */
    public function setDbAdapter(Zend_Db_Adapter_Abstract $adapter) {
        $this->_dbAdapter = $adapter;
    }

    /**
     * Set the query used to fetch the data
     * @param string|Zend_Db_Select $select
     */
    public function setDbSelect($select) {
        $this->_dbSelect = $select;
    }

    /**
     * Set the column where the identifiers for the options are fetched
     * @param string $name
     */
    public function setIdentityColumn($name) {
        $this->_identityColumn = $name;
    }

    /**
     * Set the column where the visible values in the options are fetched
     * @param string $name
     */
    public function setValueColumn($name) {
        $this->_valueColumn = $name;
    }

    public function render(Zend_View_Interface $view = null) {
        $this->_performSelect();
        return parent::render($view);
    }


    private function _performSelect() {
        if(!$this->_dbAdapter)
            $this->_dbAdapter = Zend_Db_Table::getDefaultAdapter();

            $stmt = $this->_dbAdapter->query($this->_dbSelect);
            $results = $stmt->fetchAll(Zend_Db::FETCH_ASSOC);
            $options = array();

            foreach($results as $r) {
                if(!isset($r[$this->_identityColumn])) {
                    throw new Zend_Form_Element_Exception(
                            'Identity column is not present in the result');
                }

                if(!isset($r[$this->_valueColumn])) {
                    throw new Zend_Form_Element_Exception(
                            'Value column is not present in the result');
                }

                $options[$r[$this->_identityColumn]] = $r[$this->_valueColumn];
            }

            $this->setMultiOptions($options);
    }
}

Here also a snippet of my first form in which I wanted to use it in:

namespace Import\Form;

use Zend\Form\Form;
use Import\Service\CU_Form_Element_DbSelect;
.....

$this->add(new CU_Form_Element_DbSelect(array(
                'name' => 'ProjectID',
                'dbAdapter' => $this->db,
                'dbSelect' => 'SELECT ProjectID, Projectname FROM t_project',
                'valueColumn' => 'ProjectID',
                'label' => 'Choose project'
        )));

For me the error message looks like extends Zend_Form_Element_Select is not found.

1

There are 1 answers

5
Dolly Aswin On

There is no problem to have your own class on module level. You also can use it on another module. Just call the class using use. As long as the module registered in config/modules.config.php you can use it in another modules.

Where is to put the class? Depend on your need. You can put it in root of module

ExampleModule/src/YourClass.php

or you can put it on Service folder. I usually put my own class on this folder if this class can be used as service

ExampleModule/src/Service/Yourclass.php

And about this error, please add namespace Import\Service to your Zend_Form_Element_Select class.

Fatal error: Class 'Import\Service\Zend_Form_Element_Select' not found

I see this caused by Autoloader cannot find it because it don't use the correct namespace. Please use the correct namespace, related the module name and path (eg: Import\Service).

To make your class reusable in another project, you can follow how Zend Modules created. They can be install and uninstall using composer. The first, you need to know how composer work.