PHP object or an array - php

I am writing an app that allows users to modify and change some of their site settings. I am just constructing a form generator that will send various options to variuous plugins to generate the code what I am wondering is whether I should be using objects for this rather than multidimensional arrays? If so how would I change my code?
So right now I have made this- its very long and going to get longer so I have only pasted part of it for the sake of brevity:-
$scopeSettings = array(
'site_background' => array(
'subpanels' => array(
'colour' => array(
'plugins' => array(
'colourchooser' => array(
'tip' => "The background colour appears underneath the 'Background Image' (if set)-hover over the '?' around the colour chooser for extra tips on how to use it",
'element' => 'body',
'gradientenabled' => 'true',
'opts' => array (
'closed' => 'true',
'advanced' => array(
'tip' => "You can paste in your own generated gradient codes in here",
'checkbox' => true
)//end advanced
)//end Opts
)//end colour chooser
)//end plugins
),//end colour sub panel
'pattern' => array(
'plugins' => array(
'patternselector' => array(
'tip' => "Use the pattern selector to apply effects like moire or scan lines to your background image",
'element' => 'patimg'
)//end patternselector
)//end plugins
),//end pattern sub panel
)//end subpanels
)//end site background
);//end scope settings
What would be best practice with this sort of thing?

Maybe this is a stupidity, but you can use "YAML" or "JSON" as configuration format for an application no?
As for example Symfony or other framework.

My advise: try YAML or XML or JSON to get a more readable config file, then parse it back to an array in your own code.

I would store the settings in <insert your markup language of choice> (XML, JSON, YAML, etc.).
You can then cache these in a $_SESSION variable, and populate it when you bootstrap if they don't already exist:
session_start();
if (!isset($_SESSION['settings'])) {
// Assuming you choose JSON...
$settings = json_decode(file_get_contents('settings.json'), TRUE);
$_SESSION['settings'] = $settings; // array
$_SESSION['settings'] = (object)$settings; // object
}
Whether or not you use an array or object then becomes just a matter of what access syntax you prefer:
$_SESSION['settings']['site_background']['subpanels']['colour']...
// vs.
$_SESSION['settings']->site_background->subpanels->colour...

I would say that some like Array Oriented Programmation and that, with PHP 5.4 they can express themselves in a great way.
However, more people are used to OOP -so do I- and It can be a more readable way to code your solution.

I think in this route I would go with a structured object oriented route. You can have a parent object, that holds all of the children objects (setting groups) and you can even retrieve on setting group as an object of its own. Each object will have its own definitions and properties which can be documented in the code that provides useful information within an IDE (if you use docblocks).

