Setting Environment-specific database in CakePHP - database

I am using CakePHP and was trying to implement https://github.com/josegonzalez/cakephp-environments
Which seemed to be going fine except that I have no idea where to specify the env specific database info.
Does anyone know where to set these?

I personally haven't used the plugin, however from looking at the code and the docs, if you were using the suggested database configuration, then it seems that you would define the options as either environment variables, which can be done in various ways, for example
in your server configuration (Apache example)
in your cloud varibale settings (Heroku example)
manually using putenv(), $_ENV, $_SERVER
$name = 'MYSQL_DB_HOST';
$value = 'localhost';
putenv("$name=$value");
$_ENV[$name] = $value;
$_SERVER[$name] = $value;
...
or as CakePHP configuration values via the Environment::configure() calls, something like:
Environment::configure('development',
true,
array(
'MYSQL_DB_HOST' => 'localhost',
'MYSQL_USERNAME' => 'user',
// ...
),
// ...
);

Related

How do I disable caching completely in cakephp 3.x

What is the best practice to disable caching in local development enviroments?
You might use \Cake\Cache\Cache::disable() in your bootstrap.php. I'm unaware of this being cited as 'best practise', however.
For CakePHP 4 you can do the following
in src/Application.php
use Cake\Cache\Cache;
...
public function bootstrap(): void
{
parent::bootstrap();
if (Configure::read('debug')) {
Cache::disable();
}
to disable cache completely
Also you can selectively disable only database metadata cache replacing Cache::disable(); to
$connection = ConnectionManager::get('default');
$connection->cacheMetadata(false);
Instead of default you can select your configured datasources
Do not forget to use Cake\Datasource\ConnectionManager;
And then you just need to enable debugging either in app_local.php using 'debug' => filter_var(env('DEBUG', true), FILTER_VALIDATE_BOOLEAN) or in .env setting DEBUG=true (or APP_DEBUG, look carefully in your config) if you are using dotenv. So you will not have uncommitted changes in your local files.

How to access parameters passed to Component from AppControler in CakePHP 2.4

I have created a component called ApiComponent to handle opening an HttpSocket to another server to post information. It looks like this:
class ApiComponent extends Component {
public function connect($endpoint,$data) {
App::uses('HttpSocket', 'Network/Http');
$HttpSocket = new HttpSocket();
// rest of the code
}
}
This works in the sense that I can call $this->Api->connect('/posts/add.json',$data); from my controller and the code is executed as expected.
However, I have a lot of settings in the $HttpSocket->request such as the hostname, port number, username, password etc etc that I'd like to take out of the Component and put in a config file.
According to http://book.cakephp.org/2.0/en/controllers/components.html#including-your-component-in-your-controllers I can pass parameters to the Component from the AppController like this:
public $components = array(
'Api' => array(
'host' => 'localhost',
'port' => '80'
),
'Session', 'Auth'
);
The manual says that this would pass the array to ApiComponent::__construct() but it doesn't say how I'm supposed to access the data in the component (or, it may... I'm in unfamiliar territory here).
So, my questions are:
1) Is it appropriate to put things like host, username, password etc in the AppController like this? And...
2) ...if so, how do I access them from within the Component?
...or...
3) ...if not, where exactly should I place settings like this?
In your ApiComponent your settings are stored in:
$this->settings
see API
I don't fully agree with #Lionel Chan: I don't think it's such a bad idea to store that values in the Component settings. But also using Configure class is a good practice.
No, it's not appropriate (so it's unclear). Controllers are for system/business logic, not for configurations.
(and 3.) You can probably use the following methods to store configurations:
Good, old constant way:
It's easy, just define(key, value) these credentials in your bootstrap.php and you should be fine, and it's globally accessible.
Use Configure class
Configure is pretty handy as it's global to CakePHP. You simply do Configure::write() to write the credentials in your bootstrap.php file. Yes it will have some minor overheads if you don't mind, but should not be noticeable.

Share configuration file at CakePHP between Config files (routles.php, mail.php...)

I have a site running in localhost as a development environment and in a server for production.
There are some differences in some configuration files between both and I every time I have to update the changes in the server I have to be careful not to overwrite some files which are different.
I would like to be able to simplify this process by creating just one single file with the correct configuration for each environment.
I need to read that file currently in this Config files:
app/Config/email.php
app/Config/routes.php
And ideally, if possible in:
app/Vendor/Vendor_name/vendor_file.php
Is it possible somehow?
I have tried to use Configure::read and Configure::write but it seems it can not be done inside email settings such as public $smtp or in the routes file.
Thaks.
The routes file is simply a php file with calls to the router. You could very simply split it up into multiple files and load them yourself:
app/Config/
routes.php
routes_dev.php
routes_production.php
routes.php would then load the proper routes file.
<?php
if ($env == 'dev') {
include 'routes_dev.php';
} else {
include 'routes_production.php';
}
The email config is also just a php file. You could write a function to set the proper default config based on the environment.
class EmailConfig {
public function __construct() {
if ($env == 'dev') {
$this->default = $this->dev;
}
}
public $default = array(
'host' => 'mail.example.com',
'transport' => 'Smtp'
);
public $dev = array(
'host' => 'mail2.example.com',
'transport' => 'Smtp'
);
}
As for vendor files, that's a case by case basis.
If you have a deployment system, it might be better to actually have separate files for each environment (maybe even a full config directory) and rename them after the deployment build is complete, making Cake and your code none the wiser.
The way I used to handle this situation was to add environment variables to the apache virtualhost configuration.
SetEnv cake_apps_path /var/www/apps/
SetEnv cake_libs_path /var/www/libs/
This allowed me to then pull $_SERVER['cake_apps_path'] and $_SERVER['cake_libs_path']. Then each developer can set his own variables in his own virtualhost config, and you add that to the server's virtualhost config, and you're done. Each developer can have their own pathing.

