Handling of optional, non-output components

1 view
Skip to first unread message

jaanus.h...@gmail.com

unread,
Aug 20, 2009, 8:16:22 AM8/20/09
to Konstrukt
I have an issue that I haven't been able to solve without ugly
hacking. The problem is based on me having an optional language part
in the request url like http://www.site.com/en/somepage which would
result in a component hierarchy like site_root->site_lang-
>site_structure. The site_lang component spawned for the language part
of the path does nothing except override the normal language
negotiation - no output in itself. The site_root renders the index
page content and wraps the html site.

The option I'm experimenting with now is to extend site_lang from
site_root but that requires me to disable the rendering and wrapping
in the root in case it's followed by a site_lang, besides it leaves
some ugliness in the dispatch code when calling the parent
(parent::dispatch()) that in itself is solvable but in my opinion not
in an optimal way. Feels mostly like an ugly hack.

Another Idea I got was to remove all the rendering from site_root in
favor of site_lang and then, in case there is no language part in the
url, forcibly execute it with forward...

The optimal way in my mind would be to let site_root handle the
possible labguage setting and somehow "step forward" in the url and
execute the rest of the site normally.

Do you have any other ideas for these kind of situations?

anders.ekdahl

unread,
Aug 20, 2009, 2:39:52 PM8/20/09
to Konstrukt
I would say that the best way is to force a redirect in the root to a
language, and let the language component be start page. Otherwise
both / and /en/ (or whatever language is the default) would
technically be the same resource, which would probably get you into
trouble.

Jaanus Heeringson

unread,
Aug 21, 2009, 5:50:28 AM8/21/09
to Konstrukt
Yeah, that was my conclusion to after experimenting with extending the
classes and failing miserably. I am worried about being able to get
the proper path from k_Component::url() after manually forwarding to
to lang when there is no path segment for it though...

jaa...@heeringson.com

unread,
Aug 21, 2009, 9:47:09 AM8/21/09
to Konstrukt
Well, now I have tried it this way to and no real luck either. As I
expected there is an issue with the path due to the forwarding.

Everything works as expected when there is a language segment in the
path, but it falls flat when you leave that one out. I need to be able
to forward to another component without incrementing the path:

root component: site_k lang
index component: site_k_index
structure component: site_k_structure

With language segment
url: http://www.site.com/sv/some/structure
component(name): root(null)->index(sv)_>structure(some)...

Without language segment
url: http://www.site.com/some/structure
component(name): root(null)->index(some)_>structure(structure)...

What I need:
url: http://www.site.com/some/structure
component(name): root(null)->index(null)_>structure(some)...

jaa...@heeringson.com

unread,
Aug 21, 2009, 12:27:36 PM8/21/09
to Konstrukt
Ok, chapter 2 in the ugly, dirty hacks book:

Render everything in site_k_root as usual, but change the context if
needed: $this->url() becomes $this->renderContext->url()

Set the renderContect from site_k_lang if necessary, otherwise it
defaults to site_k_root. Set site_k_lang get to:

function get(){
$this->context->setRenderContext($this);
return $this->context->get();
}

Not pretty but it actually works.

anders.ekdahl

unread,
Aug 22, 2009, 2:19:51 PM8/22/09
to Konstrukt
Say you have:
/sv/some/page
and
/some/page

Both requests would first go to the root component, and then the root
component hands over to the language component. In the first case the
segment is a valid language code, so all is well, and the language
component hands over control to some other component.
In the seconds case, the segment is not a valid language code, so you
would let the language component redirect the user to /[default
language code]/[$_SERVER['REQUEST_URI']]. Not an internal redirect,
but a 301 HTTP redirect. That way, all your requests will contain a
valid language code.

On 21 Aug, 18:27, "jaa...@heeringson.com" <jaa...@heeringson.com>
wrote:

Jaanus Heeringson

unread,
Aug 24, 2009, 3:58:45 AM8/24/09
to kons...@googlegroups.com

Say you have:
/sv/some/page
and
/some/page

Both requests would first go to the root component, and then the root
component hands over to the language component. In the first case the
segment is a valid language code, so all is well, and the language
component hands over control to some other component.
In the seconds case, the segment is not a valid language code, so you
would let the language component redirect the user to /[default
language code]/[$_SERVER['REQUEST_URI']]. Not an internal redirect,
but a 301 HTTP redirect. That way, all your requests will contain a
valid language code.
 
That would of course work, but it's not quite what I was looking for. It is cleaner than my other hacks thought... I'll have to ponder this for a while.

troels knak-nielsen

unread,
Aug 24, 2009, 4:31:42 AM8/24/09
to kons...@googlegroups.com
I'm inclined to side with Anders on this matter. It's better to force
a redirect, as this would ensure that your url's are canonical (eg.
you don't have two url's to point to the same resource). Note that you
can use requestUri(), rather than the global variable $_SERVER.

If you really wanted to have ambiguous url's you could implement it by
having your root component extend from the language-segment component.
Eg.:

class LanguageSegmentComponent extends k_Component {
protected function map($name) {
switch ($name) {
case 'foo':
return 'FooComponent';
}
}
function getLanguage() {
return $this->name;
}
}

class Root extends LanguageSegmentComponent {
protected $valid_languages = array('en','se');
protected function map($name) {
if (in_array($name, $this->valid_languages)) {
return 'LanguageSegmentComponent';
}
return parent::map($name);
}
function getLanguage() {
return $this->valid_languages[0];
}
}

class FooComponent extends k_Component {
function renderHtml() {
return sprintf("<h1>Foo</h1><p>Selected language is:
<b>%s</b></p>", htmlspecialchars($this->context->getLanguage()));
}
}

I didn't test the above code, so I may have missed a typo or so. In
any case, I would suggest that you follow Anders' suggestion.

--
troels
Reply all
Reply to author
Forward
0 new messages