Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Data Model Questions /

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

PageComments on (.htaccess driven) DataObject pages


Go to End


3 Posts   1706 Views

Avatar
Xurk

Community Member, 50 Posts

28 May 2010 at 9:54pm

Edited: 28/05/2010 9:56pm

I've been reading the boards here for an hour or so and found a lot of interesting and related topics to my problem, but nothing which quite manages to point me sufficiently in the right direction.

First of all, I'll briefly explain what I'm trying to create here. Using Silverstripe 2.4, I've developed a module for displaying two types of Articles (both site-owned articles and articles on other websites being linked to). Seeing as more than 100 articles being published on the website per year is pretty likely, I opted to store them as DataObjects (using the brilliant DataObjectManager module) rather than have each article be a Page in the SiteTree. The articles on external websites being linked to do not need to have their own page on the website, but the site-owned articles do (the user is provided with a "Read more..." link for each article on the overview page).

Seeing as the articles are DataObjects and do not have their own unique pages, I've implemented this functionality by adding a line to my installation's .htaccess and adding a method to the Article_Controller class which acts on the parameters given in the URL. This looks like so:

.htaccess

# This redirects articles/intern/43/a-friendly-title to articles/intern/?article=43
RewriteRule articles/intern/([0-9]+)/.*$		articles/intern/?article=$1 [NC,QSA,L]

Article_Controller class
function ArticleSelect() {
	if (!isset($_GET['article']) || !is_numeric($_GET['article'])) { return false; }

	// Cast the querystring variable to an integer type
	$iArticleID = (int) $_GET['article'];

	$oArticle = DataObject::get_by_id("ArticleIntItem", $iArticleID);

	return ($oArticle) ? $oArticle : false;
}

It's perhaps worth mentioning that the "a-friendly-title" part is ignored as it's there solely for SEO purposes and is a formatted version of the $Title value which belongs to an article (stripping out spaces and special characters etc.).

Now this - to my elation - worked just fine. But the website's visitors should also be able to post comments on the articles and so I've added $PageComments and $Form to the template. This is where the problem arises; the comments do get posted, but upon the (I presume) Director::redirectBack() code being executed, the visitor is redirected to a page which doesn't exist.

To be precise, they get redirected to: articles/intern/#PageComment_X (the X being the comment number)
Instead of being redirected to: articles/intern/43/a-friendly-title#PageComment_X

I understand that this is due to the CommentForm's action excluding the "/43/a-friendly-title" part of the URL and posting the form to "articles/intern/PageComments/PostCommentForm". So my actual question here, is how to get the form to recognize and incorporate the rewritten parts of my URL?

I've read about adding Director rules to the _config.php file or adding $url_handlers to the controller class, but haven't manage to implement them successfully. This is how I tried to accomplish it:

public static $url_handlers = array(
	'articles/intern/$ID' => 'ArticleSelect'
);

This has no effect, but I'm not really aware of how to use this variable properly so it's probably due to incorrect implementation of it?

This thread seems to be related to my situation as well, but again, I'm not sure how to go about implementing $UrlSegment to solve my problems.

Subsequently, while writing up this post I've noticed another drawback to having all of the articles being displayed on the same page (the ArticleHolder page which - in the CMS - contains the DataObjectManager for all the articles). Which is that all of the articles now share the same comments due to not being unique pages themselves... whoops.

Any help would be much appreciated! I hope someone more experienced can give me a few helpful pointers :)

Avatar
Xurk

Community Member, 50 Posts

1 June 2010 at 8:04pm

Edited: 01/06/2010 8:05pm

(Sorry for bumping this thread - deadlines to be made! Sound familiar? ;-) )

Is there anyone out there with any ideas on this subject? I've solved the latter problem I came across (comments being shared for all DataObjects) by adding a ArticleComment class with a $has_many relationship to each ArticleItem and displaying the comments in another tab (with a DataObjectManager) next to the Articles tab.

But I'm still struggling with posting to the ArticleItem "pages". The form action directs the user to:

/<site root>/articles/intern/articleCommentForm
which makes the "Director::redirect(<relative URL>)" or "Director::redirectBack()" methods impossible(?) to implement as the rewritten part of the URL in
/<site_root>/articles/intern/<ID>/<title>/articleCommentForm
is lost.

Any tips or ideas would be very much appreciated :)

Avatar
Xurk

Community Member, 50 Posts

2 June 2010 at 12:29am

Well, I've managed to concoct an elaborate work-around, which I'll share in case anyone else ever runs into my problem. But again, if anyone out there has a better idea (of which I'm positive they must exist!), feel free to share it :)

What I've done is added a "new HiddenField" to the comment form on an article's page. This field is called "RedirectTo" and is populated with the part of the URL after the host name, using $_SERVER['REQUEST_URI']. The method which processes the submission of the form then implements the following line of code to transport the user back to the "page" (with a rewritten URL):

Director::redirect($oForm->dataFieldByName('RedirectTo')->dataValue());

Again, it's not the most elegant solution, but it gets the job done for now.