have defined different models and modelMappers in my php project.
my folders are structured as follows
-application
--models
---DbTable
----modelName
---modelMapperName
modelName.php
class Application_Model_DbTable_ModelName extends Zend_Db_Table_Abstract{
}
modelMapper.php
class Application_Model_ModelMapper
{
}
everytime i try to access the values in my database by creating an instance of my mapper in the controller i get the message No adapter found for Application_Model_DbTable_ModelName
i thought this can be an issue with the autoloader and added the following code in the bootstrap,
$loader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Application',
'basePath' => APPLICATION_PATH
));
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->setFallbackAutoloader(true);
return $loader;
but it still didnt work, can anyone help me figure out where i am going wrong?
thank you.
This error it's related to database initialization...
You have to configure the database adapter in your application.ini:
resources.db.adapter = "pdo_mysql"
resources.db.params.host = "localhost"
resources.db.params.username = "user"
resources.db.params.password = "password"
resources.db.params.dbname = "db"
Or you could also configure the database adapter in your bootstrap file:
$db = Zend_Db::factory("pdo_mysql", $params);
Zend_Db_Table::setDefaultAdapter($db);
Since the variable APPLICATION_PATH returns de full path to your application folder try naming your classes only
Model_DbTable_ModelName
i found out that the variable i was trying to access didn't start with an underscore and also capitalization issues with the models created was causing the problem.
Thank you all for helping
Related
I've got a dubious issue. I have a set of existing annotated Doctrine entities which have been successfully used in a Symfony2/Doctrine2 project. However, I'm currently isolating some core functionality of this project into it's own web framework independent library and I can't seem to get the entities to function properly.
At the moment my major concern is the fact that the Doctrine CLI utility is giving me mixed results.
When I do the following:
bin/doctrine orm:validate-schema
I get the following output:
[Mapping] OK - The mapping files are correct.
[Database] OK - The database schema is in sync with the mapping files.
But when I do:
bin/doctrine orm:info
I get this:
[Exception]
You do not have any mapped Doctrine ORM entities according to the current configuration. If you have entities or mapping files you should check your mapping configuration for errors.
I have gone over my configuration a gazillion times now. I've even removed all my entities and left a most basic User entity in there giving me the same scenario.
What could possible be the source of these mixed results?
It turns out that the standard Doctrine config set up [1] doesn't work with my code base, or any code base I have tested with, maybe the docs are outdated. After ploughing through the Interwebs for hours, this is the configuration that finally made it work for me:
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
use Doctrine\Common\Annotations\AnnotationReader;
$paths = array( realpath(__DIR__."/../src/My/Entity") );
$isDevMode = TRUE;
// the connection configuration
$dbParams = array(
'driver' => 'pdo_mysql',
'user' => 'myuser',
'password' => 's3cr3t',
'dbname' => 'mydb',
);
$cache = new \Doctrine\Common\Cache\ArrayCache();
$reader = new AnnotationReader();
$driver = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader, $paths);
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
$config->setMetadataCacheImpl( $cache );
$config->setQueryCacheImpl( $cache );
$config->setMetadataDriverImpl( $driver );
$entityManager = EntityManager::create($dbParams, $config);
//-- This I had to add to support the Mysql enum type.
$platform = $entityManager->getConnection()->getDatabasePlatform();
$platform->registerDoctrineTypeMapping('enum', 'string');
[1] http://docs.doctrine-project.org/en/latest/tutorials/getting-started.html
The accepted answer is ok but the same thing could be achieved in less verbose manner:
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
$paths = array( realpath(__DIR__."/../src/My/Entity") );
$isDevMode = TRUE;
// the connection configuration
$dbParams = array(
'driver' => 'pdo_mysql',
'user' => 'myuser',
'password' => 's3cr3t',
'dbname' => 'mydb',
);
$config = Setup::createAnnotationMetadataConfiguration(
$paths, $isDevMode, null, null, false
);
$config->setQueryCacheImpl(new \Doctrine\Common\Cache\ArrayCache());
$entityManager = EntityManager::create($dbParams, $config);
//-- This I had to add to support the Mysql enum type.
$platform = $entityManager->getConnection()->getDatabasePlatform();
$platform->registerDoctrineTypeMapping('enum', 'string');
All here is about usage of simple annotation driver or not (last parameter of the Setup::createAnnotationMetadataConfiguration function. By default, a simple annotation driver is used which doesn't recognise the #ORM\Entity annotation.
I have PHP entity in Ressources/config/doctrine/Foo.orm.php
but I use annotation.
Too different way for orm = [Exception]
You do not have any mapped Doctrine ORM entities according to the current configuration. If you have entities or mapping files you should check your mapping configuration for errors.
Just delete the bad entity file
For me it happened that I imported the vendor directory from a different system and it wasn't working properly.
A simple composer install or php composer.phar install fixed it.
I'm trying to create an API with Phalcon for the first time.
I have been followed the tutorial "http://docs.phalconphp.com/en/latest/reference/tutorial-rest.html", but encountered a problem.
I've been created a new project with all the settings, and inside I got:
a "models" folder with "photos.php" file
a "index.php" with connection to my DB and function to retrieve information from "photos" table
The problem is that when I'm trying to activate the function through the browser i get an Error:
"Phalcon\Mvc\Model\Exception: Model 'photos' could not be loaded inC:\wamp\www\Test\index.php on line 77".
$photos = $app->modelsManager->executeQuery($phql); // line 77
What can cause this problem?
It's one of three problems:
1 - Your class name in photos.php is not photos.
2 - You have mis-referenced the photos model in your PHQL query.
3 - You have not registered the directory where your models are stored. To do this, add
$loader = new \Phalcon\Loader();
$loader->registerDirs(array(
'/path/to/models'
))->register();
after
$di = new \Phalcon\DI\FactoryDefault();
but before
$app = new \Phalcon\Mvc\Micro();
If you create project structure using Phalcon developer tool, the config.ini might need an update like this:
from:
modelsDir = /models/
to:
modelsDir = **..**/models/
i just faced same issue, got it solved by add require with model path right after $di = new \Phalcon\DI\FactoryDefault(); and
before $app = new \Phalcon\Mvc\Micro($di);
like suggested by brian
I have next settings in application.ini
resources.db.adapter = PDO_MYSQL
resources.db.params.host = localhost
resources.db.params.username = some
resources.db.params.password = somepass
resources.db.params.dbname = name
resources.db.isDefaultTableAdapter = true
have 2 similar models Zend_db_table_Abstract
in first model i use
$db = Zend_Db_Table::getDefaultAdapter();
all work fine
but if i try use same in the second
i see next message
Exception information:
Message: No adapter for type Zend_Db_Statement_Pdo
i tried to take adapter using another method but i see same Message
trying
in class extended zend_db_table_abstract
$this->getDefaultAdapter
Registry var db in Zend_registry from bootstrap
all time i see same message
Any idea ?
$db = Zend_Db_Table::getDefaultAdapter();
$db->query('SET #rank:=0');
try this
A few questions regarding the basics of Zend Framework 1.9.
i followed the quickstart guide, and basically, bootstrapping involves,
a. from index.php:
$ZEND_FRAMEWORK_LIB_PATH = '/appl/ZendFramework-1.9.7/library';
defined('APPLICATION_PATH') || define('APPLICATION_PATH', (realpath(dirname(__FILE__) . '/../application')));
defined('APPLICATION_ENV') || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));
set_include_path(implode(PATH_SEPARATOR, array((dirname(dirname(__FILE__)) . '/library'), $ZEND_FRAMEWORK_LIB_PATH, get_include_path(),)));
require_once 'Zend/Application.php';
$application = new Zend_Application(APPLICATION_ENV, (APPLICATION_PATH . '/configs/application.ini'));
$application->bootstrap()->run();
b. Then in the Bootstrap.php, i have
protected function _initAutoload()
{
$autoloader = new Zend_Application_Module_Autoloader(array("namespace" => "Default_", "basePath" => dirname(__FILE__),));
return $autoloader;
}
protected function _initDoctype()
{
$this->bootstrap("view");
$view = $this->getResource("view");
$view->doctype("XHTML1_STRICT");
}
For a start, a few things i don't understand:
a. If a user access the site not via the default index.php, does that mean that bootstrapping (and indeed, all the code in the index.php including setting of environment etc, will be bypassed?)
b. There is no place that explicitly calls the Bootstrap's _initAutoload() or _initDoctype() methods. So when are these methods implicitly invoked?
c. Since in the index.php, i have already "passed in" the config file '/configs/application.ini' to the Zend_Application constructor, is there any way to retrieve the config entries elsewhere?
In my application, i have to work with different databases (so i can't just use resources.db.*). So in the same application.ini file, i have, e.g.
custdb.adapter = "PDO_MYSQL"
custdb.params.host = "localhost"
custdb.params.username = "username"
custdb.params.password = "password"
custdb.params.dbname = "custdb"
What's the best practice to manage the DB adapter?
a. Is it possible to (and should i) create the DB adapter in index.php OR Bootstrap.php and retrieve it elsewhere when needed (and how)?
b. Or is possible to (and should i) just retrieve the config entries elsewhere (how?) and instantiate the DB adapter as and when needed?
Thanks!
Here's a few answers.
2a. All request are redirected to index.php. This is done with mod_rewrite and specified in the .htaccess file.
2b. The bootstrap calls any method prefixed with _init. See Zend Framework - Theory of Operation
2c. Yes. Zend::Config. You could store an instance in Zend::Registry for easy access. Eg:
$config = new Zend_Config((APPLICATION_PATH . '/configs/application.ini'));
$application = new Zend_Application(APPLICATION_ENV, $config);
Zend_Registry::set('config', $config);
Check the API reference to see the constructors for these two classes.
I don't think the Quick start is that helpful. I'd recommend a getting a book. I enjoyed "Zend Framework 1.8 Web Application Development" by Keith Pope.
To answer question 3, ZF uses the Application Resource Plugin Zend_Application_Resource_Db to ingest the config and create a database adapter instance.
If your need for multiple databases is an environmental thing, you can easily namespace your DB params in your application.ini file.
[production]
resources.db.adapter = PDO_MYSQL
resources.db.params.host = localhost
resources.db.params.username = user
resources.db.params.password = pass
resources.db.params.dbname = production_db
[staging : production]
resources.db.params.dbname = staging_db
[development : production]
resources.db.params.dbname = development_db
In this example, we're setting up common info in the [production] section and overriding it for our staging and development environments. Which config is applied is controlled by the environment variable in your app's .htaccess
If you need to access multiple databases in a single application, then I would recommend rolling your own Application Resource Plugin, and creating some kind of structure to hold multiple connections.
It's not as difficult as it might seem. Read up on it here and create a subclass of of Zend_Application_Resource_ResourceAbstract. Using this class, you can easily grab resources.* in your config file using:
$this->getBootstrap()-getResource('mydb')`
You would then have access to your plugin via the bootstrap object:
$bootstrap->getPluginResource('mydb')
Hope that helps.
EDIT: I forgot to mention, if you have a resource plugin as part of your application.ini, the Zend_Application bootstrapper will automatically know to include it as part of the bootstrap proccess, so you don't need to define any _init() method in your bootstrap file. It's kind of magic like that.
Also, as far as storing an adapter instance, I'd probably just user Zend_Registry.
thanks for all your replies! It really helped my understanding of the concept of ZF.
i've also gone through the references and source codes to get a deeper understanding, and this is what i adopted:
In my application.ini i have:
custom.db.customers.adapter = "PDO_MYSQL"
custom.db.customers.params.host = "localhost"
custom.db.customers.params.username = "username"
custom.db.customers.params.password = "password"
custom.db.customers.params.dbname = "custdb"
Then, in my Bootstrap.php i have:
protected function _initCustomDbCustomers()
{
$config = $this->getOptions();
$cfgCustom = $config['custom'];
if (null != $cfgCustom)
{
$cfgCustomDb = $cfgCustom['db'];
if (null != $cfgCustomDb)
{
$cfgCustomDbCustomers = $cfgCustom['customers'];
if (null != $cfgCustomDbCustomers)
{
$resrcCustomDbCustomers = new Zend_Application_Resource_Db($cfgCustomDbCustomers);
return $resrcCustomDbCustomers
}
}
}
}
Of course, in my index.php, i call:
$application->bootstrap();
$application->run();
Then, in the controller where i need to get the DB adapter, i do:
$bootstrap = $this->getInvokeArg('bootstrap');
$resrcCustomDbCustomers = $bootstrap->getResource('customDbCustomers');
$adpCustomDbCustomers = $resrcCustomDbCustomers->getDbAdapter();
// Do Stuffs With DB Adapter
Is this a Good/Bad way to do things? And is there any pitfall i should watch for?
Thanks!
I am using Zend_Application and it does not feel right that I am mixing in my application.ini both application and user configuration.
What I mean with this is the following. For example, my application needs some library classes in the namespace MyApp_ . So in application.ini I put autoloaderNamespaces[] = "MyApp_". This is pure application configuration, no-one except a programmer would change these. On the other hand I put there a database configuration, something that a SysAdmin would change.
My idea is that I would split options between an application.ini and an user.ini, where the options in user.ini take preference (so I can define standard values in application.ini).
Is this a good idea? How can I best implement this? The idea's I have are
Extending Zend_Application to take multiple config files
Making an init function in my Bootstrap loading the user.ini
Parsing the config files in my index.php and pass these to Zend_Application (sounds ugly)
What shall I do? I would like to have the 'cleanest' solution, which is prepared for the future (newer ZF versions, and other developers working on the same app)
I found a solution to this issue that may be new to framework version 1.10. When creating the Zend Application object, you can pass in 2 configuration file paths in the options array that get merged together:
$application = new Zend_Application(
APPLICATION_ENV,
array(
'config' => array(
APPLICATION_PATH . '/configs/application.ini',
APPLICATION_PATH . '/configs/user.ini'
),
)
);
you know this will merge as much inis as you want?
in application.ini
[production]
config[] = APPLICATION_PATH "/configs/dsn.ini"
config[] = APPLICATION_PATH "/configs/error.ini"
...
There is nothing wrong with that, I do something similar. I suggest using your second choice. I just have an _initConfig() method that takes care of loading the user config using Zend_Config_Ini. I wouldn't extend Zend_App, that seems a bit much.
Edit:
In response to your comment, you would simply do:
$this->bootstrap('config');
Thus, to ensure config is loaded before DB, you'd have something like:
protected function _initConfig()
{
$config = new Zend_Config_Ini('/path/to/user.ini');
return $config;
}
protected function _initDb()
{
$this->bootstrap('config');
$config = $this->getResource('Config');
/* ... */
}
There is no need to use Zend_Registry as anything returned by a Bootstrap _init method is accessible using getResource()
An configuration file can have the item 'config' which refers to another config file. Zend_Application will include this config file. The included config-file will have preference, and overwrite the keys already defined in the standard config-file.
Yesterday there was also started a thread on the Zend Framework mailing list
Examples
application.ini:
[production]
config = APPLICATION_PATH "/configs/config.ini"
resources.db.adapter = "Mysqli"
resources.db.host = "localhost"
config.ini:
[production]
resources.db.host = "mysql.server.com"
resources.db.username = "myuser"
public/index.php:
$application = new Zend_Application(
APPLICATION_ENV,
APPLICATION_PATH . '/configs/application.ini'
);
In a similar scenario, I saw that the application specific parameters can be provided programmatically when instantiating the application. This helped to place configuration related parameters within the config.ini
I did it actually this way:
inside the index.php to bootstap the application
$application = new Zend_Application(APPLICATION_ENV, array(
'resources' => array(
'FrontController' => array(
'controllerDirectory' => APPLICATION_PATH . '/main/controllers',
),
'layout' => array(
'layoutpath' => APPLICATION_PATH . "/layouts/scripts"
),
),
));
and then inside the bootstrap parse the config.ini inidependently
protected function _initConfigFile() {
try {
$configuration = new Zend_Config_Ini(
APPLICATION_PATH . '/config/app.ini',
APPLICATION_ENV );
$registry->configuration = $configuration;
} catch (Zend_Exception $zExp) {
echo "Could not read application ini file (app.ini). "
. " Please check that it exists and has the appropriate structure.\n";
echo("\n");
var_dump($zExp);
exit(1);
}
}
inside the bootstrap
You can ensure an _initConfig() bootstrap method is invoked before others by specifying in your other bootstrap methods (that require the config object) something like:
$this->bootstrap('config');
A more complete example (context of a Bootstrap class):
protected function _initConfig() {
$config = new Zend_Config_Ini('[filename]');
Zend_Registry::set('config',$config);
}
protected function _initSomething() {
$this->bootstrap('config');
$config = Zend_Registry::get('config');
// you can now do whatever you like with the $config object
}
Update:
As has now been mentioned in other answers, if the config is only required within the bootstrap, I would say to use the $this->getResource('Config') method. I use the registry so that config can be accessed easily in other parts of my application.