Default class for form elements - php

I have a custom form class that extends base Zend_Form and specifies the decorators for the form itself and elements as well.
And now I'm in stuck - how to add some particular HTML class to every input element?
The only thing I could think of is to override addElement() but I'm open to better solutions if any.

just another solution:
class My_Form extends Zend_Form
{
public function render(Zend_View_Interface $view = null)
{
foreach ($this->getElements() as $element) {
$element->setAttrib('class', 'default');
}
return parent::render($view);
}
}

sounds like you want a way to automatically assign a unique class to each element.
Expanding on the answer given by b.b3rn4rd, try something like:
class My_Form extends Zend_Form
{
public function render(Zend_View_Interface $view = null)
{
foreach ($this->getElements() as $element) {
//assign the class as some unique identifier that is part of the element
//each element requires a unique name so it's a good place to start
$element->setAttrib('class', $element->getName());
}
return parent::render($view);
}
}

I don't like solutions that inherit Zend_Form, so I devised another way to do this.
<?php
abstract class Application_Style
{
private $_object;
function __construct ($object = null)
{
if (isset ($object))
{
$this->apply ($object);
}
}
function apply ($object)
{
$this->setObject ($object);
if ($this->filter ())
{
$this->onApply ();
}
return $object;
}
function __call ($method, $arguments)
{
return call_user_func_array (array (
$this->getObject (),
$method
), $arguments);
}
abstract protected function onApply ();
protected function filter ()
{
return true;
}
function setObject ($_object)
{
$this->_object = $_object;
}
function getObject ()
{
return $this->_object;
}
}
class Application_Style_ElementClass extends Application_Style
{
function onApply ()
{
foreach ($this->getObject ()
->getElements () as $element)
{
$element->setOptions (array (
'class' => 'test-class'
));
}
}
function filter ()
{
return $this->getObject () instanceof Zend_Form;
}
}
$form = new Zend_Form ();
$form->addElement ('text', 'name');
new Application_Style_ElementClass ($form); // apply the class name
echo $form;
This way you can apply all the styles needed for any form in any order.

Adding HTML class attributes to elements is like this
$element->setAttrib('class', 'text'):
or directly
$element->class = 'text;

Related

How can I change existing function in a class

I have a form class and I want define different functions when form be submitted.
<?php
class Forms {
function __construct() {
if (!empty($_POST['exampleInput'])) {
$this->PostedForms();
}
}
function __call($func, $param) {
}
function PostedForms() {
if (!empty($_POST['exampleInput'])) {
if (function_exists($this->userDefined)) {
$this->userDefined();
}
}
}
}
$form = new Forms();
$form->userDefined = function ($param) {
print_r($_POST);
}
?>
I want define userDefined function outside of class. How can I do this? Can I change any function of class after class was called? Can I change userDefined = function ($param) {print_r($_GET);} for example?

How can I create new instances of different classes in a good way?

I have a class, more specific a repository. This repository will hold my validators so I can reach them whenever I want. Currently it looks like this:
class ValidatorRepository {
private $validators;
public function __construct() {
$this->validators = array();
}
public function get($key) {
return $this->validators[$key];
}
public function add($key, iValidator $value) {
$this->validators[$key] = $value;
}
public static function getInstance() {
//(...)
}
}
And with this class I would like to do something like this:
$vr = ValidatorRepository::getInstance();
$vr->add("string", new StringValidator());
I can insert something else than a instantiated object if that is for the better.
.. and later on, somewhere else;
$vr = ValidatorRepository::getInstance();
$vr->get("string"); // should return a *new* instance of StringValidator.
The idea is that the ValidatorRepository should NOT know about the classes before these are added.This works fine, as long as I return the current object.
But instead I would like a new object of the class. I could to this by putting a static getInstance() function in each validator, or use eval in some way, but I hope there might be another, less ugly, way.
I believe you should be able to do something this simple:
public function add( $key, iValidator $value ) {
$this->validators[ $key ] = get_class( $value ); // this call can be moved to get() if you wish
}
public function get( $key ) {
return new $this->validators[ $key ];
}
get_class() takes namespaces into account, so if you use namespaces then it will still be fine.
A slightly more flexible approach might be this:
public function add( $key, iValidator $value ) {
$this->validators[ $key ] = $value;
}
public function get( $key, $new = true ) {
if ($new) {
$class = get_class( $this->validators[ $key ] );
$class = new $class;
} else {
$class = $this->validators[ $key ];
}
return $class;
}
What you should be using is instead either inheritance:
abstract class Validated {
public function validate(){
foreach(self::VALIDATIONS as $val) {
// ...
}
}
}
class Person extends Validated {
protected $name;
const VALIDATIONS = array(
'name' => array( 'length' => new LengthValidator(15) )
);
}
or traits:
trait Validated {
function validate(){
// ...
}
}
class Person {
use Validated;
}
Shoving all the validation logic into a single class violates the single responsibly principle since it becomes responsible for for validating all classes which use it. It will quickly get out of hand.
Note that I have used a constant for the validations - you rarely need to change validation rules for a class during runtime.

