Class not printing variable - php

Im trying to understand objects & classes. But Im having a problem. Im trying to pass a variable from a class into another class.
Why Im doing this is mostly because I want to understand more how classs work but also for future where Im gonna need to send database connection into classes.
Here is my code simplified for the problem:
class databaseConnection
{
public function connect(){
return "localhost";
}
}
class like
{
private $database;
public function __construct(){
$this->database = databaseConnection::connect();
}
public function addLike()
{
return $database;
}
}
$obj = new like;
echo $obj->addLike();
But this doesn't show anything. What i thought the results would be is echo "localhost";
Why isn't this working?

connect is not a static method, you should either change it to static or create an instance.
// if you use databaseConnection::connect();
public static function connect(){
or
$db = new databaseConnection;
$this->database = $db->connect();
And you also need to change
public function addLike()
{
// use $this to access object property
return $this->database;
}

You are calling databaseConnection::connect() as a static method. Modify it to:
public static function connect(){ }
Edit - as #Shankar Damodaran pointed, also add:
public function addLike()
{
return $this->database;
}

First of all you should really follow convention and start naming classes StartingWithCapitalLetter.
Secondly, "::" operator is used to call static methods (to put it simply - you don't have to create object of a class to call them, if they are public).
Normally, to call object's method you use operator "->", like $object->method(arguments);
So in your case, you need to first create an object of your databaseConnection class (because you can't call methods on not-initialized methods) and then call "connect" on it, like that:
$connection = new databaseConnection();
$database = $connection->connect();
To pass a parameter, you need to modify the method declaration
public function connect($parameter){
return "Connecting to " ... $parameter;
}
and call it with
$database = $connection->connect($parameter);
On a sidenote, you should really use parenthesis when creating objects of a class, like:
$obj = new like();
echo $obj->addLike();
Also, as deceze pointed out, you need to access class variable using $this instead of accessing local method variable:
public function addLike()
{
return $this->database;
}

public function addLike()
{
return $this->database;
}

$database and $this->database are two different variables. $database is a local function variable which does not exist, it's not the object property you set before.

Related

How to use an instance of a class within another class in PHP 7

I have what seems like a simple query but I have not found an answer elsewhere.
I have 2 classes, one called DB which essentially connects to the database and can then run queries. I instantiate it at the top of the document $db= new DB; and I can then run a series of queries on the database throughout the page.
The issue I am having is that I want to use this instance within another class I have called User.
I know I can either instantiate again but this does not make sense OR pass the instance of DB when instantiating User, for instance $user = new User($db); but considering the $db instance will be used by most classes I am going to create I am thinking there is a better solution to import it into other classes.
I have looked at the global route but I read it is bad practice + I am getting unexpected global error
class User{
global $db;
public function __construct()
{
var_dump($this-> db);
}//end constructor
}//end class
Since your DB client will be instantiated once and then used everywhere else my initial thought was to recommend passing it as a constructor parameter (dependency injection), but since you are not fan of this approach, I would recommend making your DB client a singleton class, which means it can only be instantiated once and any subsequent attempt would return the same instance everywhere.
You can see a detailed response about singleton classes in PHP at Creating the Singleton design pattern in PHP5.
As a quick example, your DB would look like similar to this:
final class DB
{
public static function getInstance()
{
static $inst = null;
if ($inst === null) {
$inst = new self();
}
return $inst;
}
private function __construct()
{
// your code here ...
}
// your code here ...
}
And then, on your User class you would just get the DB class instance:
class User {
// your code here ...
public function doSomething() {
$db = DB::getInstance();
// your code here ...
}
}
PHP does not handle scopes like Javascript does, your $db is undefined.
The scope of a variable is the context within which it is defined. For the most part all PHP variables only have a single scope. This single scope spans included and required files as well […] Within user-defined functions a local function scope is introduced. Any variable used inside a function is by default limited to the local function scope.
Source: http://php.net/manual/en/language.variables.scope.php
This means that there is only a global scope and a function/method scope in PHP. So, either pass the $db instance into the method as a collaborator
class User{
public function __construct() {}
public function getInfo(Database $db) {
$db->query( /* ... */ );
}
}
$user = new User();
$db = new Database();
$user->getInfo($db);
or pass it in the constructor (dependency injection)
class User{
private $db;
public function __construct(Database $db)
{
$this->db = $db;
}
public function getInfo() {
$this->db->query( /* ... */);
}
}
$db = new Database();
$user = new User($db);
$user->getInfo();

Classes using mysqli

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.

Test if a function is run from a static context

I am writing a PHP class and have included a couple static functions for quick access as they are common for use and are simple in function. However they do use an object in them for database access. I will likely be using these static methods from both a static and non-static context throughout my code so I want to be able to test whether the function was called from a static or non-static context so that I can avoid creating a duplicate object if the function was called from a non-static context (this instance object and the one within the function to be used statically). Is there any way that I can test this in the function so that I can use the instance object if the function is called from a non-static context and create it's own object if the function is called from a static context?
Code Example:
class MyClass {
private $db;
function __constuct(){
$this->db = new DBConnect();
}
public static function myFunction(){
if(/* Is static */){
$db = new DBConnect();
} else {
$db =& $this->db;
}
// Do processing with $db, etc.
}
}
When a method is declared as static,
not only is the magic variable $this
unavailable (returns NULL), but it is
impossible to tell if the function was
actually called from a static context.
A backtrace implies that for a static
method, calling $object->method() is
internally translated to
className::method() at run time.
http://php.net/manual/en/language.oop5.static.php
You can check for non-static access only if you do not force the method to be static-only. Leave out the static keyword from the function declaration and test with:
public function myFunction(){
if(!isset($this)) {
(It can still be called as static function, even though you did not declare it as such.)
Bottom line - don't make classes which contain only static functions. It is not OOP, it is just your old procedural code masquerading as oop
If you are executing functions statically, there is no $this, as there is no object.
You will end up making the private $db a static variable too , and use it as self::$db.
That said, i would recommend to drop this pattern and write something like :
class Foobar
{
protected $_connection = null;
public function __construct( DBConnect $db )
{
$this->_connection = $db;
}
public function some_function()
{
$db = $this->_connection;
// Do processing with $db, etc.
}
}
And you use this class like this :
$db = new DBConnection( /* your password , user , host , etc. */);
$stuff = new FooBar( $db );
$stuff->some_function();
$blah = new DifferentClass( $db );
This way you share the same connection with all the classes that require it. And now the class FooBar is not responsible for making connection or has to know your connection details.
Solution 1: Make the $db variable private, and use it via a getter.
Solution 2: Implement a singleton pattern on the dbal side.
Even when calling a static method from an instance (not recommended), you do not have
access to $this, so your class will fatal.
class sns {
public static function moo() {
var_dump($this->fng);
}
public function goo() {
var_dump($this);
}
}
sns::moo();
$_ = new sns;
$_->moo();
$_->goo();
As another poster has indicated from the php manual.
$db however can be defined statically instead so it only needs to be created once regardless of whether the object is an instance or not.

PHP: Utilizing singleton pattern correctly?

I've trying to learn PHP OOP and have made some research on how to make a global database class to use around in my project. From what I've seen the most appropriate pattern available is a singleton which would ensure that only one database connection are present at all times. However as this is my first time working with the Singleton pattern, I am not sure that I have made it right.
Is this a proper singleton? Will this code ensure one database connection only? Is there any way I can test this? (Learn a man to fish and he will have food for the rest of his life...)
I am using redbean as my ORM and here's how I set it up plainly:
require_once PLUGINPATH.'rb.php';
$redbean= R::setup("mysql:host=192.168.1.1;dbname=myDatabase",'username','password');
I've made the following script based upon this source, as my own singleton Database class;
class database {
private $connection = null;
private function __construct(){
require_once PLUGINPATH.'rb.php';
$this->connection = R::setup("mysql:host=192.168.1.1;dbname=myDatabase",'username','password');
}
public static function get() {
static $db = null;
if ( $db === null )
$db = new database();
return $db;
}
public function connection() {
return $this->connection;
}
}
Thanks!
The instance variable needs to be a static member of the class. I haven't tested this code, but it should work. Connection should probably be static too. With this code, you will have one instance of your database class, and one instance of the connection. It is possible to do this without connection being static, but making it static will ensure there is only one connection instance. I also changed the literal names of the class to php magic constants. This make your code more maintainable. If you change the name of your class down the road, you won't have to go and find all of the literal instances of the old class name in your code. This may seem like overkill now, but trust me, as you work on more and more complex projects, you will appreciate the value.
class database {
private static $connection = null;
private static $db;
private function __construct(){
require_once PLUGINPATH.'rb.php';
self::$connection = R::setup("mysql:host=192.168.1.1;dbname=myDatabase",'username','password');
}
public static function get() {
if ( !(self::$db instanceof __CLASS__) ) {
$klass = __CLASS__; // have to set this to a var, cant use the constant with "new"
self::$db = new $klass();
}
return self::$db;
}
public function connection() {
return self::$connection;
}
}
You're singleton is almost correct.
The private member (no pun intended) $connection needs to be static as well. You might go with the following too:
class database {
private static $instance = NULL;
protected $conn;
private function __construct() {
$this->conn = mysql_connect( ... );
}
public static function init() {
if (NULL !== self::$instance)
throw new SingletonException();
self::$instance = new database();
}
public static function get_handle() {
if (NULL === self::$instance)
; // error handling here
return self::$instance->conn;
}
}

Objects in PHP including other objects

I think the title is right but please correct me if It is mis-leading.
The problem: I have a class which wants to use the DB class, now instead of having to "global $db;" in every method I wish to use the DB object I want to be able to place the object reference in my class properties.
Still following? OK here goes:
class user
{
private $id = 0;
private $name = NULL;
private $password = NULL;
private $db;
function __construct()
{
$this->load_db();
}
private function load_db()
{
global $db;
$this->$db =& $db;
}
I get an error "Object of class db could not be converted to string" which is annoying as I can't figure out how to set the var type in PHP...
Now my question is two fold:
1) How do I fix this.
or
2) Is there a better way of doing it as this feels really "kack-handed".
Thanks in advance,
Dorjan
edit: Just to make sure I'm clear I do not want to make multiple instances of the same DB object. At least I believe this to be a good practice ^,^
If you're using $this, you only need one dollar sign. So $this->db.
private function load_db()
{
global $db;
$this->db =& $db;
}
Also if you are using php 5 you dont need to use the =& operator because objects are implicitly passed by reference. Secondly, you should inject $db into the constructor or fetch it from a Registry object instead of using global.
You should better do
class User
{
private $id = 0;
private $name = NULL;
private $password = NULL;
private $db;
function __construct($db=null)
{
$this->db = $db;
}
}
Note that you don't put a $ before variable names if you access properties via $object->. That is were the error comes from.
To use a global inside a class method is really bad practice as you somehow tie your class to that global variable. Better pass it as a parameter to the constructor or a method.
Later you can instantiate the class with
$user = new User($db)
Also note that class names by convention start with a capital letter.
This:
$this->db
Inject the db instance through the constructor
public function __construct($db)
{
$this->db = $db;
}
Yopu'll want to use something called dependency injection. This is where you "inject" an object into another object to do whatever it is the object does. In this case do database stuff
class user
{
private $id = 0;
private $name = NULL;
private $password = NULL;
private $db;
function __construct($database_object)
{
$this->load_db();
$this->$db = $database_object;
}
public function do_db_stuff()
{
$this->$db->doStuff();
}
$db = new Mysql()
$user = new User($db);
$user->do_db_stuff();

Categories