Jump to content


Photo

Any implications of having custom classes instead of Page?


  • Please log in to reply
6 replies to this topic

#1 adamkiss

adamkiss

    Master of the universe

  • Moderators
  • 1,078 posts
  • 289

Posted 31 May 2012 - 04:18 AM

Hey all (and Ryan, mostly ;) )

During me playing with PW, I noticed that you can set different PHP Object for pages, instead Page. SO what I do now: I have custom Autoloader added (in the end of config), have custom classes for all templates (extending Page class), and all templates are redirected to index.php, which only calls some default function $page->render();

Why? This allows me now do stuff like this: '$page->children()->renderListItem();', which I find superclean.

I also teamed up with Steve (netcarver) to see whether there is some performance hit. There is, but minor one - application went from 24 rqs/s down to 21 rqs/s, which I am pretty much okay with.

But (there is always one), I am curious whether there are any other implications? This possiblity is hidden in the advanced settings, which you recommend only to module makers – but I would need to turn this on for each page I'll be working on, so... I am asking. :)

Are there any?

#2 Soma

Soma

    Hero Member

  • Moderators
  • 3,218 posts
  • 1769

  • LocationSH, Switzerland

Posted 31 May 2012 - 04:32 AM

I don't understand why and what exactly you did. But for having $page->children()->renderListItem(), you could just simply create a module to add that method to page array objects. I've done similar things in a project.

@somartist | modules created | support me, flattr my work flattr.com


#3 adamkiss

adamkiss

    Master of the universe

  • Moderators
  • 1,078 posts
  • 289

Posted 31 May 2012 - 04:41 AM

TL;DR: I basically wrap the original Page object (the one that is returned from PW when you call $page or PageArray->eq(0), for instance) into my own PHP class, so I can add my own code to different template classes.

This is makes it easier (for me, at least) to separate the logic part (when deciding stuff based on input or urlSegments, for isntance) from the HTML code generation itself – it's very "MVC-ish" :)

#4 apeisa

apeisa

    Hero Member

  • Moderators
  • 2,530 posts
  • 859

  • LocationVihti, Finland

Posted 31 May 2012 - 09:26 AM

I use that kind of stuff in every project. Here is one of my "MarkupRenderHelper" modules (stripped some code to make it easier to follow - might throw few errors because of that, but should give the idea):
<?php

class MarkupRenderHelper extends WireData implements Module {
public static function getModuleInfo() {
  return array(
   'title' => 'Render Helper',
   'version' => 100,
   'summary' => 'Simple module that adds few methods to Pagearray and Page object. -Antti',
   'singular' => true,
   'autoload' => true
   );
}
public function init() {
  $this->addHook('PageArray::renderArticleList', $this, 'renderArticleList');
  $this->addHook('Page::renderListItem', $this, 'renderListItem');
  $this->addHook('Page::renderTags', $this, 'renderTags');
  $this->addHook('Page::renderMeta', $this, 'renderMeta');
  $this->addHook('Page::firstImage', $this, 'firstImage');
}
public function renderArticleList($event) {
 
  $articles = $event->data['object'];

  $out = "<ul class='acticles-list'>";
  foreach($articles as $p) {
   $out .= $p->renderListItem();
  }
  $out .= "</ul>";
  $event->return = $out;
}
public function renderListItem($event) {
  $p = $event->data['object'];
  $parent = $p->parent();
  $out = "";
  $img = $p->firstImage();

  if ($p->author) $author = $p->author . ",";

  $out .= "<li class='$parent->name'>";
  if ($img) {
   $img = $img->width(130);
   $out .= "<img src='$img->url' width='$img->width' height='$img->height' alt='$img->description' />";
  }
  $out .= "<div class='text-holder'>";
  $out .= $p->renderMeta();
  $out .= "<h2><a href='$p->url'>$p->title</a></h2>";
  $out .= "<p>$p->summary</p>";
  $out .= "</div>";
  $out .= "</li>";
  $event->return = $out;
}
public function renderMeta($event) {
  $p = $event->data['object'];
  $parent = $p->parent();
  $author = ($p->author) ? $p->author . "," : "";
  $out = "<span class='meta'><a href='$parent->url'>$parent->title</a> $author $p->publish_date </span>";
  $event->return = $out;
}
public function renderTags($event) {
  $p = $event->data['object'];
  $out = '';
  foreach($p->tags as $tag) {
   $out .= "<a href='$tag->url'>$tag->title</a>";
   if ($tag !== $p->tags->last()) $out .= ", ";
  }
  $event->return = $out;
}
public function firstImage($event) {
  $p = $event->data['object'];
  if (count($p->images) > 0 ) {
   $img = $p->images->first();
  } else {
   $img = false;
  }

  $event->return = $img;
}
}

Sometimes I add "widgets" for $pages object too. Then I can just do <?= $pages->renderInfobox() ?> or something like that.

#5 adamkiss

adamkiss

    Master of the universe

  • Moderators
  • 1,078 posts
  • 289

Posted 31 May 2012 - 09:30 AM

Antti: but do you do this for your templates too?

Edit: Oh, I see what you did there; You are adding a custom hooks to fake class methods, right?

#6 Soma

Soma

    Hero Member

  • Moderators
  • 3,218 posts
  • 1769

  • LocationSH, Switzerland

Posted 31 May 2012 - 09:41 AM

apeisa, yes that's what I did. I thought why so complicated if there's a nice method to add those in PW. Sorry to not explain further.

@somartist | modules created | support me, flattr my work flattr.com


#7 ryan

ryan

    Hero Member

  • Administrators
  • 5,811 posts
  • 3132

  • LocationAtlanta, GA

Posted 31 May 2012 - 12:29 PM

When it comes to markup render stuff that is needed throughout the site, I also use that hook/module method mentioned above, adding new hook methods as needed to Page and PageArray.

$events = $pages->find("template=event, sort=-date, limit=3"); 
echo $events->renderEvents();

Either that, or I'll just put them in a separate file and call them up with functions:

include("./tools.inc"); 
echo renderEvents($events); 

If i'm making a lot of repetitive $pages->find() calls, I might also add a new hook method to $pages to serve as a filter so that I could do this:

$events = $pages->events("limit=3");

I think that inheritance isn't ideal if all you need is to add some new methods to a class. While it works, it's adding another level of complexity, so I prefer to plug-in to things where possible, rather than extend them through inheritance. But what works for one doesn't necessarily work for all, and people have different preferences and ways of achieving things, so I would stick with whatever makes the most sense for your project.

The inheritance of Page that you see in PW's core (like User, Permission, etc.) is more about having a separate type for typecasting purposes, than it is for extending functionality of Page. Though in PW's case, it does both. But if I didn't need separate typecasting (for argument type hints and such) then I might have utilized hooks for these instead. It was also a way to keep the system consistent with PW 2.0, which had User, Permission, Role classes that weren't Page objects. By making the new classes extend Page, it was a way to avoid potentially breaking older code that expected those types.

As for implications, stuff that is in 'Advanced' mode is there because I don't really know the full implications. :) So if you find everything works, I think you are good. But the only implication I would be worried about is just what happens during upgrades and whether they are more likely to affect the approach you are using. I can't say for certain, as I don't totally understand the approach, but if it works now, it's more likely to continue working than not. That being said, the further you go in using a different approach from others, the more difficult it may be to troubleshoot when something doesn't work.

Using an MVC approach with PW also doesn't need to be complex. If you think of your template files as PHP controllers, your $page(s) as your model, and use the TemplateFile class to render your views, you have an easy to use and implement MVC setup. There are applications where I like to use this approach. But for most web sites I find it more convenient and maintainable to use templates, modules and includes in a more traditional way. There are times when layers on top of markup makes things better, and there are times when it makes it worse.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users