Doctrine 2, creating EntityManager from PDO - error - php

I have the following scenario:
class ModelManager extends EntityManager implements ModelManagerInterface
{
public function __construct($conn, $options = array())
{
$isDev = empty($options['is_dev']) ? false : $options['is_dev'];
// #see Doctrine\ORM\EntityManager#create()
$config = ArrayUtils::arrayMergeRecursiveRight($options, array(
'cache' => $isDev ? new Cache\ArrayCache : new Cache\ApcCache,
'queryCache' => $isDev ? new Cache\ArrayCache : new Cache\ApcCache,
'modelsProxiesPath' => getcwd() . '/cache/ModelProxies',
));
// create Configuration object
if (is_array($options)) {
$config = $this->initConfig($options);
if (!$config->getMetadataDriverImpl()) {
throw ORMException::missingMappingDriverImpl();
}
}
// test EventManager object
$eventManager = empty($options['eventManager']) ? new EventManager() : $options['eventManager'];
switch (true) {
case ($conn instanceof \PDO):
$conn = array(
'driver' => 'pdo_' . $conn->getAttribute(\PDO::ATTR_DRIVER_NAME),
'pdo' => $conn,
);
print_r($conn);
$conn = \Doctrine\DBAL\DriverManager::getConnection($conn, $config, $eventManager);
break;
case (is_string($conn)):
$pdo = new \PDO($conn);
if ('oci8' !== $pdo->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
$conn = array(
'driver' => 'pdo_' . $pdo->getAttribute(\PDO::ATTR_DRIVER_NAME),
'pdo' => $pdo,
);
} else {
$conn = $this->mapDsnToDoctrine($conn);
}
$conn = \Doctrine\DBAL\DriverManager::getConnection($conn, $config, $eventManager);
break;
case (is_array($conn)):
$conn = \Doctrine\DBAL\DriverManager::getConnection($conn, $config, $eventManager);
break;
case ($conn instanceof Connection):
if ($eventManager !== null && $conn->getEventManager() !== null) {
throw ORMException::mismatchedEventManager();
}
break;
default:
throw new Exception\InvalidArgument("Invalid argument: " . json_encode($conn));
}
// parent constructor
// #see Doctrine\ORM\EntityManager#__construct()
parent::__construct($conn, $config, $conn->getEventManager());
}
// ...
}
This is used smth like this:
self::$em = new ModelManager(
new \PDO(self::$config['db_adapter']['connection']['dsn']),
empty(self::$config['db_adapter']['options']['doctrine']) ?
array() : self::$config['db_adapter']['options']['doctrine']
);
$tool = new \Doctrine\ORM\Tools\SchemaTool(self::$em);
$classes = $this->db(self::$config['db_adapter']['options']['doctrine']['modelsPath']);
$tool->updateSchema($classes);
Where the config looks like this:
$config = array(
'db_adapter' => array(
'connection' => array(
'dsn' => 'mysql://root:******#localhost/netistest' . time(),
),
'options' => array(
'doctrine' => array(
'cache' => 'ArrayCache|ApcCache', // development|testing&production
'queryCache' => 'ArrayCache|ApcCache', // development|testing&production
'modelsPath' => __DIR__ . '/NetisTest/Model',
'modelsProxiesPath' => __DIR__ . '/cache/doctrine/ModelProxies',
'modelsProxiesNamespace' => 'App\Models\Proxies',
'modelsProxiesAutogenerate' => 'App\Models\Proxies',
),
'zend' => array(
// at this moment we decided not to implement Zend\DbAdapter
),
)
),
);
The problem with all this strange configuration, is that, after instantiating the ModelManager class, when trying to interrogate the database for creating the tables associated to my models, it throws the following error:
Doctrine\DBAL\DBALException: An exception occurred while executing 'SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'':
SQLSTATE[3D000]: Invalid catalog name: 1046 No database selected
/home/dragosc/workspace/athem-repositories/Component_NetisDb/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php:91
/home/dragosc/workspace/athem-repositories/Component_NetisDb/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:699
/home/dragosc/workspace/athem-repositories/Component_NetisDb/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:630
/home/dragosc/workspace/athem-repositories/Component_NetisDb/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php:206
/home/dragosc/workspace/athem-repositories/Component_NetisDb/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php:250
/home/dragosc/workspace/athem-repositories/Component_NetisDb/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php:986
/home/dragosc/workspace/athem-repositories/Component_NetisDb/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaTool.php:855
/home/dragosc/workspace/athem-repositories/Component_NetisDb/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaTool.php:832
/home/dragosc/workspace/athem-repositories/Component_NetisDb/tests/NetisTest/Db/Setup/Doctrine.php:51
You can find the code (however in an older form) here as well:
https://github.com/athemcms/Component_NetisDb/blob/master/library/Netis/Db/ModelManager/ModelManager.php
Can anyone please help me in understanding why PDO isn't enough for EntityManager to remember the database as well ?
Thanks a lot in advance!

