Simple OOP PHP Question - php

Sorry for the noob question.
I have the following code which works fine:
$obj = new view;
echo $obj->connect();
echo $obj->content_two();
Basically what I need to do is get a variable called $variable from inside the function content_two(), How would I call $variable from content_two() ?
Thanks in advance.

With a member property.
<?php
class View {
protected $foo;
function connect() {
$this->foo = 42;
return "Hello from connect";
}
function connectTwo() {
return "Hello from connectTwo. foo = " . $this->foo;
}
}
Note that the conventions dictates that classes are named in CapitalCamelCase, whereas methods (functions on objects) and properties (variables on objects) are named in lowerCamelCase. You don't have to follow the convention, but it's probably a good idea to do so.

Related

Defining dynamic variable inside function scope

I have a very simple class:
class MyClass
{
public function someFunction()
{
echo array_key_exists( 'dynamicVariable', $GLOBALS ) ? 'true' : 'false';
}
}
I want to define a variable 'on the fly' inside 'someFunction', but I can't seem to figure out how to do this inside function scope.
$classInstance = new MyClass();
$varName = 'dynamicVariable';
$classInstance->$varName;
What I want to do:
$classInstance = new MyClass();
$varName = 'dynamicVariable';
$classInstance->functionScopeReference->$varName;
$classInstance->myFunction(); <-- this will print TRUE
How can do the same thing, but define it in someFunction scope, instead of MyClass scope? Thanks
Posting as a community wiki in order to satisfy the OP, since dbf hasn't posted the comment to close the question.
"Short answer, you can't from outside of the methods scope, unless the variable is a property used inside any method. – dbf"
...
"#dbf thank you! you can post this comment as an answer and I will mark it – 0x29a"
By using the $this keyword... I would suggest a good 101 course on object oriented programming which should explain scope better then I could...
class MyClass
{
public function someFunction($foo)
{
$this->dynamicVariable = $foo;
}
}
$classInstance = new MyClass();
$classInstance->someFunction('dynamicVariable');
echo $classInstance->dynamicVariable;
EDIT: to better answer OP's question (sorry for not reading that correctly!): although it does not change scope, a workaround would be to use getters and setters and make your properties private:
class MyClass
{
private $property_one; // can't access this without using the getPropertyOne function
private $property_two;
public function setPropertyOne($bool)
{
$this->property_one = $bool;
}
public function getPropertyOne()
{
return $this->property_one;
}
public function setPropertyTwo($bool)
{
$this->property_two = $bool;
}
public function getPropertyTwo()
{
return $this->property_two;
}
}
$classInstance = new MyClass();
// trying to access the properties without using the functions results in an error
echo $classInstance->property_one;
$classInstance->setPropertyOne(true);
echo $classInstance->getPropertyOne();
$classInstance->setPropertyTwo(false);
echo $classInstance->getPropertyTwo();

Modify the class property inside the class function

I got the code from php.net website:
<?php
class foo {
public $foo;
public $bar;
public function foo() {
$this->foo = 'Foo';
$this->bar = array('Bar1', 'Bar2', 'Bar3');
}
}
$foo = new foo();
echo <<<EOT
I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
EOT;
?>
But I'm confused, what is every "foo" stand for? Can you really modify the properties(variables) inside a method(function) without calling the function?
I write a similar code but nothing happened
<?php
class page {
public $meta;
public $buttons;
public function show_meta() {
$this->meta = "I'm a website";
$this->buttons = array(
"home" => "index.php",
"about" => "about.php"
);
}
}
$index = new page();
echo $index->meta;
echo $index->buttons["home"];
?>
I'm a php learner, I need your help please :)
function foo is a PHP4-style constructor (note that the function has the same name as the class). In PHP5 you would write function __construct() instead.
new foo() actually calls the constructor, initilizing your variables.
On the first, yes, because your properties are public.
On the second case, you have reference with a string to remove the warning.
$index->buttons["home"];
You never call show_meta so the array is never populated.
this is the old php syntax for constructor methods. Constructors are Special methods, which are called, whenever a new object from the class is created. The new naming convention for constructors say, all constructors are named __construct.
To get the code above to work, you have to call show_meta, before accessing the two vars or make show_meta the constructor.
$index = new page();
$index->show_meta();
echo $index->meta;
echo $index->buttons["home"];
btw.. home is a string and should be inside "", or you raise at least a warning.

PHP - passing variables to classes

I trying to learn OOP and I've made this class
class boo{
function boo(&another_class, $some_normal_variable){
$some_normal_variable = $another_class->do_something();
}
function do_stuff(){
// how can I access '$another_class' and '$some_normal_variable' here?
return $another_class->get($some_normal_variable);
}
}
and I call this somewhere inside the another_class class like
$bla = new boo($bla, $foo);
echo $bla->do_stuff();
But I don't know how to access $bla, $foo inside the do_stuff function
<?php
class Boo
{
private $bar;
public function setBar( $value )
{
$this->bar = $value;
}
public function getValue()
{
return $this->bar;
}
}
$x = new Boo();
$x->setBar( 15 );
print 'Value of bar: ' . $x->getValue() . PHP_EOL;
Please don't pass by reference in PHP 5, there is no need for it and I've read it's actually slower.
I declared the variable in the class, though you don't have to do that.
Ok, first off, use the newer style constructor __construct instead of a method with the class name.
class boo{
public function __construct($another_class, $some_normal_variable){
Second, to answer your specific question, you need to use member variables/properties:
class boo {
protected $another_class = null;
protected $some_normal_variable = null;
public function __construct($another_class, $some_normal_variable){
$this->another_class = $another_class;
$this->some_normal_variable = $some_normal_variable;
}
function do_stuff(){
return $this->another_class->get($this->some_normal_variable);
}
}
Now, note that for member variables, inside of the class we reference them by prefixing them with $this->. That's because the property is bound to this instance of the class. That's what you're looking for...
In PHP, constructors and destructors are written with special names (__construct() and __destruct(), respectively). Access instance variables using $this->. Here's a rewrite of your class to use this:
class boo{
function __construct(&another_class, $some_normal_variable){
$this->another_class = $another_class;
$this->some_normal_variable = $another_class->do_something();
}
function do_stuff(){
// how can I access '$another_class' and '$some_normal_variable' here?
return $this->another_class->get($this->some_normal_variable);
}
}
You need to capture the values in the class using $this:
$this->foo = $some_normal_variable

Variable scope problem with super object

I'm having some trouble creating a "super object" (similar to that of CodeIgniter) for a framework project I'm working on.
I want to make a super object that all of my other classes will run through. I did that, but it seems I am unable to use my super object's object in each of my classes without using the global keyword in every function.
I have something like this:
class a
{
function aa()
{
return 'class a';
}
}
class b
{
function bb()
{
$blah->a->aa();
}
}
class superobj
{
function loadClass($class)
{
$this->$class = new $class;
}
}
class blah extends superobj
{
function __construct()
{
$this->loadClass('a');
$this->loadClass('b');
}
}
$blah = new $blah;
So if I run this, I get an error because I can't access the aa method. If I put global $blah into the method bb, then it works (or at least in my real project it does, I dunno about this 5 second mockup hehe).
So is there any way to either make the $blah object global so that I don't need to reference it for every method, OR is there a better way to achieve what I am trying to do?
I'm not very good at OOP...
function bb() {
$blah->a->aa();
}
Indeed, as with any function, this function has no variables in its scope. $blah was neither passed to the function nor is it defined in the function, so it doesn't exist.
If your objects depend on an instance of blah to work, you should pass it to the constructor.
class b {
var $blah = null;
function __construct($blah) {
$this->blah = $blah;
}
function bb() {
$this->blah->foo();
}
}
$b = new b($instanceOfBlah);
Alternatively, use a static class that holds references to global objects and returns them on request (Registry pattern, like $blah = Registry::get('blah')).
Don't use global. Just don't.

Dynamically creating instance variables in PHP classes

I'm not sure if this is a trivial questions but in a PHP class:
MyClass:
class MyClass {
public $var1;
public $var2;
constructor() { ... }
public method1 () {
// Dynamically create an instance variable
$this->var3 = "test"; // Public....?
}
}
Main:
$test = new MyClass();
$test->method1();
echo $test->var3; // Would return "test"
Does this work?? How would I get this to work? Ps. I wrote this quickly so please disregard any errors I made with setting up the class or calling methods!
EDIT
What about making these instance variables that I create private??
EDIT 2
Thanks all for responding - Everyone is right - I should have just tested it out myself, but I had an exam the next morning and had this thought while studying that I wanted to check to see if it worked. People keep suggesting that its bad OOP - maybe but it does allow for some elegant code. Let me explain it a bit and see if you still think so. Here's what I came up with:
//PHP User Model:
class User {
constructor() { ... }
public static find($uid) {
$db->connect(); // Connect to the database
$sql = "SELECT STATEMENT ...WHERE id=$uid LIMIT 1;";
$result = $db->query($sql); // Returns an associative array
$user = new User();
foreach ($result as $key=>$value)
$user->$$key = $value; //Creates a public variable of the key and sets it to value
$db->disconnect();
}
}
//PHP Controller:
function findUser($id) {
$User = User::find($id);
echo $User->name;
echo $User->phone;
//etc...
}
I could have just put it in an associative array but I can never correctly name that array something meaningful (ie. $user->data['name'] ... ugly.) Either way you have to know what is in the database so I do not really understand what the argument is that its confusing, especially since you can just var dump objects for debugging.
Why dont you just write the code and see for yourself?
<?php
class Foo
{
public function __construct()
{
$this->bar = 'baz';
}
}
$foo = new Foo;
echo $foo->bar; // outputs 'baz'
and
var_dump($foo);
gives
object(Foo)#1 (1) {
["bar"] => string(3) "baz"
}
but
$r = new ReflectionObject($foo);
$p = $r->getProperty('bar');
var_dump($p->isPublic());
will throw an Exception about 'bar' being unknown, while
$r = new ReflectionObject($foo);
$p = $r->getProperties();
var_dump($p[0]->isPublic());
will return true.
Now, should you do this type of assignment? Answer is no. This is not good OOP design. Remember, OOP is about encapsulation. So, if bar is describing some public property of the class, make it explicit and declare it in your class as public $bar. If it is supposed to be private declare it as private $bar. Better yet, dont use public properties at all and make them protected and provide access to them only through getters and setters. That will make the interface much more clearer and cleaner as it conveys what interaction is supposed to be possible with an object instance.
Assigning properties on the fly here and there across your code, will make maintaining your code a nightmare. Just imagine somewhere along the lifecylce of Foo someone does this:
$foo = new Foo;
$foo->monkey = 'ugh';
echo $foo->monkey; // outputs 'ugh'
Now, from looking at the class definition above, there is absolutely no way, a developer can see there is now a monkey patched into Foo. This will make debugging a pain, especially if code like this is frequent and distributed across multiple files.
Yes that will indeed work. Auto-created instance variables are given public visibility.
yes that works as you'd hope/expect.
I you wanted to make private variables on the fly you could use php magic functions to emulate this, e.g
MyClass
<?php
class MyClass {
public $var1;
public $var2;
private $data = array();
public function __get($key) {
// for clarity you could throw an exception if isset($this->data[$key])
// returns false as it is entirely possible for null to be a valid return value
return isset($this->data[$key]) ? return $this->data[$key] : null;
}
public function __set($key, $value) {
$this->data[$key] = $value;
}
}
?>
Main
<?php
$test = new MyClass();
$test->myVar = 'myVar is technically private, i suppose';
echo $this->myVar; // 'myVar is technically private
?>
Although these dynamically created variables are technically private, they are infact publicly accessible... i cannot image the purpose for wanting to dynamically create private instance variables. I would question your design.
Did you try it?
It is possible but you might get strict errors. If you dynamically need to create these variables, you are probably doing something wrong.
You should either change this into a function:
function var($no) { .. }
or use __get (http://ca.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members)

Categories