0

I'd like to make an application in CakePHP which manages exercises and users results. Users and results are not important in this question.

I want to have a possibility to add an exercise with adding only a specific table and line to .ini config file. Application should route to a GenericExercisesController if specific one doesn't exists. Controller should load a GenericExerciseModel if specific doesn't exists. I'd managed with model loading and partially with routing with controller like this:

In route.php

foreach(Configure::read('exercisesTables') as $exerciseName){
    if( App::import('Controller', Inflector::pluralize($exerciseName))){
        Router::connect('/exercises/'.Inflector::pluralize($exerciseName).'/:action', array('controller' => Inflector::pluralize($exerciseName)));
    }else{
        Router::connect('/exercises/'.Inflector::pluralize($exerciseName).'/:action', array('controller' => 'GenericExercises', 'fakeModel' => $exerciseName));
    }
}

So if I want to load an exercise Foo I should use address:

http://example.com/exercises/Foos/view

And this works fine, doesn't matter if specific controller exists.

Problem begins when I use reverse routing to generate links in views. If exercise Foo have specific controller this works correctly:

print $this->Html->url(array('controller' => Inflector::pluralize($exerciseName), 'action' => 'view')); produces: /exercises/Foos/view

But when exercise Bar doesn't have specific controller then the same code produces: /Bars

This causes a problem, there is no Bars Controller.

Temporarily I'm generating those links manually, but I don't think that this is the best solution:

print $this->Html->url("/".Configure::read('exerciseRoutingPrefix')."/".Inflector::pluralize($exerciseName)."/view");

Maybe someone of you know a better solution. Thank you for reading my question.

UPDATE 1:

Those are routes in route.php defined before foreach in order as they're in file:

Router::connect('/', array('controller' => 'questions', 'action' => 'regulations'));
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
Router::connect('/help', array('controller' => 'pages', 'action' => 'faq'));
Sebastian Piskorski
  • 4,026
  • 3
  • 23
  • 29

1 Answers1

1

If I understood your question correctly, you could try making a "MyHtmlHelper" which does some magic before parsing your options to the HtmlHelper::link();

You can do it like so:

/app/View/Helpes/MyHtmlHelper.php

Create a helper which extends the "HtmlHelper" like so:

<?php
App::uses('HtmlHelper', 'View/Helper');
class MyHtmlHelper extends HtmlHelper {
    public function link($title, $url = null, $options = array(), $confirmMessage = false) {
        //do your magic here and change the $title, $url or $options accordingly.
        return parent::link($title, $url, $options, $confirmMessage);
    }
}

Now in your controller, you should include the Helper like so (aliasing) $helpers = array('Html' => array('className' => 'MyHtml')); instead of $helpers = array('Html');.

I guess you can fill in the blanks on the public function link yourself. If not, feel free to ask more help :)

Off course it is possible to do this with every other Helper or method you can think off. HtmlHelper::link() is just used as example.

Jelmer
  • 2,663
  • 2
  • 27
  • 45
  • Thank you for the answer. That might do the trick, but I'm not sure if this is the best way. I'd rather like to use cakePHP native functions if it is possible. I'll check it anyway and mark as right answer eventually. – Sebastian Piskorski May 09 '13 at 12:10
  • 1
    It is Cakephp native when you extend a helper :) I do it all the time. Just use the aliasing so you can still use the same names which will prevent the core from failing :) – Jelmer May 09 '13 at 13:26
  • If I place MyHtml in AppController then all classes should use MyHtml by default? Right? – Sebastian Piskorski May 15 '13 at 11:09
  • 1
    Yes. But make sure to make use of the aliasing. So that you can use `$this->Html->method()` instead of `$this->MyHtml->method()` – Jelmer May 15 '13 at 11:36
  • 1
    It did the trick. Thank for the tip with aliasing. Sill I'd like to find more elegant solution. Maybe some day :) – Sebastian Piskorski May 17 '13 at 13:07
  • @SebastianPiskorski I think this is an elegant method. Since you are using the extended helpers which is perfectly fine. I use it all the time for setting default link values and default form values for example. So I don't have to redo it all the time. Also for link generating which is getting messy when using prefixes. I like it to reset by default so that I don't have to set every prefix to false every time I create a link. So, I think this is the way to go :) – Jelmer May 17 '13 at 14:39