Jump to content

Using OOP PHP for HTML


PHPcoder182

Recommended Posts

I am a completely self-taught programmer and have been building my knowledge for 3 years. My site runs seasonally with a break for 3 months in the summer, which every year gives me a chance to do something new with the site. I tend to find every year I almost start my site from scratch because my knowledge I have learnt in that year makes my code redundant. This year the big change I'm making is switching from procedural to OOP.

 

My site has a lot of HTML tables and I have therefore used OOP to generate these table with very little code. This has been extremely efficient and some table which would previously take 50 lines of code I can generate in 4 now. 

 

My question is, do most PHP programmers use OOP in this way (i.e. for generating HTML code more efficiently). I didn't start doing it because I read somewhere to do it. I just applied my knowledge of OOP in a way that I thought would be useful. My concern is whether or not someone with better OOP knowledge might think this was the wrong way to do things, whether that be because there is an even better way to do it or if it is just not the done thing. 

 

I guess you could make the argument that if it makes things more efficient (which it does do to an extreme) then it is obviously good, and it makes use of the DRY principles, but I just want to know if this is a typical way to use OOP.

 

Essentially what I have is a class to connect to the database, an extended class to run the Mysql query, a further extended class for generating a table and a class extended from this to hold an array of details to dynamically change that table. 

Link to comment
Share on other sites

My question is, do most PHP programmers use OOP in this way (i.e. for generating HTML code more efficiently).

Do most programmers use OOP to generate HTML? Not often.

Do most programmers who need something to help them generate HTML use OOP? Probably many do.

 

HTML generation code tends to be

a) A function. Something that generates an HTML table isn't really an object per se.

b) A sort of "HTML table factory" class, where it makes sense to go OOP as the class represents a thing that creates tables. And that's not just semantics.

c) A utility class geared towards generating HTML, and one (or more) methods would be about generating tables. Not OOP in the truest sense but merely a bunch of functions all put in one place.

 

I didn't start doing it because I read somewhere to do it. I just applied my knowledge of OOP in a way that I thought would be useful. My concern is whether or not someone with better OOP knowledge might think this was the wrong way to do things, whether that be because there is an even better way to do it or if it is just not the done thing.

Like I showed above, it could be implemented reasonably using OOP, or implemented reasonably not using OOP. Personally I've always wanted a lot of control over the table markup and creating a generator to accommodate everything is a hassle that's not worth the time.

 

I guess you could make the argument that if it makes things more efficient (which it does do to an extreme) then it is obviously good, and it makes use of the DRY principles, but I just want to know if this is a typical way to use OOP.

That argument does hold water, but it needs to be weighed against other arguments. For example,

- Is it maintainable? If there is a bug with the implementation, how easy would it be to fix?

- Is it extensible? A big part of OOP is about reusing classes - mostly through inheritance. Can this class be extended to create another table generator that is somehow "more specific"? (If such a thing could possibly make sense.)

- Is the code acceptable to someone who is familiar with object-oriented programming? It may not be ideal but is it at least something the person won't scratch their head about wondering what could have possessed someone to write that code.

 

Essentially what I have is a class to connect to the database, an extended class to run the Mysql query,

So a generic class for database connections, and a child class that adds MySQL queries? Okay.

 

a further extended class for generating a table

Less okay. Extending a class should be about specializing it. Extending a class because you want to use its functionality is not very good; more often you should simply have an instance of the first class as a member variable in the second class.

class DatabaseProvider { ... }

class DatabaseConsumer {

	private $database = null;

	public function __construct() {
		$this->database = new DatabaseProvider();
	}

}
In my mind there are four classes so far:

// generic database stuff
// abstract because this class doesn't know enough information to actually communicate with a database
abstract class Database { ... }

// specialized database stuff
class MySqlDatabase extends Database { ... }

// potential related classes
class PostgreSqlDatabase extends Database { ... }
class OracleDatabase extends Database { ... }
class MongoDatabase extends Database { ... }


// generic html generator, probably has some common functionality and helper methods
// abstract because you need the specialized knowledge in subclasses in order to generate particular html elements
abstract class HtmlGenerator { ... }

// specialized <table> html generator
class TableHtmlGenerator extends HtmlGenerator { ... }

// potential related classes
class ListHtmlGenerator extends HtmlGenerator { ... }
class ImageHtmlGenerator extends HtmlGenerator { ... }
class LinkHtmlGenerator extends HtmlGenerator { ... }
The first two help you connect to the database while the second two help you generate your table markup.

 

I don't actually see a need for another class that (presumably) uses the database to get information and then pass it along to the generator class for rendering. That's actually the kind of thing that I would leave procedural: what you're doing is heavily dependent upon what this table is for and where you're putting it.

$database = new MySqlDatabase();
$users = $database->getRecentSignedUpUsers(10); // ten most recent

// so very many ways you could do the table generation. here's one idea:
$table = new TableHtmlGenerator($users);
$table->addColumn("User ID", "id"); // heading, array key
$table->addColumn("Username", "username");
$table->addColumn("Registration Date", "registered");
$table->output();

and a class extended from this to hold an array of details to dynamically change that table.

I touched on this subject with the HtmlGenerator, TableHtmlGenerator, and example code. In general a class should represent a blueprint to an object; in this case the TableHtmlGenerator would contain a blueprint to an HTML table. (More precisely it's a blueprint for a thing that can generate an HTML table.) That class also has a method where it can take the blueprint and produce an actual thing (the output).

 

Taking a class for generating a table, then extending it in order to provide details doesn't make so much sense. What good is that first class if it doesn't have details? It won't be able to do anything. It could make sense to extend that first class with another subclass that provides different details, but that could turn into a slippery slope where you need tons of subclasses for the tons of different details that could be shown in a table. If you think about it, tables all use basically the same details: headings and data, (naturally it can get more complicated) so you could just have that first class accept details from somewhere? Now you have the TableHtmlGenerator.

Thinking about it some more, you could decide you want another class: one for generating lists. You go about making it and then realize that you're writing a bunch of code that looks similar to what's in the TableHtmlGenerator: start tags, end tags, attributes... Individual HTML elements all work the same way and what varies is what elements you use in what order. That's where the HtmlGenerator class comes in. It's not very useful by itself as the idea of blueprint for a universal HTML generator is a bit too broad to cover in one class, but it can include logic that other HTML generator classes would find handy.

abstract class HtmlGenerator {

	protected function writeElement($tagname, array $attributes = array(), $innerHTML = null) {
		echo "<", $tagname;
		foreach ($attributes as $attr => $value) {
			echo " ", $attr, '="', htmlspecialchars($value, ENT_QUOTES, "UTF-8"), '"';
		}
		echo ">";

		if ($innerHTML !== null) {
			echo $innerHTML, "</{$tagname}>";
		}
	}

	protected function writeEndElement($tagname) {
		echo "</{$tagname}>";
	}

}
class TableHtmlGenerator extends HtmlGenerator {

	public function output() {
		$this->writeElement("table");
		if ($this->columns) {
			$this->writeElement("tr");
			foreach ($this->columns as $heading) {
				$this->writeElement("td", array(), $heading);
			}
			$this->writeEndElement("tr");
		}
		// ...
	}

}
Edited by requinix
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.