I've VERY NEW to PDO. I created the below function, but I read having the global database ($dbo) is a bad idea. The code works and outputs what I want it too. Any suggestions on how to improve/fix?
function langString($lang_id) {
global $dbo;
$lang_result=$dbo->prepare("SELECT lang_string FROM lang WHERE lang_id=:lang_id");
$lang_result->bindParam(":lang_id",$lang_id,PDO::PARAM_INT,3);
if($lang_result->execute()){
$lang_row = $lang_result->fetch(PDO::FETCH_OBJ);
echo "<br><br>$lang_row->lang_string";
}
}
echo langString(3);
Pass the variable as an argument to the function
function langString($lang_id, $dbo) {
$lang_result=$dbo->prepare("SELECT lang_string FROM lang WHERE lang_id=:lang_id");
$lang_result->bindParam(":lang_id",$lang_id,PDO::PARAM_INT,3);
if($lang_result->execute()){
$lang_row = $lang_result->fetch(PDO::FETCH_OBJ);
echo "<br><br>$lang_row->lang_string";
}
}
echo langString(3, $dbo);
The catch with the accepted answer is that you will end up trailing your database round every function as a parameter. This results in longer lists of parameters and as you get more stuff starts to look messy.
An alternative method is to make a Singleton which you can call to get the database connection e.g. Normally large projects will use this for more than just accessing the DB but here's a simple example
class DatabaseProvider {
private static $database;
private $dbo;
private function __construct() {
//Here's where you do your PDO connection creation
$this->dbo= new PDO()....;
}
public static function getDatabase() {
if(!isset(self::$database) {
self::$database = new DatabaseProvider();
}
return $database->dbo;
}
}
Then you just call DatabaseProvider::getInstance() which returns the pdo object
Use an include file...
Put your variables or even create a db object in the include, and then you can call it from anywhere.
function langString($lang_id) {
include($_SERVER['DOCUMENT_ROOT']."/dbconnect.php"); //Put your vars in this document
$lang_result=$dbo->prepare("SELECT lang_string FROM lang WHERE lang_id=:lang_id");
$lang_result->bindParam(":lang_id",$lang_id,PDO::PARAM_INT,3);
if($lang_result->execute()){
$lang_row = $lang_result->fetch(PDO::FETCH_OBJ);
echo "<br><br>$lang_row->lang_string";
}
}
echo langString(3);
Related
I have created a PHP class and I want to access its methods from a function in another file. Below is my code:
include_once PLUGIN_DIR_PATH."/classes/Brands.php";
function create_tables(){
$brand_obj = new Brands;
$brand_obj->create_brand_table();
}
function delete_tables() {
$brand_obj = new Brands;
$brand_obj->delete_brand_table();
}
Is it possible to create the object only once and then reuse it in every function? Right now, I am creating object in every function which is not a good practice.
You can use the global keyword to use a variable created outside a function inside a function:
global $object
code example :
include_once PLUGIN_DIR_PATH."/classes/Brands.php";
$brand_obj = new Brands;
function create_tables(){
global $brand_obj;
$brand_obj->create_brand_table();
}
function delete_tables() {
global $brand_obj;
$brand_obj->delete_brand_table();
}
I'm going to assume your actual functions do more than what you posted, otherwise you don't really need functions and can simply do this:
$brand_obj = new Brands;
$brand_obj->create_brand_table();
$brand_obj->delete_brand_table();
Otherwise, you can make a class and inject the Brands dependency into one of its properties via its constructor:
class TablesManager
{
private $brands;
public function __construct(Brands $brands)
{
$this->brands = $brands;
}
public function create_tables(): void
{
$this->brands->create_brand_table();
}
public function delete_tables(): void
{
$this->brands->delete_brand_table();
}
}
Usage:
$brands = new Brands();
$tables_manager = new TablesManager($brands);
$tables_manager->create_tables();
$tables_manager->delete_tables();
Note: calling a class SomethingManager is sometimes considered bad practice / a sign that the class does too many things. Consider (at least) giving it a more accurate name for your needs.
Demo: https://3v4l.org/iTmY6
Non-OOP alternative
function create_tables(Brands $brand_obj): void {
$brand_obj->create_brand_table();
}
function delete_tables(Brands $brand_obj): void {
$brand_obj->delete_brand_table();
}
$brand_obj = new Brands();
create_tables($brand_obj);
delete_tables($brand_obj);
I have a class that executes eval statements within a (very large) loop. The eval statements are database stored code (mixed html & php) that needs to be processed. There is however is a serious performance issue because of this.
Instead of parsing the eval-statement every time in the loop, I would like to create a dynamic methods from the available eval-codes coming from the database within my class.
I thought of the following pseudocode so that the eval code is converted to a method:
class foo
{
private $test=3;
public function doloop()
{
for($i=0;$i<5;$i++)
{
$string="echo 50 * \$this->test.'<br>';";
$func="evalcode_001";
if(!isset(${$func}))
{
${$func}=create_function('',$string);
}
${$func}();
}
}
}
$obj_foo = new foo();
$obj_foo->doloop();//must output '150<br>150<br>150<br> .....'
However when running it I get the error message "Using $this when not in object context in ...". So obviously I didn't really create methods within the class.
So my question is:
How do I create a method for a class dynamically and assign code for the given method. Basically I want to be able to do:
$obj_foo->evalcode_001();
in the above example.
Help appreciated
PS I am using PHP5.4
If you can change $this->test inside string (or write extra preg_match) you can use:
<?php
class foo
{
public $test=3;
public $functions = array();
public function doloop()
{
for($i=0;$i<5;$i++)
{
$string="echo 50 * \$this->test.'<br>';";
$func="evalcode_001";
if(!isset($this->functions[$func]))
{
$string = str_replace('$this','$object', $string );
$this->functions[$func]= create_function('$object',$string);
}
$this->functions[$func]($this);
}
}
public function __call($name, $arguments) {
if (isset($this->functions[$name])) {
return $this->functions[$name]($this);
}
}
public function otherMethod() {
echo "test";
}
}
$obj_foo = new foo();
$obj_foo->doloop();//must output '150<br>150<br>150<br> .....
$obj_foo->evalcode_001();
$obj_foo->otherMethod();
However as other said I wouldn't like to use anything like that in my real script
I am getting this error and i can't see what i am doing wrong. I have done the same thing with other objects from other classes which are built in the exact same way and i can't see why i am getting this error now.
The code in which i create the object is this one:
$consulta2 = "SELECT * FROM TiposDireccion WHERE Cliente_CIF='$cif' and Direccion_Direccion='$direccion' and Direccion_CP=$cp ";
echo($consulta2."</br>");
if ($resultado2 = $conexion->query($consulta2)){
while($fila2 = $resultado2->fetch_object()){
$tipodireccion78=$fila2->TipoDireccion_Tipo;
//we see here that the select is returning a correct string with a correct value
echo($tipodireccion78);
//we try to instantiate and it fails =(
$unTipoDireccion=TipoDireccion::constructor1($tipodireccion78);
This is the class TipoDireccion:
<?php
class TipoDireccion{
private $tipo;
private $descripcion;
//Construct auxiliar
function __construct() {
}
//Constructor 1 : completo
function constructor1($tipo) {
$tipoDireccion = new TipoDireccion();
$tipoDireccion->tipo = $tipo;
return $tipoDireccion;
}
function ponTipo($tipo) {
$this->tipo = $tipo;
}
function devuelveTipo() {
return $this->tipo;
}
function ponDescripcion($descripcion) {
$this->descripcion = $descripcion;
}
function devuelveDescripcion() {
return $this->descripcion;
}
}
?>
Thank you a lot in advance!
Don't know if this is still relevant to you, but in case anyone else comes on here for an answer. The problem is in this function:
function constructor1($tipo) {
$tipoDireccion = new TipoDireccion();
$tipoDireccion->tipo = $tipo;
return $tipoDireccion;
}
Because in the class definition, you define private $tipo; and then you try and assign $tipoDireccion->tipo to what was passed through the function. However, you aren't trying to access that variable through the scope of the class, you are trying to assign it from the 'public' scope as far as the class is concerned.
The fix for this has two options, the first one would be to change private $tipo; to public $tipo;. But that isn't a good solution as you have an assignment function for it.
Instead, use your functions that you made, which would make the function look like:
function constructor1($tipo) {
$tipoDireccion = new TipoDireccion();
$tipoDireccion->ponTipo($tipo);
return $tipoDireccion;
}
That's how you need to access it from the public scope, which you are doing after you initiate a new one.
function constructor1($tipo) {}
should be
static function constructor1($tipo) {}
i have 2 classes
for DB
for language
i want to use my language things in the DB
so it outputs the result
ex :
class db_control{
var $db_connection, $lang_var;
//create the function for the connection
function db_connect(){
//define some variables
global $db_host, $db_username, $db_password, $db_name, $lang_var;
$this->db_connection = mysql_connect("$db_host","$db_username","$db_password")or die("can't connect to server with these informations");
//checl that the connection is established
if($this->db_connection){
echo $lang_vars->getvar("$langvals[lang_con_est]");
}
but this
$lang_vars->getvar("$langvals[lang_con_est]");
doesn't work
i mean it outputs many problems
and am sure my problem is that i didn't define my variables and classes correctly
P.S : the language class is in file called language.php and this part is in DB.MySQL.php
EDIT :
this is the language class
class lang_vars{
public static function getvar($variable){
return $variable;
}
}
i want the DB class to display text from the language class
thats why i used
echo $lang_vars->getvar("$langvals[lang_con_est]");
but it doesn't work
cuz when i declare the language class
$lang_vars = new lang_vars;
inside the db_control it shows error unexpected T_something expected T_Function
and when i declare it outside nothing up
hope i made things more clear now
Any reason why you are still using PHP4 syntax?
When creating an instance of the db_control class, pass the object to be stored as $lan_var into the constructor or set it via a dedicated setter. See Dependency Injection.
class DBControl
{
protected $_lang;
public function __construct($lang = NULL)
{
if($lang !== NULL) {
$this->_lang = $_lang;
}
}
public function setLang($lang)
{
$this->_lang = $lang;
}
}
Then do either
$dbControl = new DBControl(new LangThing);
or
$dbControl = new DBControl;
$dbControl->setLang(new LangThing);
Also, get rid of the globals. Pass those in via Dependency Injection too.
Make your language class methods static . Read more here.
class LangClass
{
public static function getvar()
{
// your code here
}
}
Then, you can use its functions without creating objects like this:
$LangClass::getvar("$langvals[lang_con_est]");
This can do the trick.
$lang_vars = new LanguageClassOrWhateverItIsCalled();
$lang_vars->getvar($langvals[lang_con_est]);
But maybe you should think of making it a static method. In that case you can call it with:
LanguageClassOrWhateverItIsCalled::getVar($langvals[lang_con_est]);
You can define the method static like:
public static function getVar() {
// Do something
}
Edit: #SAFAD
You should use the static method for this. To make this work, be sure your class language.php is loaded. To do so just add in the DB.MYSQL.php file the following line:
require_once('language.php');
class db_control {
...
Make sure you have the right path to the language.php file.
Then you should call the method in db_control class like this:
if($this->db_connection){
echo lang_vars::getvar("$langvals[lang_con_est]");
}
Besides, what is the use of a function like this? You should either do:
if($this->db_connection){
echo $langvals[lang_con_est];
}
or change your static getvar method to:
public static function getvar($variable){
return $langvals[$variable];
}
and your function call to:
if($this->db_connection){
echo lang_vars::getvar("lang_con_est");
}
If I create an object inside of the main scope:
INDEX.PHP:
$db = new database();
Then how can I use this same object inside of a completely different class?
ANYTHING.PHP:
class anything {
function __construct(){
$db->execute($something); # I want to use the same object from INDEX.PHP
}
}
Would I need to make $db a global or is there a 'better' more obvious way?
You could just use global to find it:
class anything {
function __construct(){
global $db;
$db->execute($something);
}
}
Or, you could pass it in when creating a new anything:
class anything {
function __construct($db) {
$db->execute($something);
}
}
It really depends on what makes the most sense for you.
For the DB you may want to use Singleton pattern
class anything
{
public function load($id)
{
$db = DB::getInstance();
$res = $db->query('SELECT ... FROM tablename WHERE id = '.(int)$id);
// etc...
}
}
You may want to extend it if you need different DB connections at the same time (i.e main db and forum's db). Then you'll use it like DB::getInstance('forum'); and store instances in associative array.
You could pass it as an argument, like this
function __construct($db){
$db->execute($something);
}
then when you instance anything, do it as anything($db)
As Paolo and ONi suggested you can define $db as global inside the method or pass it into the constructor of the class. Passing it in will create a reference to that object so it will in fact be the same $db object. You could also use the $GLOBALS array and reference $db that way.
$GLOBALS["db"];
I'm assuming that index.php and anything.php are linked together somehow by include() or require() or some similar method?
In Paolo's post:
After you pass it, you can then assign it to a class variable like this:
class anything {
var $db_obj;
function __construct($db) {
$this->db_obj = $db;
}
function getUsers() {
return $this->db_obj->execute($something);
}
}