PHP mandatory function call

I understand that one can use interfaces to mandate the definition of a function, but I cannot find something that enables one to mandate function calls, such that e.g. if I create a class being a member of another class (via extends, etc), with a function, for that class to automatically ensure that mandatory functions are called in part with that function.
I mean, to clarify further:
class domain {
function isEmpty($input) {
//apply conditional logic and results
}
}
class test extends domain {
function addTestToDBTable($test) {
/**
* try to add but this class automatically makes it so that all rules of
* class domain must be passed before it can run
* - so essentially, I am no longer required to call those tests for each and
* every method
**/
}
}
Apologies if this appears incoherent by any means. Sure, it seems lazy but I want to be able to force context without having to concern abou
Update:
Okay, to clarify further: in PHP, if I extend and declare a __construct() for a child class, that child class will override the parent __construct(). I do not want this, I want the parent construct to remain and mandate whatever as it pleases just as the child class may do so also.
I guess it can be done in two different ways.
Aspect Oriented Programming
Have a look here https://github.com/AOP-PHP/AOP
Generate or write Proxy classes
A really simple example could be:
<?php
class A {
public function callMe() {
echo __METHOD__ . "\n";
}
}
class B extends A {
// prevents instantiation
public function __construct() {
}
public function shouldCallMe() {
echo __METHOD__ . "\n";
}
public static function newInstance() {
return new ABProxy();
}
}
class ABProxy {
private $b;
public function __construct() {
$this->b = new B();
}
public function __call($method, $args) {
$this->b->callMe();
return call_user_func_array(array($this->b, $method), $args);
}
}
// make the call
$b = B::newInstance();
$b->shouldCallMe();
// Outputs
// ------------------
// A::callMe
// B::shouldCallMe
Hopes this helps a bit.
Sounds like you want a Decorator.
See This answer for a detailed explanation on how to do it. Note that it does not require a class extension.
I would use a domain-validating decorator with some doc-block metaprogramming magic. But this is really a job for an entire library, which no doubt exists.
fiddle
<?php
class FooDomain {
public static function is_not_empty($input) {
return !empty($input);
}
}
class Foo {
/**
* #domain FooDomain::is_not_empty my_string
*/
public function print_string($my_string) {
echo $my_string . PHP_EOL;
}
}
$foo = new DomainValidator(new Foo());
$foo->print_string('Hello, world!');
try {
$foo->print_string(''); // throws a DomainException
} catch (\DomainException $e) {
echo 'Could not print an empty string...' . PHP_EOL;
}
// ---
class DomainValidator {
const DOMAIN_TAG = '#domain';
private $object;
public function __construct($object) {
$this->object = $object;
}
public function __call($function, $arguments) {
if (!$this->verify_domain($function, $arguments)) {
throw new \DomainException('Bad domain!');
}
return call_user_func_array(
array($this->object, $function),
$arguments
);
}
public function __get($name) {
return $this->object->name;
}
public function __set($name, $value) {
$this->object->name = $value;
}
private function verify_domain($function, $arguments) {
// Get reference to method
$method = new \ReflectionMethod($this->object, $function);
$domains = $this->get_domains($method->getDocComment());
$arguments = $this->parse_arguments(
$method->getParameters(),
$arguments
);
foreach ($domains as $domain) {
if (!call_user_func(
$domain['name'],
$arguments[$domain['parameter']]
)) {
return false;
}
}
return true;
}
private function get_domains($doc_block) {
$lines = explode("\n", $doc_block);
$domains = array();
$domain_tag = DomainValidator::DOMAIN_TAG . ' ';
foreach ($lines as $line) {
$has_domain = stristr($line, $domain_tag) !== false;
if ($has_domain) {
$domain_info = explode($domain_tag, $line);
$domain_info = explode(' ', $domain_info[1]);
$domains[] = array(
'name' => $domain_info[0],
'parameter' => $domain_info[1],
);
}
}
return $domains;
}
private function parse_arguments($parameters, $values) {
$ret = array();
for ($i = 0, $size = sizeof($values); $i < $size; $i++) {
$ret[$parameters[$i]->name] = $values[$i];
}
return $ret;
}
}
Output:
Hello, world!
Could not print an empty string...

How to add methods dynamically

