Is it possible to pass an object into the constructor of a PHP class, and set that object as a global variable that can be used by the rest of the functions in the class?
For example:
class test {
function __construct($arg1, $arg2, $arg3) {
global $DB, $ode, $sel;
$DB = arg1;
$ode = arg2;
$sel = $arg3;
}
function query(){
$DB->query(...);
}
}
When I try to do this, I get a "Call to a member function on a non-object" error. Is there anyway to do this? Otherwise, I have to pass the objects into each individual function directly.
Thanks!
You probably want to assign them to values on $this.
In your constructor, you'd do:
$this->DB = $arg1;
Then in your query function:
$this->DB->query(...);
This should similarly be done with the other arguments to your constructor.
$this in an instance context is how you reference the current instance. There's also keywords parent:: and self:: to access members of the superclass and static members of the class, respectively.
As a side-note...
Even thought this isn't required, it is generally considered best to declare member variables inside the class. It gives you better control over them:
<?php
class test {
// Declaring the variables.
// (Or "members", as they are known in OOP terms)
private $DB;
protected $ode;
public $sel;
function __construct($arg1, $arg2, $arg3) {
$this->DB = arg1;
$this->ode = arg2;
$this->sel = $arg3;
}
function query(){
$this->DB->query(...);
}
}
?>
See PHP: Visibility for details on the difference between private, protected and public.
you can do it pretty easily by storing the argument as a property of the object:
function __construct($arg1, $arg2, $arg3) {
$this->db = arg1;
}
function f()
{
$this->db->query(...);
}
let's say you have a db object
$db = new db();
and another object:
$object = new object($db);
class object{
//passing $db to constructor
function object($db){
//assign it to $this
$this-db = $db;
}
//using it later
function somefunction(){
$sql = "SELECT * FROM table";
$this->db->query($sql);
}
}
Related
Is there a way that i can access $connect in all functions on class?
class topicClass {
function viewTopic() {
function grabId() {
global $connection;
}
function grabTopic(){
global $connection;
}
function grabReplies(){
global $connection;
}
}
}
Instead of writing it over and over?
Define it as a property of your class, like so:
class topicClass {
private $connection;
public function __construct() {
$this->connection = "myConnectionString";
}
function viewTopic() {
// you can then refer to $this->connection here
}
...
}
When you do:
var cls = new topicClass();
the construct() will be called and will assign the value to connection, and you can then refer to it in the other functions.
NOTE: In the example I gave, I used private. You may need to change that to public, depending on where you need to access it.
<?php
require_once 'database.php';
class User {
public $id;
public $username;
public $first_name;
public $last_name;
public $password;
public static function find_by_id($id){
$result_array = self::find_by_sql("SELECT * FROM users WHERE id = {$id} LIMIT 1");
return !(empty($result_array))? array_shift($result_array): false;
}
public static function find_by_sql($sql){
global $database;
$result = $database->query($sql);
$object = array();
while ($row = $database->fetct_array($result)){
$object[] = self::instantiate($row);
}
return $object;
}
public static function instantiate($record)
{
$object = new self;
foreach($record as $attribute => $value)
{
if ($object->has_attribute($attribute)){
$object->$attribute = $value;
}
}
return $object;
}
private static function has_attribute($attribute){
$object_var = get_object_vars($this);
return array_key_exists($attribute, $object_var);
}
}
?>
I got error when I try to call function has_attribute. Notice: Undefined variable: this
Why I cannot use this in get_object_vars in private function has_attribute($attribute).
Can anyone help me with that?
Thank you.
$this is not defined in static methods (they belong to the class in general, not to specific object) - but all the methods in your class are defined as static.
You might want to change the has_attribute method so it'll take the instance of User as a param, but I don't think that's good design. In fact, I don't understand why do you need this method at all: for all the cases when non-existing property of an object is accessed, so-called magic method __get() is called automatically:
The overloading methods are invoked when interacting with properties
or methods that have not been declared or are not visible in the
current scope. [...] __get() is utilized for reading data from inaccessible properties.
If you defined has_attribute to prevent accessing non-existing properties (log these attempts, for example), move the code into __get.
That is because $this keyword is not accesible on a static context.
Source
I am building an API in PHP and I have a question. I'm using classes, and some of these classes need to access my database. However, I don't want to define variables for the database in every single class in order to open it, or have to send my mysqli object as a parameter of every single class constructor.
What would be the best way to go about this? Do I define a global variable of some kind?
A classic solution would be as follows
Create an instance of dbatabase handler class, either raw mysqli (worse) or better abstraction class (way better)
In the constructor of your application class take this db class instance as a parameter and assign it to a local variable
Use this variable with your class.
A quick example:
class Foo()
{
protected $db;
function __construct($db);
{
$this->db = $db;
}
function getBar($id)
{
return $this->db->getOne("SELECT * FROM bar WHERE id=?i", $id);
}
}
$db = new safeMysql();
$foo = new Foo($db);
$bar = $foo->getBar($_GET['id']);
How about using a static classes?
class mysqli_wrapper {
private static $db = null;
public static function open() {
GLOBAL $opts; // this can be global or setup in other ways
if (!self::$db) {
self::close();
self::$db = null;
}
self::$db = #mysqli_connect('p:'.$opts['hn'], $opts['un'], $opts['pw'], $opts['db']);
return self::$db;
}
public static function query($qry) {
return mysqli_query ( self::$db, $qry );
}
public static function affected_rows() { return #mysqli_affected_rows(self::$db); }
public static function error() { return #mysqli_error(self::$db); }
public static function close() { #mysqli_close(self::$db); }
} // end mysqli_wrapper
mysqli_wrapper::open(); // Here's how to call it
In a system I maintain my app needs to access its own MySQL db, as well as remote Oracle and SQL Server databases, and I use a trait for it. Here's a simplification of my code, just using MySQL:
dbaccess.php
trait DatabaseAccess {
protected $db;
private $host = 'host', $dbName = 'db', $username = 'username', $password = 'pword';
public function connectToMysql() {
$this->db= new mysqli(......);
}
}
then in myclass.php
require 'dbaccess.php';
class MyClass {
use DatabaseAccess;
//class code.....
}
All elements of DatabaseAccess will be available as if you hand-typed them in MyClass.
Note: if you're using PHP < 5.4, then this solution won't be possible.
I still have not been able to figure this out. How can we access a one class object in another class?
I am using the below code but I am getting and error:
class ListofRecord{
var $db;
function __construct(){
$db = global $db;
}
function record(){
$record = $this->db->SelectQuery("SELECT * FROM user order by UID ASC");
return $record;
}
}
You need to refer to the global $db variable first and then use it in a statement. You also have a minor syntax error in your constructor. You forgot to use the $this keyword when referring your your $db property.
function __construct(){
global $db
$this->db = $db;
}
It also is a better practice not to use global variables and instead pass any variables that you need as parameters to your method call. In this case it is your constructor:
function __construct($db){
$this->db = $db;
}
$list_of_record = ListofRecord($db);
I have a global variable outside my class = $MyNumber;
How do I declare this as a property in myClass?
For every method in my class, this is what I do:
class myClass() {
private function foo() {
$privateNumber = $GLOBALS['MyNumber'];
}
}
I want this
class myClass() {
//What goes here?
var $classNumber = ???//the global $MyNumber;
private function foo() {
$privateNumber = $this->classNumber;
}
}
EDIT: I want to create a variable based on the global $MyNumber but
modified before using it in the methods
something like: var $classNumber = global $MyNumber + 100;
You probably don't really want to be doing this, as it's going to be a nightmare to debug, but it seems to be possible. The key is the part where you assign by reference in the constructor.
$GLOBALS = array(
'MyNumber' => 1
);
class Foo {
protected $glob;
public function __construct() {
global $GLOBALS;
$this->glob =& $GLOBALS;
}
public function getGlob() {
return $this->glob['MyNumber'];
}
}
$f = new Foo;
echo $f->getGlob() . "\n";
$GLOBALS['MyNumber'] = 2;
echo $f->getGlob() . "\n";
The output will be
1
2
which indicates that it's being assigned by reference, not value.
As I said, it will be a nightmare to debug, so you really shouldn't do this. Have a read through the wikipedia article on encapsulation; basically, your object should ideally manage its own data and the methods in which that data is modified; even public properties are generally, IMHO, a bad idea.
Try to avoid globals, instead you can use something like this
class myClass() {
private $myNumber;
public function setNumber($number) {
$this->myNumber = $number;
}
}
Now you can call
$class = new myClass();
$class->setNumber('1234');
Simply use the global keyword.
e.g.:
class myClass() {
private function foo() {
global $MyNumber;
...
$MyNumber will then become accessible (and indeed modifyable) within that method.
However, the use of globals is often frowned upon (they can give off a bad code smell), so you might want to consider using a singleton class to store anything of this nature. (Then again, without knowing more about what you're trying to achieve this might be a very bad idea - a define could well be more useful.)
What I've experienced is that you can't assign your global variable to a class variable directly.
class myClass() {
public $var = $GLOBALS['variable'];
public function func() {
var_dump($this->var);
}
}
With the code right above, you get an error saying "Parse error: syntax error, unexpected '$GLOBALS'"
But if we do something like this,
class myClass() {
public $var = array();
public function __construct() {
$this->var = $GLOBALS['variable'];
}
public function func() {
var_dump($this->var);
}
}
Our code will work fine.
Where we assign a global variable to a class variable must be inside a function. And I've used constructor function for this.
So, you can access your global variable inside the every function of a class just using $this->var;
What about using constructor?
class myClass {
$myNumber = NULL;
public function __construct() {
global myNumber;
$this->myNumber = &myNumber;
}
public function foo() {
echo $this->myNumber;
}
}
Or much better this way (passing the global variable as parameter when inicializin the object - read only)
class myClass {
$myNumber = NULL;
public function __construct($myNumber) {
$this->myNumber = $myNumber;
}
public function foo() {
echo $this->myNumber;
}
}
$instance = new myClass($myNumber);
If you want to access a property from inside a class you should:
private $classNumber = 8;
I found that globals can be used as follows:
Create new class:
class globalObj{
public function glob(){
global $MyNumber;
return $this;
}
}
So, now the global is an object and can be used in the same way:
$this->glob();
class myClass
{
protected $foo;
public function __construct(&$var)
{
$this->foo = &$var;
}
public function foo()
{
return ++$this->foo;
}
}