Ask your Symfony questions! Pay money and get answers fast! (more info)

troubleshooting configuration errors on site Symfony

  • SOLVED

Symfony 1.0.22

The site I'm working on has had a lot of people work on it. I feel like the configuration was maybe over-ridden in some places. I'm getting database connection errors with some front controllers, bt not others. How is that possible? For instance, I have this front controller:


define('SF_ROOT_DIR', realpath(dirname(__FILE__).'/..'));
define('SF_APP', 'cms');
define('SF_ENVIRONMENT', 'dev');
define('SF_DEBUG', true);

define('SF_PRODUCT', 'cms' );

require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.$

sfContext::getInstance()->getController()->dispatch();


The config file contains:

$sf_symfony_lib_dir = '/usr/share/php/symfony';
$sf_symfony_data_dir = '/usr/share/php/data/symfony';


The databases.yml file now contains:

all:
propel:
class: sfPropelDatabase
param:
dsn: 'mysql:host=localhost;dbname=zor'
username: autos
password: zzz



On some front controllers, the database connection doesn't work. Any thoughts about how to trouble shoot this?

UPDATE:

Sorry, I should have looked more closely sooner. So, the front controllers load app specific config files, which have this code in them:

// include project configuration
include(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');

// symfony bootstraping
require_once($sf_symfony_lib_dir.'/util/sfCore.class.php');
sfCore::bootstrap($sf_symfony_lib_dir, $sf_symfony_data_dir);

define( 'SERVER_CONFIG_LOCATION','/topconfig/');


The last line I'm thinking gets in the way of some of the normal config files from loading. I assume I can not move this without breaking the existing code, but can anyone suggest a way to force the loading of the normal config files?

I think it would be enough to manually force the loading of the yaml files in the top level config file?

<strong>UPDATE</strong>:

I realize now how much the original builders of the site broke out of the Symfony framework. They wrote their own DATABASE class, which handles most of the connections to the databases. I'm guessing they did this because the site has to switch back and forth between an old Microsoft database and a newer MySql database. They have a Config class that uses the DATABASE class to establish a connection to the database:


private function ConnectDB()
{

if( $this->dbhandle )
return;

require(SERVER_CONFIG_LOCATION.'SysConfig.config.php');
$this->dburi = $DBURI;

$this->dbhandle = DATABASE::Create($this->dburi);
}


Instead of Peer classes, they hand-wrote a bunch of "Getter" classes, which start off like this:

public function __construct( $prefix = '' )
{
$sc = Config::getInstance();
$this->dburi = $sc->Get('CONTENT_DB','');

if( empty($this->dburi) )
throw new Exception ('Content DBURI is not specified in config.');

if( empty($prefix) )
$prefix = SF_PRODUCT;

$this->cmssys = $prefix;
$this->db = DATABASE::Create($this->dburi);
}


There is nothing wrong with any of this, except that somewhere they have seemingly de-activated the normal process whereby Symfony uses Propel to connect to the database. I'd like to know where I should look to force the Propel connection to happen.

Here is the filters.yml file:

rendering: ~
web_debug: ~
security: ~

# generally, you will want to insert your own filters here
screener:
class: genFilter

#Custom Filter for authorition
CMSAuthorization:
class: CMSAuthFilter


cache: ~
common: ~
flash: ~
execution: ~


I do not think any of this would over ride Symfony's normal process for connecting to the database.

UPDATE:

I notice there is no ProjectConfiguration.class.php in the top level config folder. ProjectConfiguration.class.php is standard on the projects I've worked on, using Symfony 1.1 and Symfony 1.2. Did it simply not exist back in version 1.0?

<strong>UPDATE April 8th:</strong>

So, the front controller has this line:

sfContext::getInstance()->getController()->dispatch();

The sfContext class has this initialize method:

protected function initialize()
{
$this->logger = sfLogger::getInstance();
if (sfConfig::get('sf_logging_enabled'))
{
$this->logger->info('{sfContext} initialization');
}

if (sfConfig::get('sf_use_database'))
{
// setup our database connections
$this->databaseManager = new sfDatabaseManager();
$this->databaseManager->initialize();
}

// create a new action stack
$this->actionStack = new sfActionStack();

// include the factories configuration
require(sfConfigCache::getInstance()->checkConfig(sfConfig::get('sf_app_config_dir_name').'/factories.yml'));

// register our shutdown function
register_shutdown_function(array($this, 'shutdown'));
}


I am curious about the sfConfig::get('sf_use_database')) setting. Possibly they turned this off? Does anyone know where this config setting is set?

UPDATE:

I notice the core file sfContext has this non-static method:

