I have class
class User extends BaseModel{
public $id;
public $name;
}
class BaseModel{
function __construct($data=null){
if($data!=null)
//set $id and $name
}
}
I would like to set $id , $name and any other data that extends BaseModel by calling
$test = new User(array('id'=>1,'name'=>'user name'))
I tried to use
$this->__set($arrayKey,$arrayValue);
But i got error : Fatal error: Call to undefined method User::__set()
What am I doing wrong?
Thank you for any help.
Just loop through the data and assign each property:
class BaseModel {
function __construct($data = NULL) {
foreach ((array) $data as $k => $v) {
$this->$k = $v;
}
}
}
The reason you got the error about __set() not being defined is because you didn't define it. Although __set() is a magic method, you do still have to define it's behavior if you want to do something with it.
http://www.php.net/manual/en/language.oop5.overloading.php#object.set
__set is run when writing data to inaccessible properties
This means if you try to "set" a class variable in a scope you're not allowed to (like a private or protected variable), this function will run.
class Test {
private $var;
}
$c = new Test;
$c->var = 1; // Error, or call __set if defined
foreach ($data as $key => $value) {
$this->$key = $value;
}
Try this
class BaseModel{
function __construct($data=null){
if($data!=null)
{
//set $id and $name
$this->id = $data['id'];
$this->name = $data['name'];
}
}
}
Related
I wanna get variable from out of class.
Example,
config.php
$config['function'] = array('filter_validate','form');
controller.php
class Controller{
public function __construct()
{
foreach ($config['function'] as $key => $function_class) {
$function_class = new $function_class();
}
}
}
But, I can't get $config['function'] variable in Controller. How can do that?
Solution #1 (with parameter):
class Controller {
public function __construct($config) {
foreach ($config['function'] as $key => $function_class) {
$function_class = new $function_class();
}
}
}
Solution #2 (with global - NOT recommended):
class Controller {
public function __construct() {
global $config;
foreach ($config['function'] as $key => $function_class) {
$function_class = new $function_class();
}
}
}
You need to pass config to the constructor, like this:
class Controller{
public function __construct($config)
{
foreach ($config['function'] as $key => $function_class) {
$function_class = new $function_class();
}
}
}
$config['function'] = array('filter_validate','form');
$controller = new Controller($config);
functions outside any class are global an can be called from anywhere. The same with variables.. just remember to use the global for the variables.
<?php
function abc() { }
$foo = 'bar';
class SomeClass {
public function tada(){
global $foo;
abc();
echo 'foo and '.$foo;
}
}
?>
There are many ways, the most modern right now is with a fluent, getter / setter. one one of many examples, not tested:
public function config(array|string $arg, array|string $default)
{
// assume lonley arg is a getter
if(is_string($arg)) return $this->variableBag[$arg];
// assume arg is a setter when array
if(is_array($arg)) return $this->variableBag[$arg[0]??$arg['key'] = ?? $arg['1'] ?? $arg['value'];
// else assume if second is set a default val
return isset($this->variableBag[$default]) ?$this->variableBag[$default] : $default
}
```
I want to declare a variable inside a class with an unknown name
class Example {
function newVar($name, $value) {
$this->$name = $value;
}
}
And I want to use it that way
$c = new Example();
$c->newVar('MyVariableName', "This is my Value");
echo($c->MyVariableName);
The Important thing is, that I do not know the name of the variable. So I cannot put a public $MyVariable inside the class.
Is that in anyway possible? and if yes, can i do this with different scopes (private, protected, public) ?
U should use magic methods __get and __set (example without checking):
class Example {
private $data = [];
function newVar($name, $value) {
$this->data[$name] = $value;
}
public function __get($property) {
return $this->data[$property];
}
public function __set($property, $value) {
$this->data[$property] = $value;
}
}
$c = new Example();
$c->newVar('MyVariableName', "This is my Value");
echo($c->MyVariableName);
// This is my Value
$c->MyVariableName = "New value";
echo($c->MyVariableName);
// New value
See http://php.net/manual/en/language.oop5.magic.php
If i am understanding this correctly you can tweak a little bit by using key value array
class Example {
private $temp;
function __construct(){
$this->temp = array();
}
function newVar($name, $value) {
$this->temp[$name] = $value;
}
function getVar($name){
return $this->temp[$name];
}
}
$c = new Example();
$c->newVar('MyVariableName', "This is my Value");
echo($c->getVar('MyVariableName'));
Instead of using private you can use protected as well.
Your looking for magic calling. In PHP you can use the __call() function to do stuff like that. Have a look here: http://www.garfieldtech.com/blog/magical-php-call
Off the top of my head, something like
function __call($vari, $args){
if(isset($this->$vari){
$return = $this->$vari;
}else{
$return = "Nothing set with that name";
}
}
This will also work for private, protected and public. Can also use it to call methods as required in a class
I have something like this:
class MyParent {
protected static $object;
protected static $db_fields;
public function delete() {
// delete stuff
}
public static function find_by_id($id = 0) {
global $database;
$result_array = self::find_by_sql("SELECT * FROM " . static::$table_name . " WHERE id=" . $database -> escape_value($id) . " LIMIT 1");
return !empty($result_array) ? array_shift($result_array) : false;
}
public static function find_by_sql($sql = "") {
global $database;
// Do Query
$result_set = $database -> query($sql);
// Get Results
$object_array = array();
while ($row = $database -> fetch_array($result_set)) {
$object_array[] = self::instantiate($row);
}
return $object_array;
}
private static function instantiate($record) {
$object = self::$object;
foreach ($record as $attribute => $value) {
if (self::has_attribute($attribute)) {
$object -> $attribute = $value;
}
}
return $object;
}
}
class TheChild extends MyParent {
protected static $db_fields = array('id', 'name');
protected static $table_name = "my_table";
function __construct() {
self::$object = new TheChild;
}
}
$child= TheChild::find_by_id($_GET['id']);
$child->delete();
I get this: Call to undefined method stdClass::delete() referring to the last line above. What step am I missing for proper inheritance?
You never actually instanciate the TheChild class, which should be done by
$var = new TheChild();
except in TheChild constructor itself.
So, the static $object field is never affected (at least in your example), so affecting a field to it (the line $object -> $attribute = $value; ) causes the creation of an stdClass object, as demonstrated in this interactive PHP shell session:
php > class Z { public static $object; }
php > Z::$object->toto = 5;
PHP Warning: Creating default object from empty value in php shell code on line 1
php > var_dump(Z::$object);
object(stdClass)#1 (1) {
["toto"]=>
int(5)
}
This object does not have a delete method.
And as said before, actually creating a TheChild instance will result in an infinite recursion.
What you want to do is this, probably:
class TheChild extends MyParent {
protected static $db_fields = array('id', 'name');
protected static $table_name = "my_table";
function __construct() {
self::$object = $this;
}
}
Edit: Your updated code shows a COMPLETE different Example:
class MyParent {
protected static $object;
public function delete() {
// delete stuff
}
}
class TheChild extends MyParent {
function __construct() {
self::$object = new TheChild;
}
}
$child = new TheChild;
$child->delete();
Calling "Child's" Constructor from within "Child's" Constructor will result in an infinite loop:
function __construct() {
self::$object = new TheChild; // will trigger __construct on the child, which in turn will create a new child, and so on.
}
Maybe - i dont know what you try to achieve - you are looking for:
function __construct() {
self::$object = new MyParent;
}
ALSO note, that the :: Notation is not just a different Version for -> - it is completely different. One is a Static access, the other is a access on an actual object instance!
I was wondering if you could get the class name and property name from a property reference in PHP?
class Test {
public static $TestProp;
}
GetDoc(& Test::$TestProp);
function GetDoc($prop) {
$className = getClassName($prop);
$propertyName = getPropertyName($prop);
}
what I'm looking for is if it is possible to create the functions getClassName and getPropertyName?
What you want is basically not possible; a property doesn't know its parent structure.
The only sane thing I could think of is to use reflection for it:
class Test
{
public static $TestProp = '123';
}
//GetDoc(& Test::$TestProp);
GetDoc('Test', 'TestProp');
function GetDoc($className, $propName)
{
$rc = new ReflectionClass($className);
$propValue = $rc->getStaticPropertyValue($propName);
}
Within the Test class you could use __CLASS__ as a convenient reference for the class name.
I have figured out the way to get this to work there is a lot of magic that goes on just to get this to work, but in my case it's worth it.
class Test {
private $props = array();
function __get($name) {
return new Property(get_called_class(), $name, $this->props[$name]);
}
function __set($name, $value) {
$props[$name] = $value;
}
}
class Property {
public $name;
public $class;
public $value;
function __construct($class, $name, $value) {
$this->name = $name;
$this->class = $class;
$this->value = $value;
}
function __toString() {
return $value.'';
}
}
function GetClassByProperty($prop) {
return $prop->class.'->'.$prop->name;
}
$t = new Test();
$t->Name = "Test";
echo GetClassByProperty($t->Name);
this example yes I know it's complex, but it does the job how I'd want it to, will print out "Test->Name" I can also get the value by saying $prop->value. If I want to compare the value to another object I can simply do this:
if($t->Name == "Test") { echo "It worked!!"; }
hope this isn't too confusing but it was a fun exploration into PHP.
Php have a build in function called get_class
I want to create properties that are set to mysql data.
class MyClass{
private $a = $r['a'];
private $b = $r['a'];
private $c = $r['c'];
}
I know this is incorrect syntax but I want you to get the idea.
I could create a method that returns a requested mysql data, but I don't want the function to be called for every single row.
You need to implement the magic method __get.
Something like:
class MyClass {
protected $_row = array();
public function __get( $name )
{
if (array_key_exists($name, $this->_row)) {
return $this->_row[$name];
}
return null;
}
public function __isset( $name )
{
return array_key_exists($name, $this->_row);
}
}
And you could used as:
$obj = new MyClass();
$obj->load(); // Or any method to load internal data
echo $obj->a . $obj->b;
Why reinvent the wheel ?
check this mysqli_result::fetch_object