PHP Passing an object through a class? - php

After restructuring my entire class layout, I'm still having trouble using multiple class instances.
class User {
public $variable;
public function getUser() {
$this->variable = 'It works!';
return 'bob';
}
}
class Base {}
class One extends Base {
public function test() {
print_r($User->variable); // Want it to print 'It works!'
}
}
$User = new User();
$username = $User->getUser();
if($username === 'bob') {
$One = new One();
$One->test(); // prints "Notice: Undefined property: One::$variable
}
What the above code does: The class User gets the username. If the username is bob, it will create an object one and try to print the variable from class User. In my real code, User is extremely intricate and passing a bunch of things with __construct just isn't what I'm looking for.
I think the solution (which is why I titled this question as so) would be to create a new class User within class Base but I just can't wrap my head around having to create a whole new object and re-initiate everything just to get the username.

Inject your User instance:
class One {
private $user;
public function __construct(User $user) {
$this->user = $user;
}
public function test() {
print_r($this->user->variable);
}
}
$User = new User();
$One = new One($user);
$One->test();
This doesn't have any undue effects with regards to efficiency, as the instance is passed by reference as opposed to copied.

The class One does not know about the $User variable and therefore can not access it.
You could either pass the variable to the class in the constructor or set it after creation of an object of the class.
class One extends Base {
protected $user;
public function setUser(User $user) {
$this->user = $user;
}
public function One(User $user) {
$this->setUser($user);
}
public function test() {
print_r($this->user->variable);
}
}
Or (but please don't, it is bad practice) set the $User variable to global.
global $User

Related

php oop how connect two class (extended from one parent)

is possible to connect two class like this ?
we want first login with admin class then use $user without passing variables
class app {
$user;
}
class admin extends app {
function login() {
$this->user = "lamar";
}
}
class song extends app {
function add() {
// add somthing with $this->user
}
}
$admin = new admin();
$admin->login();
now how to use class song to add song with user "lamar" ?
Connecting classes and use their values without passing variables is not possible. Have a look at dependency injection to get access to a class within another.
Regarding to your example it could look like this:
class User {
private $username;
function getUsername() {
return $this->username;
}
}
class Song {
private $user;
function __construct(User $user) {
$this->user = $user;
}
function getUser() {
return $user;
}
}
It might be a good idea to optimize your approach for app, admin and song otherwise your architecture could become quite complicated.

Passing a variable into a protected function in PHP

I am working with a plugin where there is a protected function like so
<?php
class CustomUploadHandler extends UploadHandler {
protected function get_user_id() {
//If I manually enter a value here, the value passes along
return ('myvariable');
}
}
?>
Yet when I make a variable like
<?php $myvar = 'myvariable'; ?>
and try to insert it into the function like this
<?php
class CustomUploadHandler extends UploadHandler {
protected function get_user_id() {
//If I use a variable, the value is lost
return ($myvar);
}
}
?>
it completely fails...
I am unfamiliar with protected classes and also how return() works so any help would be greatly appreciated.
I have tried many lines of code such as
print $myvar; return $myvar; echo $myvar; with and without ()
Don't introduce global state via the global keyword. You'll be welcoming a world of pain down the line.
Instead, inject the dependency (the value, a user ID in this case) into the class when it's created, or with a setter.
class CustomUploadHandler extends UploadHandler
{
private $user_id;
protected function get_user_id()
{
return $this->user_id;
}
// setter injection; the value is
// passed via the method when called
// at any time
public function set_user_id($user_id)
{
$this->user_id = $user_id;
}
// constructor injection; the value is
// passed via the constructor when a new
// instance is created
public function __construct($user_id)
{
$this->set_user_id($user_id);
}
}
Then when you have an instance of this class:
// creates and sets $user_id = 42
$customUploadHandler = new CustomUploadHandler(42);
// sets $user_id = 77
$customUploadHandler->set_user_id(77);
Protected means that only the class itself, the parent class and the childs of the class where the function is defined can use the function. So it depends from where you call the function for it to work. return statements without brackets should be fine.

Accessing object's properties from another class

I'm playing around with OOP in PHP and I've got the following code:
index.php:
<?php
include('user.class.php');
include('page.class.php');
$user = new User;
$page = new Page;
$page->print_username();
?>
user.class.php:
<?php
class User {
public function __construct() {
$this->username = "Anna";
}
}
?>
page.class.php:
<?php
class Page extends User {
public function __construct() {
}
public function print_username() {
echo $user->username;
}
}
?>
My problem occurs in the class "Page", in the print_username() function.
How do I access the $user object's properties within this class? I am, as you can see, defining the two objects in index.php.
Thanks in advance
/C
class User {
public $username = null;
public function __construct() {
$this->username = "Anna";
}
}
class Page extends User {
public function __construct() {
// if you define a function present in the parent also (even __construct())
// forward call to the parent (unless you have a VALID reason not to)
parent::__construct();
}
public function print_username() {
// use $this to access self and parent properties
// only parent's public and protected ones are accessible
echo $this->username;
}
}
$page = new Page;
$page->print_username();
$user should be $this.
class User {
public $username = null;
public function __construct() {
$this->username = "Anna";
}
}
class Page extends User {
public function print_username() {
echo $this->username; //get my name! ($this === me)
}
}
I see some confusion here:
You've caused your Page class to inherit from User. This means that the page itself has all the properties of the User class, and in fact, could be used in place of a User class. As the print_username() method is written in your code, it won't work - because it doesn't have a reference to a $user variable. You could change $user to $this to get a username in the print_username() method, and borrow from the parent class (User) to get the username property.
My thinking is though, that you didn't intend to do that. A Page is not a User, after all - they aren't related to each other. So what I'd do instead is remove extends User from the Page class. This will make a Page a Page, and a User a User.
But how is the Page going to print a username? Pages need to do that of course. What you could do instead is pass the $user object as a parameter to the Page's __construct() method, and then you can reference that value in your Page.
The first way of writing the code, using extends, involves inheritance. The second way of writing the code when passing in the user as a parameter involves composition. In a situation like this, with two separate ideas (Pages and Users), I would use composition to share and access object properties instead of inheritance.
I would do this instead:
<?php
class User {
public function __construct() {
$this->username = "Anna";
}
}
class Page {
private $user;
public function __construct($user) {
$this->user = $user;
}
public function print_username() {
echo $user->username;
}
}
$user = new User;
$page = new Page($user);
$page->print_username();
?>

DataMapper For Codeigniter: Possible To Instantiate Model Object Just Once and Reuse?

Not trying to spam or advertise here, I value this community and the people that gladly give up their time to answer questions (like myself). I have built an authentication library for Codeigniter called WolfAuth. It currently relies on DataMapper for all database interaction, until further notice.
Each function currently uses code along the lines of the following.
$u = new User;
$u->get_by_id($user_id);
if ( $u->exists() )
{
// Do user stuff here
}
I'm not entirely sure how PHP handles object instantiation, but surely doing this in 50 functions plus can't be good for performance, and if not, adds unnecessary object instantiation. Is it possible to have a global instantiation of each DataMapper model object I am using and re-use in each function?
So something like the following.
class Someclass {
protected $user;
protected $group;
protected $roles;
public function __construct()
{
$this->user = new User;
$this->group = new Group;
}
public function the_user($user_id)
{
$user = $this->user->get_by_id($user_id);
if ( $user->exists() )
{
echo "The user exists!";
}
}
}
Am I just being extremely picky here, or is what I am asking possible and probably the better way to do things for such a large library like I've built?
Yes, you can pass objects as arguments in php.
class Someclass {
protected $user;
protected $group;
protected $roles;
public function __construct()
{
$this->user = new User();
$this->group = new Group();
}
public function get_user($user_id)
{
if (empty($this->user->id))
{
$user = $this->user->get_by_id($user_id);
}
else
{
$user = $this->user;
}
if ( $user->exists() )
{
prove_user_exists($user);
return $user;
}
else
{
show_error('No User Found');
}
}
public function prove_user_exists($user)
{
log_message('info', $user->id);
}
Then, you can just call get_user($user_id) when you need the user - if the user has already been found, then you won't have to call the db again.

How to make a globally accessible object

Hi i have a little collection of classes some of which should be globally accessible.
I found something similar in Zend_Registry, but reading its code i cant understand how a call to a static function could return an initialized instance of a class...
i need to do something like:
<?php
//index.php
$obj = new myUsefulObject();
$obj->loadCfg("myFile.xml");
$req = new HTTPRequest();
$req->filter("blablabla");
myappp::registerClass("object",$obj);
myappp::registerClass("request",$req);
$c = new Controller();
$c->execute();
?>
Here i have filtered the Request object and i want the controller to be able to reach that already filtered request.
<?php
class Controller
{
function __construct()
{
$this->request = Application::getResource("request");//This must be the filtered var =(
}
}
?>
I don't know how to implement that Application::getResource(), the only thing i know is that it must be a static method because it can't be related to a specific instance.
Aside from static methods, PHP also has static properties: properties that are local to the class. This can be used to implement singletons, or indeed a Registry:
class Registry {
private static $_registry;
public static function registerResource($key, $object)
{
self::$_registry[$key] = $object;
}
public static function getResource($key) {
if(!isset(self::$_registry[$key]))
throw InvalidArgumentException("Key $key is not available in the registry");
return self::$_registry[$key];
}
}
1: You can acess global variables with the global keyword:
$myVar = new SomethingProvider();
class MyClass {
public function __construct() {
global $myVar;
$myVar->doSomething();
}
}
2: You can do the same using the $GLOBALS super-global:
$myVar = new SomethingProvider();
class MyClass {
public function __construct() {
$GLOBALS['myVar']->doSomething();
}
}
3: You can define a singleton class (the wikipedia has a nice example, too).
4: You could add globals as public static members (or private static members with public getters/setters) to a class:
class Constants {
const NUM_RETIES = 3;
}
if ($tries > Constants::NUM_RETRIES) {
# User failed password check too often.
}
class Globals {
public static $currentUser;
}
Globals::$currentUser = new User($userId);
I wouldn't recommend the first two methods, overwriting the values of these global variables unintentionally is too easy.
Seems to me like you might need some form of Singleton design pattern;
Check this out!
Hope it helps!

Categories