/**
* Retrieve a database connection from the database manager.
*
* This is a shortcut to manually getting a connection from an existing
* database implementation instance.
*
* If the [sf_use_database] setting is off, this will return null.
*
* @param name A database name.
*
* @return mixed A Database instance.
*
* @throws <b>sfDatabaseException</b> If the requested database name does not exist.
*/
public function getDatabaseConnection($name = 'default')
{
if ($this->databaseManager != null)
{
return $this->databaseManager->getDatabase($name)->getConnection();
}

return null;
}


So I added these 3 lines to my front controller:

$instance = sfContext::getInstance();
echo " get database connection";
echo get_class($instance->getDatabaseConnection());


I got "get database connection" followed by nothing. So I tried to explicitly reference the propel connection:

$instance = sfContext::getInstance();
echo " get database connection";
echo get_class($instance->getDatabaseConnection('propel'));


Still nothing. This is what I currently have in databases.yml:


default:
propel:
class: sfPropelDatabase
param:
dsn: mysql:[email protected]/zor
username: autos
password: zzz


So, I am thinking the previous programmer turned off the database connections. But I need to find where that config setting is set.

UPDATE:

I have a partial solution now. If I open up the controller and paste in 2 lines to create a database connection, then everything works. This (with a lot of debugging junk) is what I have in my front controller right now:

<?php

define('SF_ROOT_DIR', realpath(dirname(__FILE__).'/..'));
define('SF_APP', 'cms');
define('SF_ENVIRONMENT', 'dev');
define('SF_DEBUG', true);

define('SF_PRODUCT', 'cms' );

require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTOR$

$instance = sfContext::getInstance();

echo " get database connection";
echo get_class($instance->getDatabaseConnection('Propel'));


$databaseManager = new sfDatabaseManager();
$databaseManager->initialize();


echo get_class(sfContext::getInstance()->getController()->dispatch());

//sfContext::getInstance()->getController()->dispatch();



But part of my job is to make this Symfony installation more standard. So I do not want to leave the front controller like this. Where is the configuration setting set for database connections?

UPDATE:

Okay, so I opened up the core file /usr/share/php/symfony/util/sfContext.class.php and added in a check to see if the database connections were being set up:

echo " use database: ";
echo sfConfig::get('sf_use_database');
die();

if (sfConfig::get('sf_use_database'))
{
// setup our database connections
$this->databaseManager = new sfDatabaseManager();
$this->databaseManager->initialize();
}


Nothing shows up after "use database", so the 2 crucial lines that normally set up the database connection are never getting set. I am assuming the original programmer turned this off when they were writing all of their custom database connection code.

So, again, does anyone know where the sf_use_database configuration setting is set?

Answers (2)

2010-04-06

Martin Palacio answers:

What do you mean exactly with "the database connection doesn't work"?

=> (Please, give us al least the error string and backtrace if possible)

Check for "legacy" connection scripts scattered around your app, ex. using mysql_connect(). Maybe there is some component using this kind of code.
If not, check:
* your schema.yml file, pointing to the right connection('propel' by default)
* your model classes, same thing.

Try to add environment-specific configuration in your databases.yml (ex. a "dev" section with different connection parameters). Check the documentation or a newly generated databases.yml file for examples.

Maybe rebuilding schema, model and clearing cache would help?

=> Check propel.ini too, look for:


propel.database.url = (same dsn as in databases.yml)
propel.database.creole.url = {propel.database.url}
propel.database.user = user (as stated in dsn)
propel.database.password = password (as stated in dsn)


put the correct values by editing the file by hand.
Then, try to rebuild schema-model-cc...again.


marshall comments:

Rebuilt model and cleared cache. Still the same problem.


marshall comments:

mppfiles, the stack trace is the similar to what I posted in my previous question, but now the problem is only happening in parts of the Symfony project, in certain apps or dev controllers:


[PropelException]

No connection params set for propel



stack trace

at ()

in SF_SYMFONY_LIB_DIR/vendor/propel/Propel.php line 476 ...



$dsn = isset(self::$configuration['datasources'][$name]['connection']) ? self::$configuration['datasources'][$name]['connection'] : null;



if ($dsn === null) {



throw new PropelException("No connection params set for " . $name);



}





include_once 'creole/Creole.php';

at Propel::getConnection('propel')

in SF_ROOT_DIR/lib/model/om/BaseZorMicrosoftContentPeer.php line 202 ...

at BaseZorMicrosoftContentPeer::doSelectRS(object('Criteria'), null)

in SF_ROOT_DIR/lib/model/om/BaseZorMicrosoftContentPeer.php line 196 ...

at BaseZorMicrosoftContentPeer::doSelect(object('Criteria'))

in SF_ROOT_DIR/apps/cms/modules/zor/actions/actions.class.php line 27 ...

at zorActions->executeCourses()