Related

MongoDB PHP Error: Warning: Undefined property: MongoDB\Driver\Manager

I'm trying to use MongoDB on my local machine using the advice in this stack overflow. I'm using XAMPP on Windows 10, php version 8.01, and MongoDB extension 1.9.0.
It's a very basic script that connects to MongoDB and tries to use one of the databases.
But I am still getting this warning:
Connection to database successfully
Warning: Undefined property: MongoDB\Driver\Manager::$aws_inventories in C:\xampp\htdocs\mongo_connect.php on line 8
This is my code:
<?php
require 'C:\xampp\htdocs\vendor\autoload.php'; // include Composer's autoloader
$DB_CONNECTION_STRING="mongodb://localhost:27017";
// connect to mongodb
$m = new MongoDB\Driver\Manager( $DB_CONNECTION_STRING );
echo "Connection to database successfully";
// select a database
$db = $m->aws_inventories;
?>
How can I get rid of the warning and connect to the DB correctly?
First, you're trying to access a property which doesn't exists in MongoDB\Driver\Manager class object.
Second, $db = $m->aws_inventories; works with MongoDB\Client library.
Here are few example to get collections list or find all/specific document/s or insert/bulk insert, update a document or to perform a distinct query
Get all collections of aws_inventories:
try {
$manager = new MongoDB\Driver\Manager('mongodb://localhost:27017');
$command = new MongoDB\Driver\Command(["listCollections" => 1]);
$cursor = $manager->executeCommand("aws_inventories", $command);
// list of all collections in aws_inventories
$collections = $cursor->toArray();
var_dump($collections);
} catch (\MongoDB\Driver\Exception\Exception $e) {
}
Get all documents from a collection:
try {
$manager = new MongoDB\Driver\Manager('mongodb://localhost:27017');
// setting options and filter
$filter = [];
$options = [];
/*
// or to find specific documents based on a condition and limit records
$filter = [
'service' => 'ec2',
'instance' => 'co',
'type' => 'c5',
'vCPU' => [
'$gt' => 2
]
];
$options = [
'limit' => 10,
'maxTimeMS' => 1000, // to limit the execution time of a query
'sort' => [
'vCPU' => -1
]
];
*/
// constructing the query
$query = new MongoDB\Driver\Query($filter, $options);
$cursor = $manager->executeQuery('aws_inventories.test', $query);
foreach ($cursor as $document) {
var_dump($document);
}
} catch (\MongoDB\Driver\Exception\Exception $e) {
}
To perform distinct query:
try {
$manager = new MongoDB\Driver\Manager('mongodb://localhost:27017');
$query = [
'size' => '2xlarge'
];
$command = new MongoDB\Driver\Command([
'distinct' => 'test', // Collection name
'key' => 'instance', // field for which we want to get distinct values
'query' => $query // criteria to filter documents
]);
$cursor = $manager->executeCommand("aws_inventories", $command);
// to get distinct values as array
$instances = current($cursor->toArray())->values;
var_dump($instances);
} catch (\MongoDB\Driver\Exception\Exception $e) {
}
To insert single/multiple document/s:
try {
$manager = new MongoDB\Driver\Manager('mongodb://localhost:27017');
$bulk = new MongoDB\Driver\BulkWrite;
$bulk->insert([
'service' => 'ec2',
'instance' => 'co',
'type' => 'c5',
'size' => 'large',
'model' => 'c5.large',
'vCPU' => 2,
'memory' => 4,
'storage' => 'ebs-only',
'network_bandwidth' => 10,
'ebs_bandwidth' => 4750
]);
$bulk->insert([
'service' => 'ec2',
'instance' => 'gp',
'type' => 't3',
'size' => 'nano',
'model' => 't3.nano',
'vCPU' => 2,
'memory' => 0.5,
'storage' => 'ebs-only',
'network_bandwidth' => 5
]);
$result = $manager->executeBulkWrite('aws_inventories.test', $bulk);
} catch (\MongoDB\Driver\Exception\Exception $e) {
}
To update existing document/s: (Taken from executeUpdate example)
try {
$manager = new MongoDB\Driver\Manager('mongodb://localhost:27017');
$criteria = [
'service' => 'ec2',
'type' => 'c5'
];
$document = [
'$set' => [
'features' => [
'Powered by the AWS Nitro System, a combination of dedicated hardware and lightweight hypervisor'
]
]
];
$updateOptions = array(
'multi' => true, // false - to update only first matching document, true - update all matching documents
'upsert' => 0
);
$writeConcern = new MongoDB\Driver\WriteConcern(MongoDB\Driver\WriteConcern::MAJORITY, 100);
$result = $manager->executeUpdate('aws_inventories.test', $criteria, $document, $updateOptions, $writeConcern);
printf("Updated %d document(s)\n", $result->getModifiedCount());
printf("Matched %d document(s)\n", $result->getMatchedCount());
printf("Upserted documents: %d\n", $result->getUpsertedCount());
foreach ($result->getUpsertedIds() as $index => $id) {
printf("upsertedId[%d]: ", $index);
var_dump($id);
}
/* If the WriteConcern could not be fulfilled */
if ($writeConcernError = $result->getWriteConcernError()) {
printf("%s (%d): %s\n", $error->getMessage(), $error->getCode(), var_export($error->getInfo(), true));
}
/* If the write could not happen at all */
foreach ($result->getWriteErrors() as $writeError) {
printf("%s (%d)\n", $error->getMessage(), $error->getCode());
}
} catch (\MongoDB\Driver\Exception\Exception $e) {
}
$m->aws_inventories That looks like as the older/deprecated approach. Could you try to follow this tutorial?
https://zetcode.com/db/mongodbphp/
<?php
try {
$mng = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$stats = new MongoDB\Driver\Command(["dbstats" => 1]);
$res = $mng->executeCommand("aws_inventories", $stats);
$stats = current($res->toArray());
print_r($stats);
} catch (MongoDB\Driver\Exception\Exception $e) {
$filename = basename(__FILE__);
echo "The $filename script has experienced an error.\n";
echo "It failed with the following exception:\n";
echo "Exception:", $e->getMessage(), "\n";
echo "In file:", $e->getFile(), "\n";
echo "On line:", $e->getLine(), "\n";
}
?>
This example is adapted from the official doc https://www.php.net/manual/en/mongodb-driver-manager.executequery.php
<?php
require 'vendor/autoload.php';
$manager = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$db = 'test_database';
$col = 'mycol';
$namespace = $db.'.'.$col;
// insert data
$bulk = new MongoDB\Driver\BulkWrite;
$bulk->insert(['x' => 1]);
$bulk->insert(['x' => 2]);
$bulk->insert(['x' => 3]);
$manager->executeBulkWrite($namespace, $bulk);
// query
$query = new MongoDB\Driver\Query(['x' => ['$gt' => 1]], []);
$cursor = $manager->executeQuery($namespace, $query);
foreach ($cursor as $document) {
var_dump($document);
}
As the document suggests, MongoDB\Driver\Manager is a generic abstraction to manage any type of MongoDB connection (standalone server, replica set, or sharded cluster) so the methods will look a bit too complicated for simple CRUD on standalone server.
If you just want to connect to a standalone server, you may want to check MongoDB\Client. Here is the code that do exactly the same thing:
<?php
require 'vendor/autoload.php';
$client = new MongoDB\Client("mongodb://localhost:27017");
$col = $client->test_database->mycol;
// insert data
$col->insertMany([
['x' => 1],
['x' => 2],
['x' => 3],
]);
// query
$docs = $col->find(['x' => ['$gt' => 1]]);
foreach ($docs as $document) {
var_dump($document);
}

