1

I'm working on a small CakePHP application that is subject to the following constraint (awkward but out of my control): I need it to work on either of two identical databases, with the choice being based on URL. For example:

http://www.example.com/myapp/foo/action/param
http://www.example.com/myapp/bar/action/param

The first obvious solution is to have two identical CakePHP applications at myapp/foo and myapp/bar with different database configurations. This has a kludgy feel to it, though, so I'm trying to find an elegant way of creating a single application.

The approach I'm considering is this: Define routes such that myapp/foo and myapp/bar will be associated with the same controller. Then give my DATABASE_CONFIG class a constructor:

function __construct() {
  $pathParts = explode('/', $_SERVER['REQUEST_URI']);
  if (array_search('foo', $pathParts)) {
    $this->default = $this->fooConfig;
  } else if (array_search('bar', $pathParts)) {
    $this->default = $this->barConfig;
  }
}

(Where of course I've defined fooConfig and barConfig for the two databases.) I do have control over the URL, so I can be confident that there won't be extraneous occurrences of foo or bar in the URL.

My question is this: Is there a simpler, more elegant way of handling this odd situation? Maybe something in AppModel and/or AppController? Although I'm getting rid of duplicated code, I can't shake the feeling that I'm replacing one code smell with another.

0

2 Answers 2

1

There are a few ways to do this, here is one.

Write a sweet custom route in which you always match:

Router::connect('/:ds/*', array(), array('routeClass' => 'SweetDbRoute'));

Then have SweetDbRoutes set a class variable you can use everywhere, including in your model constructors. Then it should fail so you don't actually adjust the request.

App::import('SweetDbClass', array('file' => '/path/to/your/sweet_db_class.php'));
class SweetDbRoute extends CakeRoute {
    // put your failing route code here, but use your SweetDbClass to track datasource ...
    // see http://book.cakephp.org/view/1634/Custom-Route-classes
}

Then in your AppModel:

App::import('SweetDbClass', array('file' => '/path/to/your/sweet_db_class.php'));
    class AppModel extends Model {
    public function __construct($id = false, $table = null, $ds = null) {
        $ds = SweetDbClass::$ds;
        parent::__construct($id, $table, $ds);
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

You can also find various methods to help you with datasource manipulation like Model::setDataSource()
+1 for the sweet code. I'll play around with this. (Also... welcome!)
I'm trying to use this solution but I didn't fully understand. What does the "failing route code" mean? That I should have a parse function that always returns false? How do I setup my other routes then? And if you have time, could any of you take a look at my question to help me out: stackoverflow.com/questions/21066388/… ?
0

So for example, after you perform an insert in one database, the two won't be "identical", right? Are these 2 DB somehow synced with each other? I don't know what do you need to do on those DB, but it's probably easier just to do 2 separate apps.

Yes, you can specify the DB configuration in the model: http://book.cakephp.org/view/922/Database-Configuration but you can't change it on-the-fly though (the models are not expected to change association to another table, I suppose). What you do is probably the only way.

I do have control over the URL, so I can be confident that there won't be extraneous occurrences of foo or bar in the URL

Yes, there can be "extraneous occurrences of foo or bar in the URL" :)) But it won't break your app.

1 Comment

Okay, what I meant was that the databases have identical schema. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.