in SF_SYMFONY_LIB_DIR/action/sfActions.class.php line 53 ...

at sfActions->execute()

in SF_SYMFONY_LIB_DIR/filter/sfExecutionFilter.class.php line 129 ...


marshall comments:

It is an odd site. They broke out of the Symfony framework in a lot of places. Instead of relying on Propel, in most places they get a database connection like this:

$sc = SysConfig::getInstance();
$direct = $sc->Get('CONTENT_DBURI');
$db = DATABASE::Create($direct);


Martin Palacio comments:

I never heard about such classes, sounds like custom ones.
I don't know why are they here. You have to dive in to understand how these works, and get rid of them wherever possible.
If you really need them, just be sure to load the configuration from databases.yml.

Sounds like a more complex issue!


Martin Palacio comments:

OK...try to start with a new front controller, pointing to the same app and environment, and finally add that line:

define( 'SERVER_CONFIG_LOCATION','/topconfig/');


Martin Palacio comments:

so...


<?php

define('SF_ROOT_DIR', realpath(dirname(__FILE__).'/..'));
define('SF_APP', '##APP_NAME##');
define('SF_ENVIRONMENT', 'dev');
define('SF_DEBUG', true);

require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');

sfContext::getInstance()->getController()->dispatch();


Martin Palacio comments:

Sorry I had a wrong reading of your last update. I think it was the code from other front controller.

The code you have posted lately correspond to a normal apps/myapp/config/config.php one.
The last line seems to be added by hand. It just stands for a constant that may be used in some parts of the code. Check where and how it's being used.

As a side note, I strongly recommend to setup the xdebug php extension to perform some debugging in a dev machine (don't enable it on production server). It will help you a lot.


marshall comments:

mppfiles, yes, sorry if I was unclear. The reference to "/topconfig/" is really weird. The folder is at the top level of the server. It is outside of the Symfony project. The file simply contains the database info:

<?php
$mysqlConnection = 'mysql://zor:[email protected]/auto';


That is the whole file. Most of the Symfony code fetches this and then, I think, manually creates a database connection. In other words, the people who built this system were barely using the Symfony framework.

The model classes all start off like this:

public function __construct( $prefix = '' )
{
$dburi = DBConfig::getInstance()->Get('MICROSOFT_CONNECTOR','');
$this->db = DATABASE::Create($dburi);
}


I've no idea if this was standard in Symfony 1.0, but it seems to me that the creators of this system broke out of the Symfony framework a lot, and did things in a custom manner.

Part of my current job is to make the current site a more standard Symfony installation. But, clearly, I'm struggling to figure out what they did when they set things up.


Martin Palacio comments:

You're right Marshall. "ProjectConfiguration.class.php" is the replacement of config.php files since sf 1.1.

I really don't see anything wrong with the filters you posted. I don't know exactly what are they for, but don't seem to be related.

Some hint: I never needed to override the constructor for the model classes. In fact, only in sf 1.3+ you get an empty __construct() for extending after propel:build-model.

Such code is definitely not standard, nor related to symfony. Please, try to get rid of it if possible.

The Courses action just performs a doSelect(new Criteria)? can you please post the code for this action? (executeCourses)


marshall comments:

mppfiles,

I do not think the problem is at the level of the action. The code is very basic:

public function executeCourses(){
$c = new Criteria();
$c->addDescendingOrderByColumn(WssOracleContentPeer::CONTENT_ID);
$this->listAllCourses = WssOracleContentPeer::doSelect($c);

}


The problem seems to be at an earlier point. For some reason the code is simply unaware of any credentials being set for Propel.


Martin Palacio comments:

OK then...got to search somewhere else.
Meanwhile, as a proof of concept, try this:


public function executeCourses(){

$con = Propel::getConnection(); // => new line, or $con = Propel::getConnection('propel');
$c = new Criteria();

$c->addDescendingOrderByColumn(WssOracleContentPeer::CONTENT_ID);

$this->listAllCourses = WssOracleContentPeer::doSelect($c, $con); //forcing using $con as new parameter



}


Can you post please the content of BaseWssOracleContentPeer.php?


Martin Palacio comments:

Some kind of off-topic...

You databases.yml states (as posted by you):

dsn: 'mysql:host=localhost;dbname=zor'

What about:

dsn: mysql:[email protected]/dbname

?


marshall comments:

mppfiles, good thought, I will try the different dsn style.


marshall comments:

No, did not work. I think Symfony is never seeing the databases.yml file. It is not being loaded, that is my guess.


marshall comments:

I added in the Propel::getConnection() line that you suggested. This lead to a slightly different error message:


[PropelException]
No connection params set for default

stack trace
at ()
in SF_SYMFONY_LIB_DIR/vendor/propel/Propel.php line 476 ...

$dsn = isset(self::$configuration['datasources'][$name]['connection']) ? self::$configuration['datasources'][$name]['connection'] : null;

if ($dsn === null) {

throw new PropelException("No connection params set for " . $name);

}


include_once 'creole/Creole.php';
at Propel::getConnection()
in SF_ROOT_DIR/apps/cms/modules/zor/actions/actions.class.php line 25 ...
at zorActions->executeCourses()
in SF_SYMFONY_LIB_DIR/action/sfActions.class.php line 53 ...
at sfActions->execute()
in SF_SYMFONY_LIB_DIR/filter/sfExecutionFilter.class.php line 129 ...
at sfExecutionFilter->execute(object('sfFilterChain'))
in SF_SYMFONY_LIB_DIR/filter/sfFilterChain.class.php line 43 ...
at sfFilterChain->execute()
in SF_SYMFONY_LIB_DIR/filter/sfCommonFilter.class.php line 29 ...



so $dsn is still testing "null".


Martin Palacio comments:

sfConfig::get('sf_use_database')) is looking for a "use_database" on settings.yml.