Databe connection error on start

I am having problems with a connection to the database, specifically, when I try to access the system and the database does not respond.
I am getting an error in my services.php file.
And this is the code:
try{
$di->set('db', function () use ($config) {
$config = $config->get('database')->toArray();
$dbClass = 'Phalcon\Db\Adapter\Pdo\\' . $config['adapter'];
if (stripos($config['adapter'], 'Mysql')!== false) {
$mi_conf = array(
"host" => $config['host'],
"username" => $config['username'],
"password" => $config['password'],
"dbname" => $config['dbname'],
"options" => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
)
);
} else {
$mi_conf = array(
"dbname" => '//'.$config['host'].'/'.$config['dbname'],
"username" => $config['username'],
"password" => $config['password'],
'charset' => 'utf8'
);
}
unset($config['adapter']);
return new $dbClass($mi_conf);
});
} catch (Exception $e) {
$error .= 'db, ';
return null;
}
I do not know if it will be necessary to change there or I have to make changes to each call from each model.
Any advice?
Thank you.
The code looks without errors.
Use setShared to avoid connecting to the database multiple times, or use the "persistent" attribute on the configuration to take effect. Maybe it does the trick. By the way, change the try catch to the moment where the service was created, so you can catch the exception.
$di->setShared('db', function () use ($config) {
try {
$config = $config->get('database')->toArray();
$dbClass = 'Phalcon\Db\Adapter\Pdo\\' . $config['adapter'];
if (stripos($config['adapter'], 'Mysql') !== false) {
$mi_conf = array(
"host" => $config['host'],
"username" => $config['username'],
"password" => $config['password'],
"dbname" => $config['dbname'],
"persistent" => false,
"options" => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
),
);
} else {
$mi_conf = array(
"dbname" => '//' . $config['host'] . '/' . $config['dbname'],
"username" => $config['username'],
"password" => $config['password'],
"persistent" => false,
'charset' => 'utf8',
);
}
unset($config['adapter']);
return new $dbClass($mi_conf);
} catch (Exception $e) {
$error .= 'db, ';
return null;
}
});