I would use objects. Assuming you are making a form, you should have several classes:
Form - to hold the form, will have a property $input_list (or $node_list to hold all of the inputs
Input - to describe a single input item, it should have properties like label, type, tip etc.
Fieldset - to describe a fieldset, to hold additional items inside. Like the Form class, it would have an $input_list to hold all of the inputs inside of it.
Those classes can stand alone, and can be extended to have customized common input types (for instance)
class Checkbox extends Input {
public $type = 'checkbox'
....
}

As other's people here also my opinion is to use YAML or JSON - using this it could be done in very simple way.
Just for instance an example of JSON format of Your data structure:
var settings = {
'site_background' : {
'subpanels' : {
'colour' : {
'plugins' : {
'colourchooser' : {
'tip' : "The background colour appears underneath the 'Background Image' (if set)-hover over the '?' around the colour chooser for extra tips on how to use it",
'element' : 'body',
'gradientenabled' : 'true',
'opts' : {
'closed' : 'true',
'advanced' : {
'tip' : "You can paste in your own generated gradient codes in here",
'checkbox' : true
}//end advanced
}//end Opts
}//end colour chooser
}//end plugins
},//end colour sub panel
'pattern' : {
'plugins' : {
'patternselector' : {
'tip' : "Use the pattern selector to apply effects like moire or scan lines to your background image",
'element' : 'patimg'
}//end patternselector
}//end plugins
}//end pattern sub panel
}//end subpanels
}//end site background
};//end scope
You can use PHP functions like json_encode and json_decode for JSON <-> PHP data transformation. Using curly braces means that the elements are objects while when replaced by [ and ] you got arrays...
But also a PHP OOP approach could be used succesfully especially when using extendability. You could have one main class Settings having some default properties and e.g. magic __get and __set functions and then You can implement many subsettings subclasses extending from this main Settings class.

Related

How to implement a PHP Form processing logic that is reusable?

I am new to PHP and I have a lots of forms in PHP. The forms make use of the standard HTML Input fields and need to be validated on the serverside. How can I implement this, so that I do not have to write lots of boilerplate HTML over and over again, rather only write the minimal amount of code that generate the "full forms". What is the recommended approach to implement this? Thanks.
If you prefer to do it all yourself, you should at least do it PHP-Classes which will save you from re-writing (if done right ;-)). Handle attributes of the fields through an assoc array, e.g. like this:
<?php
$form = new Form("MyInput", array ("submit" => "myform.php") );
$form->AddField("input_text", array ("label" => "Your name") );
?>
To handle validation, you could use attributes such as
$form->AddField("input_text", array (
"label" => "Your name" ,
"validate" => "required"
) );
(Only examples, there's a lot of code releated to this which you'd need to write once...)
That should be useful for learning purposes...
Next, you could use JS to validate. Pls. note that JS does client-side validation only and you cannot rely on it being executed (user might have turned of JS in his browser), so you still MUST validate in PHP when receiving the data. (And you could use JS-Libraries for that - I've used Parsley and was quite happy with it...)
If you want to skip that experience, use Frameworks or Templating Engines.
I would suggest to create a form template. Consider using a method (of class View):
private static function capture($view_filename, array $view_data)
{
extract($view_data, EXTR_SKIP);
ob_start();
require $view_filename;
return ob_get_clean();
}
And call the static function capture (caution: consider using of __toString() to print objects) Pseudo-code:
echo View::capture('template', array('id' => '1', 'class' => 'userForm', 'inputs' => array(0 => array('label' => 'Name', 'type' => 'text'), 1 => array('label' => 'Password', 'type' => 'password')));

How to display model data in various formats?

I am changing the data provided by my model in the afterFind() method, so the id is clickable text, like this:
$this->id = CHtml::link($this->id, array('/admin/auditTrail/view', 'id' => $this->id));
However, this changes every single occurrence of id value - it is in lists, in detail page, even in breadcrumbs, which is unwilling of course. How can I decide which format I will use in different views? For example, in breadcrumbs and in view.php I just want the raw value, but in the list (admin.php) I would like to use the html link, like this:
'columns'=>array(
array(
'name' => 'id',
'type' => 'html',
),
On a separate note - is this a good approach in terms of MVC, I mean changing display in a model? Should not be model only used for a database manipulation stuff?
No, this is not a good approach. There are a number of alternative approaches that would be better, for example:
Let the view do the conversion
Don't do anything in the model. When the view wants to display clickable anchors instead of bare ids, it should generate the URLs itself. This is somewhat quick and dirty (it puts the logic of URL generation in the view, which is not ideal) but it's easy and it works well if you only need to do it in one or two places.
Expose the URL as a separate property
Place a calculated read-only property in your model:
public function getAuditTrailUrl()
{
return Yii::app()->createUrl('/admin/auditTrail/view',
array('id' => $this->id));
}
You can then use the auditTrailUrl property in any view. The nice thing about this approach is that the URL generation is opaque to the views and therefore easily modifiable.
You can use this syntax to easily render links from these URLs in your CDataGrid:
'columns' => array(
array(
'class' => 'CLinkColumn',
'urlExpression' => '$data->auditTrailUrl',
)
),
In the above definition $data refers to each model in the grid, as per the documentation.

How do I access the property of a widget

I'm new to the Yii framework and I'm trying to access a property of the of a widget let's say CMenu where I want to change the values of some public properties like activeCssClass, firstItemCssClass, lastItemCssClass, htmlOptions etc. so how do you change the property of a widget in Yii.
Details:
I'm using Yii version 1.1.12 (Aug 19, 2012) and I'm trying to generate a multilevel menu but I need to change the values of some public class parameters and I don't know how?
Well, normally you apply needed values when you call the widget. You set them at the appropriate array inside widget call after widget class name.
$this->widget('zii.widgets.CMenu',
array(
'items' => $items,
'id' => 'main_menu',
'htmlOptions' => array('class' => 'nav'),
'activeCssClass' => 'active',
'firstItemCssClass' => 'first_item'
)
);
BUT! If you want to apply the values after you created some widget, but have not rendered it yet (really rare case) you can do this thing:
$widget = $this->beginWidget('application.components.MyOwnWidget');
$widget->public_property = 'aaa';
$widget->renderSomething();
$this->endWidget();
Adding on the previous answer, in case you missed it, don't forget to check the short and simple official documentation on this.

Dynamic input generation with Zend_Form

Good morning,
I have a multilingual backend application which has to support n languages.
The languages are stored in a database and can be added at any moment.
Now for my backend functionality, I need to dynamically generate <input> fields based on the languages stored in my db, for example:
German: <input type="text" id="title_de">
English <input type="text" id="title_en">
Italian <input type="text" id="title_it">
...
I currently add them like this using Zend_Form:
foreach($languages as $language){
$title = new Zend_Form_Element_Text("title_" . $language->getPrefix());
$title->setLabel("Title " . $language->getPrefix())
->setRequired(true)
$this->addElements(array($title));
}
And this is how I save the fields to my DB using Doctrine:
//get language-dependent title and write to DB
foreach($languages as $language){
$title->setLanguage($language);
$title->setContent($form->getValue("title_" . $language->getPrefix()));
$touristArea->addTitle($title);
//persist and flush
$em->persist($touristArea);
$em->flush();
}
Anyway, as I have many language dependent fields (Titles, Captions, etc.), the code to process the form can get quite nasty and I always have to query the language table in my DB in order to know what inputs have been generated.
Is there a better way to do this? Like with an array of inputs or something like that? Thanks for any inputs :)
I suggest you to use Zend_Translate component
First of all create source file with translations ->
Creating Array source files
Array source files are plain arrays. But you have to define them manually since there is no tool to aid this. But because they are so simple, it's the fastest way to look up messages if your code works as expected. It's generally the best adapter to get started with translation business.
$english = array(
'message1' => 'message1',
'message2' => 'message2',
'message3' => 'message3');
$german = array(
'message1' => 'Nachricht1',
'message2' => 'Nachricht2',
'message3' => 'Nachricht3');
$translate = new Zend_Translate(
array(
'adapter' => 'array',
'content' => $english,
'locale' => 'en'
)
);
$translate->addTranslation(array('content' => $german, 'locale' => 'de'));
Since release 1.5 it is also supported to have arrays included within an external file. You just have to provide the filename and Zend_Translate will automatically include it and look for the array. See the following page for more info about source files
Then take a look for Internationalization of Zend_Form
In order to initialize I18n in forms, you will need either a Zend_Translate object or a Zend_Translate_Adapter object, as detailed in the Zend_Translate documentation. Once you have a translation object, you can attach a translator to a specific form instance or to specific elements using their setTranslator() methods:
// Tell *this* form instance to use a specific translate adapter; it
// will also be used to translate validation error messages for all
// elements:
$form->setTranslator($translate);
// Tell *this* element to use a specific translate adapter; it will
// also be used to translate validation error messages for this
// particular element:
$element->setTranslator($translate);
Detailed guide is here

How to build a PHP form Dynamically with OOP?

How would I go about creating a real world form creation class that I can use to display a new form with fields of different types, as how many fields I want, I can use drop downs and I can do all of this by using OOP?
To be honest I wouldn't roll my own, considering there are a few mature form packages out there for PHP.
I use PEAR's HTML_QuickForm package (http://pear.php.net/manual/en/package.html.html-quickform.php) for PHP4 sites.
For PHP5, I'd have a look into Zend_Form (http://framework.zend.com/manual/en/zend.form.html).
For my quickform code, I use a helper class that lets me define forms using a config array. For example:
echo QuickFormHelper::renderFromConfig(array(
'name' => 'area_edit',
'elements' => array(
'area_id' => array('type' => 'hidden'),
'active' => array('type' => 'toggle'),
'site_name' => array('type' => 'text'),
'base_url' => array('type' => 'text'),
'email' => array('type' => 'text'),
'email_admin' => array('type' => 'text'),
'email_financial' => array('type' => 'text'),
'cron_enabled' => array('type' => 'toggle'),
'address' => array('type' => 'address'),
),
'groups' => array(
'Basic Details' => array('site_name', 'base_url'),
'Address Details' => array('address'),
'Misc Details' => array(), // SM: Display the rest with this heading.
),
'defaults' => $site,
'callback_on_success' => array(
'object' => $module,
'function' => 'saveSite',
),
));
Note that the above element types 'address' and 'toggle' are in fact multiple form fields (basically, meta-types). This is what I love about this helper class - I can define a standard group of fields with their rules (such as address, credit_card, etc) and they can be used on lots of pages in a consistent fashion.
You definitely can. Consider a Form class which stores information about the form itself: the method, action, enctype attributes. Also throw in stuff like an optional heading and/or description text at the top. Of course you will also need an array of input elements. These could probably be put into their own class (though subclassing them for InputText, InputCheckbox, InputRadio maybe be a bit over the top). Here's a vague skeleton design:
class Form {
var $attributes, // array, with keys ['method' => 'post', 'action' => 'mypage.php'...]
$heading,
$description,
$inputs // array of FormInput elements
;
function render() {
$output = "<form " . /* insert attributes here */ ">"
. "<h1>" . $this->heading . "</h1>"
. "<p>" . $this->description . "</p>"
;
// wrap your inputs in whatever output style you prefer:
// ordered list, table, etc.
foreach ($this->inputs as $input) {
$output .= $input->render();
}
$output .= "</form>";
return $output;
}
}
The FormInput class would just need to store the basics, such as type, name, value, label. If you wanted to get tricky then you could apply validation rules which would then be converted to Javascript when rendering.
I will go against other advice here and suggest that you build your own library to generate forms. If you fail, you will still learn a lot in the process.
The design process is most important here. You start from the top and ask yourself what goes on a form. At an abstract level, a form is full of elements. Some are visible, some are not, some can be entered by the user but others cannot, some elements can trigger other elements... and the list goes on...
Eventually you end up with elements that are "decorative" (Text, Headings, Separators, Fieldsets, Links, Images), elements that are interactive (Inputs, Dropdowns, Checkboxes, Radio buttons, Submit Buttons) and finally elements that are neither decorative nor interactive (Hidden Inputs, Anchors and elements that act as containers to group other elements.)
Once you have the different categories organised you start looking into features that all elements have and you can put that into the base element class. Then you go up the chain making your classes doing more and more, inheriting from other simpler element classes. In my library, the base element class is called form_element and each form_element has a unique name that no other element within the same form can have. A form_element also has a set of attributes. It has a function that all elements have called render(). In the base class render() does nothing (so a base element is always invisible) but in derived classes it starts producing HTML. By the way, I never make any of my classes create HTML. Instead I have a static class called html which writes HTML for all the classes that needs its services.
Very early in the chain of form elements, you should have one, a container that groups others. It should have an add() function and its render() function should consist of calling the render() function of all its sub-elements. the form class will be derived from this container class.
Spend plenty of time on the design. Pay attention to compatibility with the rest of your library.
If you want the data from the form to come from a database and be saved to one, you will need to add this functionality and have a form element class linked to a table and column. Here too, I have a separate DB class that can retrieve/save the data. I have a query class that creates queries. Form elements should have nothing to do with creating HTML, creating queries or accessing a database. My static class DB and my query class take care of the dirty work. The form class should only be involved with form stuff. The form class collects into an array all the tables and columns for the fields that need to be saved and pas it to the query class which creates the query which is then passed to the DB class which executes it.
Once you are properly setup, what appears to be horrendously complicated suddenly becomes very easy with properly designed classes.
Because you have a class that can write HTML, your form class needs to just html::init() and follow it with render() and the entire HTML code for the form is available within the html buffer. html::output() flushes everything out.
Validation is also handled externally with a static validation class. Form elements that can be validated hold validation instructions within an array in a format that can be passed directly to the validation class. Each element that needs to be validated is bound to an error element which displays the error if the element does not validate or remains invisible if all goes well.
This is to show you that when you design a form environment (or anything else) you really need to consider absolutely everything before you get started. The work that you put into it may not immediately translate into code that can power your application but it will sure make you a much better developer, thus making your future projects much easier to handle.
The form class creates a form, the html class creates the HTML, the query class makes queries and the DB class handles the database. If your classes start doing work that should be done by separate classes, you have a design problem.
Here is a code sample to show how my form library works:
$fm = new form('myform');
$fm->binding(FORM_DATABASE);
$fm->state(FORM_RETRIEVE);
$fm->set_recno(1);
$fm->add(new form_heading("My form"));
$fm->add($el=new form_input("name",40));
$el->bind_data('mytable','mycolumn');
$el->set_attribute('size', 25);
$el->set_default('Name');
$fm->add($el=new form_submit("submit_btn","Submit"));
if($fm->manage())
{
redirect or do something else here. The interaction with the form is done. The initial state for the form was FORM_RETRIEVE. If it had been FORM_NEW it would have displayed default values instead of the retrieved record and saved the form as a new record in the table.
}
Note that the manage() function of the form takes care of absolutely everything, retrieving data from the database, rendering the form into the view, validating data and saving it back to the database.
One of the advantages of creating forms programmatically (as above) is the option to write your own form-based code generator to create the code to make your forms.
I hope this can help you or someone else.
Just for reference, Object Oriented Forms by Khurram Khan is an excellent OO forms implementation for PHP.
Here is a sample of what the code looks like:
$form = new Form("Register", "form.php");
$personal = new Block("Personal Information");
$name = new Text("name", "Your name");
$name->setDescription("this is my description");
$name->addValidator(new MaxLengthValidator("The name you have entered is too long", 30));
...
Another more popular implementation is PHPlib. However, I find this to be a bit clunky; it seems like it's just some standard functional programming wrapped in a class.
Another option would be writing an abstraction for the built in DOM library. This will allow you to manually create any kind of form and form element using OO notation, with the added benefit that you will be returned an OO DOM instance that can be used elsewhere in your program.
You definitely should use OO PHP to do forms, and all the rest of your HTML output. I could not find any PHP library (many of the links in these answers are dead) to do what I wanted, so I wrote PHPFUI. It is not a generic HMTL output library, but outputs pages for the Foundation CSS Framework. You could easily use the same technique to output a more vanilla page, or Bootstrap or what ever. I did not want to write a generic HTML OO PHP library, as I wanted something lean and mean for performance reasons. Also I don't like to over engineer stuff, so it is hard coded to Foundation. But the same principles would apply to any PHP library that would want to output clean HTML with no validation issues, which you often find in hand written HTML.

Categories