But you already posted the contents of your settings.yml file.

It's weird, database settings are activated by default.

Glad you found a partial solution. Looking for something else.


Martin Palacio comments:

Hold on...your latest version of your databases.yml has a "default" value on line 1. It must be just "propel". Just look [[LINK href="http://trac.symfony-project.org/browser/tags/RELEASE_1_0_22/data/skeleton/project/config/databases.yml"]]here [[/LINK]]to see the original file.
Hint: [[LINK href="http://trac.symfony-project.org/browser/tags/RELEASE_1_0_22/data/skeleton"]]this page[[/LINK]] contains the "default" files when creating new projects, apps, modules, etc.. Use it as a reference.


Martin Palacio comments:

Look [[LINK href="http://trac.symfony-project.org/browser/tags/RELEASE_1_0_22/data/skeleton/app/app/config/settings.yml"]]here[[/LINK]], line 50. See? it's enabled by default, that's why it's commented. Try to add that line nevertheless...


Martin Palacio comments:

Just to be sure, find the "use_database" word on your whole project. Maybe it's deactivated somewhere else, ex.: an action, with: sfConfig::set('sf_use_database', false);


marshall comments:

Thanks so much. You've been a huge help. Yes, in the app settings.yml file, the use_database had been uncommented and and set to "no". I did not copy and paste that part of the file, because I did not see that it had been uncommented.

2010-04-06

Gert Findel answers:

let us have a look at the factories.yml and settings.yml files of the apps where the database conn doesnt work. Maybe the DB is disabled.


marshall comments:

factories.yml:

cli:
controller:
class: sfConsoleController
request:
class: sfConsoleRequest
response:
class: sfConsoleResponse

test:
storage:
class: sfSessionTestStorage

all:
# controller:
# class: sfFrontWebController
#
# request:
# class: sfWebRequest
#
# response:
# class: sfWebResponse
#
# user:
# class: myUser
#
storage:
class: sfSessionStorage
param:
session_name: msc_cookie
auto_start: false
# storage:
# class: sfSessionStorage
# param:
# session_name: symfony
#
# view_cache:
# class: sfFileCache
# param:
# automaticCleaningFactor: 0
# cacheDir: %SF_TEMPLATE_CACHE_DIR%



settings.yml:

prod:
.settings:
no_script_name: on

dev:
.settings:
error_reporting: <?php echo (E_ALL | E_STRICT)."\n" ?>
web_debug: on
cache: off
no_script_name: off
etag: off

test:
.settings:
error_reporting: <?php echo (E_ALL | E_STRICT & ~E_NOTICE)."\n" ?>
cache: off
web_debug: off
no_script_name: off
etag: off


Gert Findel comments:

Not very helpful, do you have only one schema?
What is the output of the error you are getting?


marshall comments:

I noticed obvious errors in propel.ini, which I tried to fix with

symfony configure:database "mysql:host=localhost;dbname=zor" autos zzz

But I got:

[pakeException]
Task "configure:database" is not defined.


Possibly that task didn't exist back in version 1.0.22 of Symfony?


marshall comments:

In propel.ini, I see this line:

propel.output.dir = /home/robbard/ctt


This directory does not exist. What folder is this suppose to point to? I mean, what is the point of this configuration instruction? What is needed here?


Gert Findel comments:

sure, it is possible the configure:database task didnt exist for sf1.0
you have already fixed the databases.yml with the dsn
you can fix the propel.ini file manually or you can start a new project and then copy/paste the new propel.ini file, fixing the only the details


Gert Findel comments:

propel.output.dir should be the main directory for your sf project