I'm trying to add methods dynamically from external files.
Right now I have __call method in my class so when i call the method I want, __call includes it for me; the problem is I want to call loaded function by using my class, and I don't want loaded function outside of the class;
Class myClass
{
function__call($name, $args)
{
require_once($name.".php");
}
}
echoA.php:
function echoA()
{
echo("A");
}
then i want to use it like:
$myClass = new myClass();
$myClass->echoA();
Any advice will be appreciated.
Is this what you need?
$methodOne = function ()
{
echo "I am doing one.".PHP_EOL;
};
$methodTwo = function ()
{
echo "I am doing two.".PHP_EOL;
};
class Composite
{
function addMethod($name, $method)
{
$this->{$name} = $method;
}
public function __call($name, $arguments)
{
return call_user_func($this->{$name}, $arguments);
}
}
$one = new Composite();
$one -> addMethod("method1", $methodOne);
$one -> method1();
$one -> addMethod("method2", $methodTwo);
$one -> method2();
You cannot dynamically add methods to a class at runtime, period.*
PHP simply isn't a very duck-punchable language.
* Without ugly hacks.
You can dynamically add attributes and methods providing it is done through the constructor in the same way you can pass a function as argument of another function.
class Example {
function __construct($f)
{
$this->action=$f;
}
}
function fun() {
echo "hello\n";
}
$ex1 = new class('fun');
You can not call directlry $ex1->action(), it must be assigned to a variable and then you can call this variable like a function.
if i read the manual right,
the __call get called insted of the function, if the function dosn't exist
so you probely need to call it after you created it
Class myClass
{
function __call($name, $args)
{
require_once($name.".php");
$this->$name($args);
}
}
You can create an attribute in your class : methods=[]
and use create_function for create lambda function.
Stock it in the methods attribute, at index of the name of method you want.
use :
function __call($method, $arguments)
{
if(method_exists($this, $method))
$this->$method($arguments);
else
$this->methods[$method]($arguments);
}
to find and call good method.
What you are referring to is called Overloading. Read all about it in the PHP Manual
/**
* #method Talk hello(string $name)
* #method Talk goodbye(string $name)
*/
class Talk {
private $methods = [];
public function __construct(array $methods) {
$this->methods = $methods;
}
public function __call(string $method, array $arguments): Talk {
if ($func = $this->methods[$method] ?? false) {
$func(...$arguments);
return $this;
}
throw new \RuntimeException(sprintf('Missing %s method.'));
}
}
$howdy = new Talk([
'hello' => function(string $name) {
echo sprintf('Hello %s!%s', $name, PHP_EOL);
},
'goodbye' => function(string $name) {
echo sprintf('Goodbye %s!%s', $name, PHP_EOL);
},
]);
$howdy
->hello('Jim')
->goodbye('Joe');
https://3v4l.org/iIhph
You can do both adding methods and properties dynamically.
Properties:
class XXX
{
public function __construct($array1)
{
foreach ($array1 as $item) {
$this->$item = "PropValue for property : " . $item;
}
}
}
$a1 = array("prop1", "prop2", "prop3", "prop4");
$class1 = new XXX($a1);
echo $class1->prop1 . PHP_EOL;
echo $class1->prop2 . PHP_EOL;
echo $class1->prop3 . PHP_EOL;
echo $class1->prop4 . PHP_EOL;
Methods:
//using anounymous function
$method1 = function () {
echo "this can be in an include file and read inline." . PHP_EOL;
};
class class1
{
//build the new method from the constructor, not required to do it here by it is simpler.
public function __construct($functionName, $body)
{
$this->{$functionName} = $body;
}
public function __call($functionName, $arguments)
{
return call_user_func($this->{$functionName}, $arguments);
}
}
//pass the new method name and the refernce to the anounymous function
$myObjectWithNewMethod = new class1("method1", $method1);
$myObjectWithNewMethod->method1();
I've worked up the following code example and a helper method which works with __call which may prove useful. https://github.com/permanenttourist/helpers/tree/master/PHP/php_append_methods

Override the setValue in zend form

I want the zend form to override the setValue function so that the value given to the function can be manipulated. How can i implement this?
My current form structure is like this:
class My_Form_Login
{
public $Form;
public $Username;
public function __construct()
{
$this->Form = new Form_Abstract();
$this->init();
}
public function init()
{
$this->Username ->setValue('100');
}
}
class Form_Abstract extends Zend_Form
{
public function __construct($options = null)
{
parent::__construct($options);
$this->setDecorators(array( 'FormElements','FormErrors','Form' ));
}
public function setValue($value)
{
$strippedValue = stripslashes($value);
return parent::setValue($strippedValue);
}
}
Thanks in advance..
You can extend the Zend_Form into your own class like:
My_Form extends Zend_Form
{
public function setValue($arg)
{
// My override code here
}
}
Then use this class instead of the Zend_Form directly
Consider using the Zend filter interface instead. For example
class My_Filter_Stripslashes implements Zend_Filter_Interface
{
public function filter($value)
{
return get_magic_quotes_gpc() ? $this->_clean($value) : $value;
}
protected function _clean($value)
{
return is_array($value) ? array_map(array($this, '_clean'), $value) : stripslashes($value);
}
}
Then apply this to your elements after adding them
$form->setElementFilters(array(new My_Filter_Stripslashes));

Categories