Flourish PHP Unframework
This is an archived copy of the forum for reference purposes

help: simple question - Best practice?

posted by johnstontrav 9 years ago

Hi,

Multi db connections, is this correct/best practice??

define db connections in init.php


$prod = new fDatabase('mssql', 'production', 'produser', 'password');
$stage = new fDatabase('mssql', 'stage', 'stageuser', 'password');

Then how do i access these db connections in all classes?

eg:

class User {

function qryProd() {

  return $prod->query('select * from users');
}

function qryStage() {

  return $stage->query('select * from users');
}

}

Cheers, Trav

Trav,

I don't know if there is a Flourish-y way to do this, I will give you a way that I handle this that works for me, if it works for you feel free to use it.

When I make a project I create a configuration directory structure like this.

project/
  `-config/
      `-environment.config.php
      `-environments/
          `-development.config.php
          `-qa.config.php
          `-production.config.php
  `-the rest of the project...

My deployment script never deploys environment.config.php, that's a special file that I put into each environment, it normally just contains the following lines.

<?php
  define('ENVIRONMENT', 'development');  //Replace development which whatever environment it is.
?>

Then in init.php or if you are using a front-controller you can do something like this

<?php
  require_once CONFIG_DIR . 'environment.config.php';
  require_once CONFIG_DIR . 'environments/' . ENVIRONMENT . '.config.php';

  //More init stuff below.

?>

Then you are free to put in your production configuration something like

  $database = new fDatabase('mssql', 'production', 'produser', 'password');

And in your development configuration put

  $database = new fDatabase('mssql', 'stage', 'stageuser', 'password');

Then in your user class you can just put

class User {
  function list() {
    return $database->query('select * from users');
  }
}

This way you only have to write one function for the class and your code automatically selects the correct database based off of what you have in ENVIRONMENT.config.php.

It's also nice because if you have other settings that differ between certain environments, test API endpoints versus real API endpoints, stuff like that, you can cleanly separate your environment configurations.

This has worked for me in the past, I hope you find it useful.

posted by ihumanable 9 years ago

thanks ihumanable, but when i implement your code i get undefined error in my class when calling db

return $database->query('select * from users');

Error: Undefined variable: database

What am i missing?

posted by johnstontrav 9 years ago

Well it depends on how you are including things, more than likely $database is out of scope. You could handle this a number of ways. In PHP you can access something in the global scope by using the global keyword like so.

class User {
  function list() {
    global $database;
    return $database->query('select * from users');
  }
}

This of course is not a very nice solution since it introduces global state which is not a very good practice. Flourish has a fairly robust ORM that is really nice to use, check out fActiveRecord. In your init script you can attach the database by using the fORMDatabase::attach() function. In your configuration file you would change

  $database = new fDatabase(...);

to

  fORMDatabase::attach(new fDatabase(...));

Now you can access the database connection by using the fORMDatabase::retrieve() method like so

class User {
  function list() {
    return fORMDatabase::retrieve()->query('select * from users');
  }
}

If you are doing basic CRUD operations I would highly suggest reading up on the fActiveRecord and fRecordSet classes (as well as fCRUD) as they will save you a ton of time. If you do then you can make a class like so

class User extends fActiveRecord {
  static function list() {
    return fRecordSet::build('User');
  }
}

Since User is an fActiveRecord you can then use the whole array of awesome functionality like:

$newUser = new User();
$newUser->setFirstName('New');
$newUser->setLastName("O'User");  //Look ma, no SQL Injection attacks because of fActiveRecord
$newUser->store();

$allUsers = User::list();
foreach($allUsers as $user) {
  //fActiveRecord encode means that "Timmy <strong>Beefcake</strong>" won't inject html into your markup
  echo $user->encodeFirstName() . ' ' . $user->encodeLastName() . '<br />';
}
posted by ihumanable 9 years ago

Thanks ihumanable, your post has helped me alot!

posted by johnstontrav 9 years ago