I'm writing a WordPress plug-in and need to read the database name, username, and password (In order to do a sql dump). Is this possible?
Thanks-
Yes, they are defined in wp-config.php
Database Name: DB_NAME
Database User: DB_USER
Database password: DB_PASSWORD
Database Host: DB_HOST
They are define. See you wp-config.php in the root directory of Wordpress
Wordpress has some fairly goofy stuff going on throughout its OO code, this isn't the first one I've encountered as we dig deeper into the internals with each successive project at Moxune. See WP_User::__set doesn't persist custom fields as it claims.
The goofiness I refer to here of course is that something like the table prefix, aka wpdb::prefix is a public member variable, however things like dbname, dbpassword, and dbhost are protected and there are no public accessor methods.
I'm sure one of the Wordpress core devs will try to argue some rationale for it, but in the meantime may as well use some good 'ol OO to cope. My suggestion, a decorator.
class SaneDb
{
private $_oDb;
public function __construct(wpdb $oDb)
{
$this->_oDb = $oDb;
}
public function __get($sField)
{
if($sField != '_oDb')
return $this->_oDb->$sField;
}
public function __set($sField, $mValue)
{
if($sField != '_oDb')
$this->_oDb->$sField = $mValue;
}
public function __call($sMethod, array $aArgs)
{
return call_user_func_array(array($this->_oDb, $sMethod), $aArgs);
}
public function getDbName() { return $this->_oDb->dbname; }
public function getDbPass() { return $this->_oDb->dbpassword; }
public function getDbHost() { return $this->_oDb->dbhost; }
}
Then atop your plugin code (functions.php) setup a global in similar vein to wpdb.
global $sanedb;
$sanedb = new SaneDb($wpdb);
From there, just use $sanedb within your plugin instead of $wpdb.
Lastly, getting ahold of the database name et al.
$sanedb->getDbName();
This is super simple now. You can create a PHP file and use the following code.
$path = $_SERVER['DOCUMENT_ROOT'];
include_once $path . '/wp-config.php';
include_once $path . '/wp-load.php';
include_once $path . '/wp-includes/wp-db.php';
include_once $path . '/wp-includes/pluggable.php';
// We need the WordPress Database Credentials
global $wpdb;
$user = $wpdb->dbuser;
$pass = $wpdb->dbpassword;
$name = $wpdb->dbname;
If you need other data just do a print_r on the wpdb variable and you'll see everything inside of there.
Related
I read some other posts here on stackoverflow about passing parms to a class library (for example, How to pass multiple parameters to a library in CodeIgniter?) and I also read the user manual under the libraries section.
What I'm wondering is if it's possible to pass parameters as individual variables and not as an array?
My class - which I want to use outside of my codeigniter solution- look like this:
<?php
class ABC
{
private $_hostname;
private $_password;
private $_username;
private $_connection;
private $_data;
private $_timeout;
private $_prompt;
public function __construct($hostname, $password, $username = "", $timeout = 10)
{
set_include_path(get_include_path() . PATH_SEPARATOR . '/var/www/phpseclib');
include('Net/SSH2.php');
$this->_hostname = $hostname;
$this->_password = $password;
$this->_username = $username;
} // __construct
public function connect()
{
}
public function dosomething()
{
}
I know I can do something like :
$params = array('_hostname' => $ip, '_password' => 'password', '_username' => '');
$this->load->library($classname,$params );
But I do not want to use arrays because this class will be reused by non CI solutions.
I've tried reverting to using a standard include() statement. So the code looks like:
set_include_path(get_include_path() . PATH_SEPARATOR . 'var/www/myCIapp/application/libraries');
include_once('libraries/'.$classname.'.php');
But it's complaining saying that it cannot find the include file. The specific message is:
A PHP Error was encountered
Severity: Warning
Message: include_once() [function.include]: Failed opening
'libraries/HP5406_ssh.php' for inclusion
(include_path='.:/usr/share/php:/usr/share/pear:var/www/myCIapp/application/libraries/')
Filename: models/ss_model.php
Line Number: 88
Any suggestions would be appreciated. Thanks for reading...
A simple way of doing your include could be dome using the CI APPPATH CONSTANT:
include_once(APPPATH.'libraries/'.$classname.'.php';
This CONSTANT is set in the index.php by CodeIgniter so you know it'll always be pointing to your Application directory.
the solution to the include not working is to change the include statement to look like:
include_once dirname(__FILE__) . '/../libraries/'.$classname.'.php';
I was assuming that it would automatically start with the location of the current file. But that's not true.
The above line will force it to start from the location of the current file.
I am writing a MVC Framework (for the purpose of learning and discovery as opposed to actually intending to use it) and I have came across a slight problem.
I have a config.php file:
$route['default'] = 'home';
$db['host'] = 'localhost';
$db['name'] = 'db-name';
$db['user'] = 'user-name';
$db['pass'] = 'user-pass';
$enc_key = 'enc_key'
I load these via a static method in my boot class:
public static function getConfig($type) {
/**
* static getConfig method gets configuration data from the config file
*
* #param string $type - variable to return from the config file.
* #return string|bool|array - the specified element from the config file, or FALSE on failure
*/
if (require_once \BASE . 'config.php') {
if (isset(${$type})) {
return ${$type};
} else {
throw new \Exception("Variable '{$type}' is undefined in " . \BASE . "config.php");
return FALSE;
}
} else {
throw new \Exception("Can not load config file at: " . \BASE . 'config.php');
return FALSE;
}
}
and then load the route like so:
public function routeURI($uri) {
...
$route = $this::getConfig('route');
...
}
which catches the exception:
"Variable 'route' is undefined in skeleton/config.php"
now, it works fine if I make the config.php file like so
$config['route']['default'] = 'home'
...
and change the two lines in the method like so:
if (isset($config[$type])) {
return $config[$type];
I have also tried using $$type instead of ${$type} with the same problem.
Is there something I am overlooking?
As written, this function can be called only once, because it uses require_once and on subsequent calls you won't bring in the local variables defined in config.php anymore. I suspect you are getting this error on your second call to getConfig().
As the title says there is a problem accessing variable (associative array) inside class from included file. Here is the source code both class and include file:
require("applications/cw_database.php");
require("config/dbConfig.php");
require("config/appConfig.php");
class APP_ASSESMENTS
{
private $dbObj;
private $DisplayOutput = "";
public function __construct($PageParams)
{
try
{
$dbObj = new CW_DB($dbConfig['hostname'],$dbConfig['username'],$dbConfig['password'],$dbConfig['name'],$dbConfig['port']);
} catch (Exception $e) {
throw new ErrorException($e);
}
}
...
The other part has nothing to do with $dbConfig.
Also this is the included file (config/dbConfig.php):
/*
Testing configuration for MySQL database
*/
$dbConfig['username'] = "phpcoursework"; // changed on demand
$dbConfig['password'] = "phpcoursework"; // changed on demand
$dbConfig['hostname'] = "localhost"; // changed on demand
$dbConfig['name'] = "students"; // changed on demand
$dbConfig['port'] = 3306; // default for MySQL
First, $dbObj will not automatically assume class member scope, it will create a local copy of CW_DB and discard it when __construct returns. You need to explicitly reference the property;
$this->dbObj = ...
Anyway, global state using global as suggested by others will "work", but if you're using OOP practices you're best not to do that. You can actually return from an include(), so an option would be to do the following:
// your config file dbConfig.php
return array(
'username' => "phpcoursework",
'password' => "phpcoursework",
'hostname' => "localhost",
'name' => "students",
'port' => 3306,
);
And inject it into the object, via constructor or method (here's constructor)
class APP_ASSESMENTS
{
private $dbObj;
public function __construct($dbConfig, $PageParams)
{
$dbObj = new CW_DB($dbConfig['hostname'], $dbConfig['username'],
$dbConfig['password'], $dbConfig['name'], $dbConfig['port']);
// ...
}
}
// include() here, will actually return the array from the config file
$appAssesments = new \APP_ASSESMENTS(include('dbConfig.php'), $PageParams);
It would be recommended that you go another level up: instead, inject the database object itself, taking the dependency out of your APP_ASSESSMENTS class.
(Also, PascalCase is the typical convention of class naming, such as AppAssessments and CwDb)
$dbObj = new CwDb(include('dbConfig.php'));
$appAssessments = new AppAssessments($dbObj, $etc, $etc);
This simple change allows you to remove the dependency from AppAssessments on CwDb. That way, if you extend CwDb for some reason, you can just pass in an instance of the extended class without having to change any code in AppAssessments
You can change the AppAssessments constructor like so:
public function __construct(CwDb $db, $etc, $etc){
$this->db = $db;
// ...
}
This takes advantage of PHPs (limited, albeit still useful) type-hinting, ensuring the first argument is always of the correct type.
This plays into part of the open/closed principle: classes should be open to extension but closed for modification.
Includes are used in the scope of access. So, to access the variables you need to include the files within your class. As earlier mentioned global will let you access variables from another scope too. But global should be used with caution! See the documentation.
See the manual for more information.
Edit: I need to make it clear that globals are never a good alternative for handling these kind of critical variables..
public function __construct($PageParams){
global $dbConfig;
try{
$dbObj = new CW_DB($dbConfig['hostname'],$dbConfig['username'],$dbConfig['password'],$dbConfig['name'],$dbC onfig['port']);
} catch (Exception $e) {
throw new ErrorException($e);
}
}
or you could use $GLOBALS['dbConfig'].
I need to get data, to check and send to db.
Programming with PHP OOP.
Could you tell me if my class structure is good and how dislpay all data?. Thanks
<?php
class Database{
private $DBhost = 'localhost';
private $DBuser = 'root';
private $DBpass = 'root';
private $DBname = 'blog';
public function connect(){
//Connect to mysql db
}
public function select($rows){
//select data from db
}
public function insert($rows){
//Insert data to db
}
public function delete($rows){
//Delete data from db
}
}
class CheckData{
public $number1;
public $number2;
public function __construct(){
$this->number1 = $_POST['number1'];
$this->number2 = $_POST['number2'];
}
function ISempty(){
if(!empty($this->$number1)){
echo "Not Empty";
$data = new Database();
$data->insert($this->$number1);
}
else{
echo "Empty1";
}
if(!empty($this->$number2)){
echo "Not Empty";
$data = new Database();
$data->insert($this->$number2);
}
else{
echo "Empty2";
}
}
}
class DisplayData{
//How print all data?
function DisplayNumber(){
$data = new Database();
$data->select();
}
}
$check = new CheckData();
$check->ISempty();
$display = new DisplayData()
$display->DisplayNumber();
?>
That's horrible piece of code.
For database communication use PDO. It's not perfect, but it's fine.
Every time you'll need database you'll connect with that db?
Database::insert() etc. would have to be a true magician to guess where its parameter should be inserted
You need a better IDE to show your undefined variables. I use PHPStorm.
You need some dependency injection. Use encapsulation. Just follow SOLID.
Second to last thing, don't echo from within objects. You can't unit test effectively your code that way.
You might also try some TDD.
You're going at things wrong here, I think. What you are constructing is a wrapper around already-existing database functions. Thing is, those functions already defined to do exactly what you want - the object oriented approach here serves no real purpose since it can only connect to one database and the methods are not really well defined and seem to act as pure pass-throughs to the underlying layer.
As others have mentioned, the code you seem to be going at here is not going to suit your purposes. Something like PDO will serve you well and its already built in to PHP. You don't need to re-invent the wheel for such common code as accessing a database.
Learning a few core Object Orientation principles will do you good too - look at encapsulation and code re-use first. They'll help in the future when you have to maintain that code you write!
Is it possible to define private variables in a PHP script so these variables are only visible in this single PHP script and nowhere else? I want to have an include file which does something without polluting the global namespace. It must work with PHP 5.2 so PHP namespaces are not an option. And no OOP is used here so I'm not searching for private class members. I'm searching for "somewhat-global" variables which are global in the current script but nowhere else.
In C I could do it with the static keyword but is there something similar in PHP?
Here is a short example of a "common.php" script:
$dir = dirname(__FILE__);
set_include_path($dir . PATH_SEPARATOR . get_include_path());
// Do more stuff with the $dir variable
When I include this file in some script then the $dir variable is visible in all other scripts as well and I don't want that. So how can I prevent this?
There are a few things you could do to keep $dir out of subsequent files
Example 1
set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path());
This is the most obvious.
Example 2
$dir = dirname(__FILE__);
set_include_path($dir . PATH_SEPARATOR . get_include_path());
// work with $dir
unset($dir);
Just unset the variable after defining it and using it. Note this will unset any variable named $dir used prior to including this script.
Example 3
define('DIR_THIS', dirname(__FILE__));
set_include_path(DIR_THIS . PATH_SEPARATOR . get_include_path());
It is less likely I suppose to redefine a global constant like this.
Example 4
function my_set_include_path {
$dir = dirname(__FILE__);
set_include_path($dir . PATH_SEPARATOR . get_include_path());
// Do more stuff with the $dir variable
$my_other_var = 'is trapped within this function';
}
my_set_include_path();
You can define as many variables within that function and not affect the global namespace.
Conclusion
The first method is the easiest way to solve this problem, however because you want to use $dir again, it may not be ideal. The last example will at least keep that $dir (and any others defined in that function) out of the global namespace.
The only way you're going to accomplish anything close to what you want is to wrap everything in that included file in a function, and call it. If the file needs to execute itself you could still do
<?php
run_myfile()
function run_myfile() {
...
}
?>
There is no generic way to make a variable scoped to only a file outside of namespaces, classes, or functions.
Well, I'm probably getting flailed for this, but you if you are totally desperate you could use a Registry for that. I've whipped up a small one that does without classes (since I assume from And no OOP is used here so I'm not searching for private class members. means you don't want to do it with OOP at all)
function ®istry_get_instance()
{
static $data = array();
return $data;
}
The static $data variable inside is persisted inside the function scope, so you can call the function wherever you like and always get the same contents. The crucial point is returning by reference, e.g.
$registry = ®istry_get_instance(); // get $data array by reference
$registry['foo'] = 'bar'; // set something to $data
unset($registry); // delete global reference to $data
print_r(®istry_get_instance()); // show $data
Obviously you'd still have $registry as a variable in the global scope when calling this method from the global scope. So, you could add some more functions to make the Registry more convenient to use, e.g. for setting data to the Registry:
function registry_set($key, $value)
{
$registry = ®istry_get_instance();
$registry[$key] = $value;
}
and for getting it out again:
function registry_get($key)
{
$registry = ®istry_get_instance();
if(array_key_exists($key, $registry)) {
return $registry[$key];
} else {
trigger_error(sprintf(
'Undefined Index: %s', htmlentities($key)
), E_USER_NOTICE);
}
}
and for checking if a key exists:
function registry_isset($key)
{
$registry = ®istry_get_instance();
return array_key_exists($key, $registry);
}
which you could then use like:
registry_set('foo', 'bar'); // setting something to the registry
var_dump( registry_isset('foo') ); // check foo is in the registry now
echo registry_get('foo'); // prints 'bar'
echo registry_get('punt'); // raises Notice
You could populate the Registry from an include file with an additional method like this:
function registry_load_file($file)
{
if(!is_readable(realpath($file))) {
return trigger_error(sprintf(
'File is not readable: %s', htmlentities($file)
), E_USER_WARNING);
}
$config = include $file;
if(!is_array($config)) {
return trigger_error(sprintf(
'Expected file %s to return an array', htmlentities($file))
, E_USER_WARNING);
}
$registry = ®istry_get_instance();
$registry += $config;
}
with the include file having to return an array:
// config.php
return array(
'setting1' => 'something'
);
and then you can do
registry_load_from_file('config.php'); // add the contents of config to registry
print_r(registry_get_instance()); // show content of registry
Of course, this is now six functions in the global scope just for not having a global variable. Don't know if it's worth it, especially since I consider static in functions and all that reference stuff doubtful practice.
Take it as a proof of concept :)
Why not just put everything in a static class? Then you only have a single "variable" that could possibly conflict with the global namespace.
class MyClass {
public static $myvar = 1;
public static $myvar2 = "xyz";
public static function myfunction() {
self::$myvar++;
self::$myvar2 = "abc";
}
}
// References to class items, if needed
MyClass::myfunction();
MyClass::$myvar += 3;
If the problem you are trying to is just:
$dir = dirname(__FILE__);
set_include_path($dir . PATH_SEPARATOR . get_include_path());
// Do more stuff with the $dir variable
Then the solution would be to change the include path relative to '.' in your ini settings. E.g. change:
include_path=includes:/usr/local/php
to
include_path=./includes:/usr/local/php
Note that a script does not come into scope except where you explicitly include/require it (both the _once check applies globally) however I would recommend strongly against calling include/require from within a function - its much more transparent having the includes/requires at the top of the script.
I think that the problem you are trying to solve is based on a false premise and you should look for another way of fixing it. If you want the code in an include file to behave differently depending on what includes it, then really you should seperate it out into 2 seperate files - or maybe even 3 - 2 for the different behaviours and 1 for the common.
C.