I have a legacy project, where I have a file with a class that in its construct method makes a connection with a database.
public $mysqli;
public function __construct(){
$this->mysqli = mysqli_connect( "192.168.10.10", "homestead", "secret", "myDatabase" );
}
For now, I would like to make this somewhat flexible and make a config file with an array of values that I would pass to mysqli_connect method. Something like this:
Config file:
$mysqliConfig = [
'192.168.10.10',
'homestead',
'secret',
'myDatabase'
];
And then just require that in the other file and use it in the class constructor of that file:
require_once 'includes/config.php';
class Calculator{
private $mysqli;
public function __construct(){
$this->mysqli = mysqli_connect($mysqliConfig);
}
But that is not working, how should I do that?
You need to make the variables from the config file available to the class.
require_once 'includes/config.php';
class Calculator{
private $mysqli;
public function __construct($mysqliConfig){
$this->mysqli = mysqli_connect($mysqliConfig);
}
}
$cal = new Calculator($mysqliConfig);
As an aside, I would use an associative array for the config to make it more readable.
$mysqliConfig = [
'host' => '192.168.10.10',
'database' => 'homestead',
'user' => 'secret',
'password' => 'myDatabase'
];
// E.g. $mysqliConfig['host']
You can use ... token to unpack the config into the argument list:
$this->mysqli = mysqli_connect(...$mysqliConfig);
What i do is to have a .ini file Advantage is that it returns as a key value association.
save your config details in the .ini file(path/to/config.ini)
In config.ini file,
database_name = mydatabase_name
password = my_password
host = host
system_root = system_root
other_details = other_details
Then on your calculator class, do
<?php
$currentConfig = parse_ini_file(path/to/config/config.ini);
print_r($currentConfig); # prints the entire parsed .ini file
print($currentConfig ['database_name ']); #prints "mydatabase_name"
?>
Related
So, simply put, I feel like this code should work. Literally at this moment I am just trying to create a PHP class that takes in some information and runs a command against the database. I know the command works so it's not that, it something to do with the scope of my variables.
I'm new to PHP, and it's been interesting to handle.
<?php
require __DIR__ . '/../bin/composer/vendor/autoload.php';
$cx = new Customer();
$cx->WriteCxToDB();
class Customer {
public $database = new medoo([
'database_type'=>'mysql',
'database_name'=>'dbname',
'server'=>'localhost',
'username'=>'dbusername',
'password'=>'dbpassword',
'charset'=>'utf8'
]);
public function WriteCxToDB(){
global $database;
if($database->has("customer", [
"OR"=>[
"username"=>"cxusername",
"email"=>"email#gmail.com"
]
]))
{
echo "User already exists";
}else{
$database->insert("customer", [
"username"=>"username",
"keyword"=>"keyword",
"email"=>"email#gmail.com",
"phone"=>"444-444-4444",
"first_name"=>"First",
"last_name"=>"Last"
]);
echo "User added";
}
echo "Done";
}
}
?>
I am using composer and medoo to do this database entry. I know the database code works because I've ran it on it's own and it runs fine.
What I'm struggling with the seems to be the variable $database in the code. The function call works if I remove that variable from the mix. I feel like I'm just not understanding where I am supposed to declare the variable / how to reference it from within / outside the function. Thanks.
As suggested in the previous example you should be using something like this and pass a db connection into the class, extending a base class would allow reuse of the db connection:
private $database;
public function __construct($db_connection = null){
//do stuff or set db
$this->database = $this->db_connect;
}
OR make a method in the class to do it
private function db_connect(){
return new medoo([
// required
'database_type' => 'mysql',
'database_name' => 'name',
'server' => 'localhost',
'username' => 'your_username',
'password' => 'your_password',
'charset' => 'utf8',
]);
}
to check consider catching the errors. Using a unique or primary key on the DB would be a safer way of doing this otherwise you have to do validation and searching on the DB. Add the keys and check for duplicate errors.
if($database->error()){
//deal with return or pass to logging
}
The problem here is the use of global scope. Instead of:
global $database;
if($database->has("customer",
use
if($this->database->has("customer",
you could also consider instantiating $database in the constructor, i.e.
private $database;
public function __construct() {
$this->database = new medoo([args....
I am trying integrate a way of a user being able to store there configuration settings into a blank PHP file like this:
<?php // Configuration.php
$con = array(
'host' => 'host'
'user' => 'username',
'pass' => 'password',
'name' => 'dbname'
);
?>
What I have tried:
class Configuration{
public $database = require_once 'Configuration.php';
}
$config = new Configuration;
print_r($config->database->con);
Is this possible or not? There will be a display on the Configuration.php page when accessed so I don't want to include the page in the site, only require its properties.
Thanks in advance.
Updated working code for viewers - Use of Class and Constructors by #Yoshi
Config.php -
if(defined('DFfdcxc58xasdGJWdfa5hDFG')): // Random unique security key
return array(
'host' => 'localhost',
'user' => 'bob',
'pass' => '123',
'name' => 'data'
);
endif;
Database Class:
interface Dashboard{
public function initialize($actual);
}
define('DFfdcxc58xasdGJWdfa5hDFG',0); // Random unique security key
class Configuration{
protected $config = require_once('Config.php');
protected $api_key = "Xc4FeSo09PxNcTTd3793XJrIiK";
}
class DashboardSettings{
public $alerts = array();
protected $comments = true;
protected $read_only = false;
protected $safe_mode = false;
}
class Database extends Configuration extends DashboardSettings implements Dashboard{
public function __construct(){
$this->db = mysqli_connect($this->config[0],$this->config[1],$this->config[2],$this->config[3]);
if(mysqli_connect_errno){ array_push($this->alerts, 'Error connecting to Database...'); $this->safe_mode = true; }
}
public function initialize($actual = null){
if($actual != null){
// Handle incomming setting - reference DashboardSettings
} else {
// Handle all settings - reference DashboardSettings
}
}
}
The answer is no. When you assign require_once(); to a variable, the variable turns into a boolean with 1 in case the file was included successfully, or 0 otherwise (useless in require_once() as it returns a fatal error if it fails.
So, doing:
<?php
$hello = require_once("./hello.php");
echo $hello; // Prints 1.
?>
Anyway, if you create a php file that returns something, as for example:
FILE: require.php
<?php
$hello = "HELLO";
return $hello;
?>
In this case, the previous example would be different:
<?php
$hello = require_once("./require.php");
echo $hello; // Prints HELLO.
?>
So, you cannot store the function itself to execute it later, but you can store returned values from the required or included files. Anyway, if you explain better what are you using it for, I maybe able to help you better.
Answer By #David Álvarez
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've been creating a small number of libraries / classes from scratch in php. I come from a codeigniter background, and I'm trying to make some libraries with similar functionality. I keep running into issues regarding objects.
Is the best way to create a super object $this somehow? My main issue is that I've created a view object and I run a function called load which looks like so:
class View {
public function __construct() {
}
public function load($file = NULL, $data = array()) {
if($file) {
$file .= '.php';
if(file_exists($file)) {
// Extract variables BEFORE including the file
extract($data);
include $file;
return TRUE;
} else {
echo 'View not found';
return FALSE;
}
} else {
return FALSE;
}
}
}
Then in my php file, I have at the top include 'libraries.php'; which looks like:
include 'database.php';
include 'view.php';
include 'input.php';
include 'form.php';
$config = array(
'host' => 'localhost',
'username' => 'username',
'password' => 'password',
'database' => 'database'
);
$database = new Database($config);
$view = new View();
$input = new Input();
$form = new Form();
From the file which I included the libraries, I am able to write something like $form->value('name'); without errors. However, if I do something like this:
$view->load('folder/index', array('var_name' => 'var_value')); then from the folder/index.php file I can access $var_name just fine, but not $form->value('name');. I get errors such as Call to a member function value() on a non-object in ...
My question is how can I organize my libraries and classes in a way that will be reusable. I don't want to use a front loader (an index.php file that everything runs through first). This may be an issue with the way I wrote my classes, but I imagine it's a larger issue regarding where things are located etc.
Put your library/class files in a common directory. Something like:
www
|_includes
| |_classes
| | |_view.php
| |_config
| |_database.php
|_other_folder
|_index.php
You can then set a common include path in your .htaccess file to this "includes" directory:
php_value include_path .:/path/to/www/includes
Then the other_folder/index.php file just needs something like:
require_once('config/database.php');
require_once('classes/view.php');
All,
I wrote the following wrapper that extends Zend_Db class to provide db connectivity to my entire application. The db connectivity works fine, but it fails to execute queries when invoked from a different class.
class Testapp_DB extends Zend_Db {
//Declare member variables.
public $db = null;
public $db_host = "";
public $db_database = "";
public $db_username = "";
public $db_password = "";
public function __construct()
{
//Read Database Info from Config File
$this->db_host = Testapp_Registry::get('config')->db->mysql->host;
$this->db_database = Testapp_Registry::get('config')->db->mysql->dbname;
$this->db_username = Testapp_Registry::get('config')->db->mysql->username;
$this->db_password = Testapp_Registry::get('config')->db->mysql->password;
$db = Zend_Db::factory('Mysqli', array(
'host' => $this->db_host,
'username' => $this->db_username,
'password' => $this->db_password,
'dbname' => $this->db_database
));
$db->getConnection(); //Works fine
$this->db = $db;
}
}
Trying to execute query in a PHP file that includes Testapp_DB - fails..
<?php
$db = new Testapp_DB();
print_r($db); //I can see the DB object here
$sql = 'SELECT * FROM tb_Log';
$result = $db->fetchAll($sql, 2); //This method fails.. Don't know why. Any ideas?
print_r($result);
?>
Can someone please explain, why the fetchAll method fails?
Thanks
*Zend_Db* doesnt have any method other than factory().
I dont really get, what you are trying to solve this way, but as far as I can see you need to call query() this way
$db->db->query();
Perhaps instead of using your wrapper, try this:
// Note: change your config to have a 'params' entry
$db = Zend_Db::factory(Testapp_Registry::get('config')->db->mysql);
Zend_Db_Table_Abstract::setDefaultAdapter($db);
Zend_Registry::set('database', $db);
// in your config
...mysql.params.host = ...
...mysql.params.dbname = ...
...mysql.params.username = ...
...mysql.params.password = ...
Then, your Zend_Db_Table objects will have connectivity, and in addition you can grab the connection using Zend_Registry::get('database'). And, you'll make only one database connection once per request.
Try to create a SQL file like schema.mysql.sql,
then test it on phpMyAdmin and when it's free of bugs run this code:
$bootstrap = $application->getBootstrap();
$bootstrap->bootstrap(‘db’);
$config = $bootstrap->getResource(‘db’)->getConfig();
$runCommand = “mysql -h “.$config["host"].” -P “.$config["port"].” -u’”.$config["username"].”‘ -p’”.$config["password"].”‘ “.$config["dbname"].” < “.dirname(__FILE__) . ‘/schema.mysql.sql’;
echo $runCommand;
system($runCommand);
Hope this helps! http://www.unexpectedit.com/zend-php/zend-db-exec-a-sql-file