简体   繁体   中英

Iterating through classes in PHP

I have a wrapper for interacting with databases. A class is auto-generated for each table in the database and this extends a base class that contains functions for interacting with the database eg viewTable, viewForm, getRecordByID... One of the key objectives of it is to make use of autocomplete so I don't have to remember field names etc. and to make code more secure and less prone to errors.

I am very happy with it apart from one little bit: in my code, to produce a an HTML form, I use code like this:

$objInvoice = new cls__Invoice();

$objInvoice->fldID->Active(true); //Active means it will appear on the form
                                  //and a POST will be expected
$objInvoice->fldCompany_ID->Active(true);
$objInvoice->fldSomeValue->Active(true);

$objInvoice->initForm(); //Read posted variables

echo $objInvoice->viewForm(); //viewForm can be overloaded to suit the project

There are many other settings I can use:

$objInvoice->fldCompany_ID->Title('Company Reference');

But here is where the problem starts:

$objInvoice->fldSomeValue->InputType('MoneyInput');

I pass the input type in to allow a particular Input tag or dropdown etc. to be used and to allow it to be read a particular way too. Eg "IPAddress" type actually shows 4 inputs with a dot between them. So it must be split to be displayed and concatenated before saving to the Database.

Again, this all works perfectly fine, but I have two big ugly switch statements in the middle of my base class. I would like to find a solution that;

  1. Is elegant
  2. Allows the read part and the view part to be beside each other in the code
  3. Allows the developer to create their own input types without messing with the core class.
  4. Allows me to use auto-complete at this bit: ...->InputType($objSomething->MoneyInput);

I have came up with some solutions but they fail point 1 above. I suspect the solution will be a class like this:

class clsInputBase {
    var $InputType;

    public function Read($objField) {
        $result = $_POST[$objField->VariableName];
        return $result;
    } //funct

    public function Output($objField) {
        //Standard code for outputing a normal one
        //NB: SIMPLIFIED FOR EXAMPLE!
        $result = '<input value="' . $objField->Value() . '" id="' . $objField->VariableName() . '"';
        //...
        $result .= '/>' . "\r\n";

        return $result;
    } //funct
} //funct

Then I would extend this class for each input type and overload the two functions as required.
Then the real problems start: I need to find a way to iterate through the objects / classes in the base class and a way for a developer to add custom ones to an array or something. So I guess I either need to create an array of class names and then create an object of that class using $type = 'myclass'; $instance = new $type; (not very elegant) or create lots of objects that I may not need (not very elegant either).

Sorry this is so long.
Any suggestions?

I would do the following:

// can be extended
class Form
{
// class variable to hold all inputs
// class construct expects form config and an array with inputs
// Methods to create forms, parsing forms
}

// can be extended
class Input
{
// class variables to hold input configuration with default values
// methods to echo, parse and validate inputs
// class construct expects array with single input config
// hooks to manipulate with data before and after all logics
}

Then:

$formParams = array(...);
$formInputs = array(
    input configurations
);

$form = new Form($formParams, $formInputs);
$form->initForm();

Then Form class iterates trough every $formInputs value and creates new Input class objects with according configuration.

In your active record class, when it's generated, you can give default input configurations to each column.

Now, extending this would be easy, let's say we need custom input type:

class CustomInput extends Input
{
    //at construct we call parent constuctor and adding our own data or manipulating with old
    //if we want to transform data, we can use hooks
    //this class objects still will be available at Form class object 
}

You can specify custom class in input configurations or you can get rid of second config array and add inputs manually.

At the end we will get unified form class, which we can use straight away: You even may consider not to overload Input class in many cases, instead introduce flexible logic in base class, so it can accept many configuration options.

Take a look into the Iterator Interface:

class myIterator implements Iterator {
    private $position = 0;
    private $array = array(
        "firstelement",
        "secondelement",
        "lastelement",
    );  

    public function __construct() {
        $this->position = 0;
    }

    function rewind() {
        var_dump(__METHOD__);
        $this->position = 0;
    }

    function current() {
        var_dump(__METHOD__);
        return $this->array[$this->position];
    }

    function key() {
        var_dump(__METHOD__);
        return $this->position;
    }

    function next() {
        var_dump(__METHOD__);
        ++$this->position;
    }

    function valid() {
        var_dump(__METHOD__);
        return isset($this->array[$this->position]);
    }
}

$it = new myIterator;

foreach($it as $key => $value) {
    var_dump($key, $value);
    echo "\n";
}

http://www.php.net/manual/de/class.iterator.php

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM