Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP object oriented form generator

I am trying to create an object oriented form generator. Please keep in mind it will be used only by a handful of people in our company to solve a specific problem.

I am currently facing two little caveats.

Syntax of creating elements

There are few approaches I can take.

Setting everything in constructor. As a drawback this could result in inconsitent constructor usage

Input::create('text', 'name', array('maxlength' => 10));

Limit constructor to type and expose only the most used attributes as methods (keep one method for mass attribute setting)

Input::create('text')->name('name')->value('value')->attribute('max_length', 10);

Expose every attribute as method with either creating a method for every attribute or with __call magic method which will result in no autocomplete support in an IDE. And even now, I can keep the attribute method.

Input::create()->type('text')->name('name')->value('value')->max_length(10)->id('id'); //etc.

At the moment, I consider the second approach as the best one, since it keeps "good" stuff from both worlds. As still provides a way to abstract some of the work, since e.g. method required would not only set the required attribute, but also mark this field for validation object as required.

Code duplication with approach 2 and 3

Since there are attributes that can be used by every element, but also attributes that are only usable by 3 or 4 elements, e.g. HTML5 attribute form.

Every element can inherit from base element which has methods for attributes that are universal for every element (e.g. name). Partially usable attributes can be solved with interfaces, but this leads to code duplication as they cant contain method body.

Traits would be the solution, but sadly, I am stuck at PHP 5.3 with no way to upgrade. That leaves me with either implementing Mixin or Composition pattern, which again, might lead to no autocomplete support. This would be partially mitigated when using second approach.

So to my actual question:

Which approach can end as most suitable? (suitable as in minimal code duplication, solid code reuse and easiness of implementation)

I realize this might very well spawn opinion based answers so I apologize in advance if it does.

like image 359
realshadow Avatar asked Nov 09 '22 18:11

realshadow


1 Answers

I realize this is an old question, but someone in the comments mention a project that I've created called htmlgen, mirrored on packagist. I'm chiming in with some support here as I've recently released a new version 2.x that makes HTML generation quite pleasant in PHP.

use function htmlgen\html as h;
echo h('input', ['name'=>'catQty', 'value'=>500])

Will render

<input name="catQty" value="500">

However, that example is barely scratching the surface in terms of potential

h('#wrapper',
  h('h1.title', 'Hello, World'),
  h('p',
    h('comment', 'link to duckduckgo'),
    h('a', ['href'=>'https://duckduckgo'], 'search the internet')
  )
);

Here's the output (actual output does not have whitespace)

<div id="wrapper">
  <h1 class="title">Hello, World</h1>
  <p>
    <!-- link to duckduckgo -->
    <a href="https://duckduckgo">search the internet</a>
  </p>
</div>

It's also very handy at rendering collections of data

use function htmlgen\html as h;
use function htmlgen\map;

$links = [
  'home' => '/',
  'cats' => '/cats',
  'milk' => '/milk',
  'honey' => '/honey',
  'donuts' => '/donuts',
  'bees' => '/bees'
];

echo h('nav',
  h('ul',
    map($links, function($href, $text) { return
      h('li',
        h('a', ['href'=>$href], $text)
      );
    })
  )
);

Would output (again, whitespace is here just for display)

<nav>
  <ul>
    <li><a href="/">home</a></li>
    <li><a href="/cats">cats</a></li>
    <li><a href="/milk">milk</a></li>
    <li><a href="/honey">honey</a></li>
    <li><a href="/donuts">donuts</a></li>
    <li><a href="/bees">bees</a></li>
  </ul>
</nav>

It's all 100% PHP and no custom, proprietary funny business. It's highly expressive and lends itself to great compositions. You can break down your templates into easy-to-reuse functions or require calls.

like image 141
Mulan Avatar answered Nov 15 '22 04:11

Mulan