Codeigniter PDO integration

i did lot of research on the web but i didnt find anything that could help me to use PDO in codeigniter. I saw in the change lof of CI 2.1.0(i think) that pdo driver was added to the framwork.
I ended up now with a database.php config file that looks like this:
$db['default']['hostname'] = 'mysql:host=myhostname;port=myport';
$db['default']['username'] = 'myusername';
$db['default']['password'] = 'mypassword';
$db['default']['database'] = 'mydb';
$db['default']['dbdriver'] = 'pdo';
So now(after a lot of wasted time to get the snippet above to work -.- ) i receive no error about connection, but HOW TO EXECUTE QUERY NOW? i cant figure out what syntax will work and how to build queries. Anyone have hints?
PS: if you're wordering about why i need pdo in ci, the answer is my boss want me to create a structured enviroment with:
CI 2.x + (done)
Smarty 3 (done)
PhpUnit (not yet)
PDO (not yet)
so if you have also any hints for integrate phpunit feels free to answer. Ty in advance
You use PDO the same way you use any other database driver in CodeIgniter. If you are still unsure then I would recommend reading the documentation on the Database Class.
You can issue standard queries by explicitly writing the query or you can use the Active Record Class (which is more of a query builder).
Here are some examples:
// Standard query
$results = $this->db->query('SELECT name, title, email FROM my_table');
// Active record
$this->db->select('name, title, email');
$results = $this->db->get('my_table');
As for integrating PHPUnit, have a look at https://github.com/cmillr/CI-PHPUnit (I haven't tested it myself) or look around the CodeIgniter forums. I've seen a ton of topics on integrating PHPUnit with CodeIgniter.
You need to change your config a little:
'dsn' => 'mysql:host=localhost;dbname=codeigniter',
//'hostname' => 'localhost',
'username' => 'codeigniter',
'password' => 'codeigniter',
'database' => 'codeigniter',
Notice we use dsn, not hostname.
After that, simply use your $this->db-> like you always do - the PDO driver will translate everything to PDO methods
A little dated, but the topic is lacking clear explanations & docs so I wrote this - hope it helps clarify for people:
http://codebyjeff.com/blog/2013/03/codeigniter-with-pdo

Paged ldap_search in OpenLDAP to get around size limit?

We are currently in the process of migrating from an aged proprietary directory service to OpenLDAP.
Today we ran into the problem that ldap_search_ext_s or ldapsearch in general does not return any results, if the number of entries, which were to be returned by the current search, would hit a certain limit.
Unfortunately setting the size limit higher in the LDAP server configuration might just postpone the problem, as we have a really big database and our update mechanism, which runs every morning, has to performe huge queries.
In the MSDN documentation I noticed that there is a mechanism to perform a paged search, which would allow me to get around the size limitation.
Apparently this is also specified in an RFC draft from 1996 but hasn't been finalized (yet)?
Anyway, since I'm not working on a Windows-Box I have to use the OpenLDAP API, which doesn't seem to provide that mechanism (at least I couldn't find it on their search page)
Which brings me to my question: Do you have an idea what I could do, to solve that problem in an elegant manner?
Thanks for your help!
OpenLDAP supports paged result retrieval via ldap_create_page_control () and friends. Here is a description and sample code. If that doesn't help I may be able to provide excerpts from production code.
I had an issue using ldap_create_page_control with ldap_search_ext_s, my ldap library implementation was using LDAP version 2 by default and it looks it's supported for version 3+. It was returning "Not supported" from ldap_search_ext_s() before I set LDAP to version 3.
I was able to get around the size limitation using ldap_control_paged_result
ldap_control_paged_result is used to Enable LDAP pagination by sending the pagination control. The below function worked perfectly in my case.
function retrieves_users($conn)
{
$dn = 'ou=,dc=,dc=';
$filter = "(&(objectClass=user)(objectCategory=person)(sn=*))";
$justthese = array();
// enable pagination with a page size of 100.
$pageSize = 100;
$cookie = '';
do {
ldap_control_paged_result($conn, $pageSize, true, $cookie);
$result = ldap_search($conn, $dn, $filter, $justthese);
$entries = ldap_get_entries($conn, $result);
if(!empty($entries)){
for ($i = 0; $i < $entries["count"]; $i++) {
$data['usersLdap'][] = array(
'name' => $entries[$i]["cn"][0],
'username' => $entries[$i]["userprincipalname"][0]
);
}
}
ldap_control_paged_result_response($conn, $result, $cookie);
} while($cookie !== null && $cookie != '');
return $data;
}
Use AD or Novell's eDirectory? ;)

Resources