Alias "components.HybridAuthIdentity" is invalid

I am following this tutorial http://www.yiiframework.com/wiki/459/integrating-hybridauth-directly-into-yii-without-an-extension/
into my own application but I get an error and I spend many hours to find wich step that I miss.
Here is my error.
Alias "components.HybridAuthIdentity" is invalid. Make sure it points to an existing directory or file.
In components directory, I create a file named HybridAuthIdentity.php
class HybridAuthIdentity extends CUserIdentity{`
public $hybridAuth;
public $adapter;
public $userProfile;
public $allowedProviders = array('google', 'facebook', 'linkedin', 'yahoo', 'live',);
protected $config;
function __construct()
{
$path = Yii::getPathOfAlias('ext.hybridauth');
require_once $path . '/hybridauth/Hybrid/Auth.php';
$this->config = array(
"base_url" => "touchtalent.dev/login/SocialLogin",
"providers" => array(
"LinkedIn" => array(
"enabled" => true,
"keys" => array (
"key" => "My key",
"secret" => "my secret id",
),
),
),
"debug_mode" => false,
"debug_file" => "",
);
$this->hybridAuth = new Hybrid_Auth($this->config);
}
}
In my siteController, I write :
Yii::import('components.HybridAuthIdentity');
$haComp = new HybridAuthIdentity;
if(!$haComp->validateProviderName($_GET['provider']))
{
throw new CHttpException("500", "Invalid action. Please Try again");
}
else
{
$haComp->adaptor = $haComp->hibrydAuth->authenticate($_GET['provider']);
$haComp->userProfile = $haComp->adaptor->getUserProfile();
$haComp->login();
$this->redirect('create');
}
How I can fix it? Thanks for all resposes...

Couldn't extend session timeout in ZF2

I'm saving my session data on my database(mongodb), the customer asked that he want the system to be idle for 2 hours(he has videos on the site which may take 2 hours to finish, so he asked to set session timeout value as 2 hour). I did it as Zend Framework suggested. see my config.php below
return array(
'env2_session' => array(
'config' => array(
'class' => 'Zend\Session\Config\SessionConfig',
'options' => array(
'name' => 'test',
'remember_me_seconds' => 7200,
'gc_maxlifetime' => 7200,
),
),
'mongo_handler' => array(
'options' => array(
'class' => 'Zend\Session\SaveHandler\MongoDBOptions',
'collection' => 'sessions',
),
),
'save_handler' => 'Env2Session/Mongo/Handler',
'validators' => array(
array(
'Zend\Session\Validator\RemoteAddr',
'Zend\Session\Validator\HttpUserAgent',
),
),
),
);
But this is not the correct code as I couldn't see the session extended. it still get timed out after 24 minutes.
It will work if I add 'cookie_lifetime' => 7200 after 'gc_maxlifetime' => 7200 But this get timedout even if I'm using the site.
I want the timeout only when the system is idle. Please get me some thing on this.
Here is the save handler code which I written in Module.php
public function getServiceConfig()
{
return array(
'factories' => array(
'Env2Session/Mongo/Handler' => function ($sm) {
$config = $sm->get('config');
$session = $config['env2_session'];
$mongo = $sm->get('Env2\Mongo');
$class = isset($session['mongo_handler']['options']['class']) ? $session['mongo_handler']['options']['class'] : 'Zend\Session\SaveHandler\MongoDBOptions';
$options = array();
$options['collection'] = $session['mongo_handler']['options']['collection'];
$options['database'] = $config['db']['mongo']['db_name'];
$mongoOption = new $class($options);
$sessionSaveHandler = new MongoDB($mongo, $mongoOption);
return $sessionSaveHandler;
},
'Env2Session' => function ($sm) {
$config = $sm->get('config');
if (isset($config['env2_session'])) {
$session = $config['env2_session'];
$sessionConfig = null;
if (isset($session['config'])) {
$class = isset($session['config']['class']) ? $session['config']['class'] : 'Zend\Session\Config\SessionConfig';
$options = isset($session['config']['options']) ? $session['config']['options'] : array();
$sessionConfig = new $class();
$sessionConfig->setOptions($options);
}
$sessionStorage = null;
if (isset($session['storage'])) {
$class = $session['storage'];
$sessionStorage = new $class();
}
$sessionSaveHandler = null;
if (isset($session['save_handler'])) {
$sessionSaveHandler = $sm->get($session['save_handler']);
}
$sessionManager = new SessionManager($sessionConfig, $sessionStorage, $sessionSaveHandler);
if (isset($session['validator'])) {
$chain = $sessionManager->getValidatorChain();
foreach ($session['validator'] as $validator) {
$validator = new $validator();
$chain->attach('session.validate', array($validator, 'isValid'));
}
}
} else {
$sessionManager = new SessionManager();
}
Container::setDefaultManager($sessionManager);
return $sessionManager;
}
),
);
}
I was struggling with the same issue for zend session timeouts. Finally I implemented own solution for this case. I set up the expiration time which is refreshed during each request. But if user is not active, the time will expire and session will be destroyed.
I put all tutorial how to do it here: http://blog.tulikowski.com/zend-framework-2-implementation-of-session-authentication-timeouts/
Go to your autoload/global.php and either create or edit this key:
'session_config' => array
(
'cache_expire' => 60*60*2,
'name' => 'sessionName',
'cookie_lifetime' => 60*60*2,
'gc_maxlifetime' => 60*60*2,
'cookie_path' => '/',
'cookie_secure' => FALSE,
'remember_me_seconds' => 60*60*2,
'use_cookies' => true,
),

Twig "Unable to add function"

I'm using twig, and i'm attempting to add a function.
$Func = new \Twig_SimpleFunction('placeholder', function ($title) {
$this->module->CurrentPage->addPlaceholder($title);
});
\App::make('twig')->addFunction($Func);
I will get the following exception
Unable to add function "placeholder" as extensions have already been initialized.
I've checked twice that the "addFunction" is executed before the twig "loadTemplate". So, it does not seem to be the problem.
Does anyone have a hint, or an idea about this? Or what its all about.
Thanks in advance.
You need to add twig functions right after you created Twig_Environment instance. For example, the following WILL NOT work:
$loader = new Twig_Loader_Filesystem($this->resourceRoot . '/views');
$twig = new Twig_Environment($loader, array(
'cache' => storage_path('twig'),
'debug' => Config::get('app.debug'),
'strict_variables' => true,
));
$lexer = new Twig_Lexer($twig, array(
'tag_comment' => array('{#', '#}'),
'tag_block' => array('{%', '%}'),
'tag_variable' => array('{^', '^}'),
'interpolation' => array('#{', '}'),
));
$twig->setLexer($lexer);
$function = new Twig_SimpleFunction('widget', function ($widget, array $params) {
WidgetFactory::renderWidget($widget, $params);
});
$twig->addFunction($function);
Because Lexer is initialized before functions are added. You need to make it like this:
$loader = new Twig_Loader_Filesystem($this->resourceRoot . '/views');
$twig = new Twig_Environment($loader, array(
'cache' => storage_path('twig'),
'debug' => Config::get('app.debug'),
'strict_variables' => true,
));
$function = new Twig_SimpleFunction('widget', function ($widget, array $params) {
WidgetFactory::renderWidget($widget, $params);
});
$twig->addFunction($function);
$lexer = new Twig_Lexer($twig, array(
'tag_comment' => array('{#', '#}'),
'tag_block' => array('{%', '%}'),
'tag_variable' => array('{^', '^}'),
'interpolation' => array('#{', '}'),
));
$twig->setLexer($lexer);

Categories