class Car {
function __construct() {
// echo 'car con';
}
function setInfo($car_arr) {
foreach ($car_arr as $key => $value) {
$this->{$key} = $value;
}
}
}
i try to access like bellow
$car1 = new Car();
$car1->setInfo('make', 'Toyota')->setInfo('model', 'scp10');
that gave to me bellow error
Call to a member function setInfo() on a non-object
how can i change setInfo() method call $car1->setInfo('make', 'Toyota')->setInfo('model', 'scp10'); after that car class set $make = 'Toyota', like that
how can i print this object like
bellow
make = Toyota
model = scp10
You need to add return $this; in the end of your method for chain-like calls.
change the setInfo code to return itself like:
function setInfo($car_arr,$car_val=null) {
if(is_array($car_arr)){
foreach ($car_arr as $key => $value) {
$this->{$key} = $value;
}
}else if(is_string($car_arr) && $car_val != null){
$this->{$car_arr} = $car_val;
}
return $this;
}
now you can chain the functions because its returning itself.
also if you want to call it like you want ( like $this->setInfo("make","Ford")) you need to add an else on is_array and add an optional parameter like shown in the code above
To combine all answers into one (well, except #EaterOfCorpses):
<?php
class Car {
private $data = array();
function setInfo(array $carInfo) {
foreach ($carInfo as $k => $v) {
$this->data[$k] = $v;
}
return $this;
}
function __set($key, $val) {
$this->data[$key] = $val;
}
function __get($key) {
return $this->data[$key];
}
}
$car = new Car();
$car->setInfo(['make' => 'Toyota', 'warranty' => '5 years']);
Note that there's no reason to return $this if you are setting all the properties at once.
Edited to add: also include magic getter/setter idea from Mark Baker just for the fun of it.
You should use $car1->setInfo('make', 'Toyota') only once. That's because you create a car, then set info, and then you want to set info to info, but you can't set info to info.
It's called a fluent interface
Add
return $this;
as the last line of your setInfo() method
Use array syntax: $car1->setInfo(array('make', 'Toyota'))
You can return $this in your function (if you have php 5.4):
function setInfo($car_arr) {
...
return $this;
}
Related
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
So I am building a helper class that would store all get variables from a url, remove trailing spaces and return it so that other methods can use them.
The problem is that only the first value gets stored.
The url looks like:
https://pay.paymentgateway.com/index.php?name=xyz&amount=10.30&checksum=abcd
My code outputs:
Array
(
[name] => xyz
)
My code:
class helperboy
{
protected $cleanvariables = array();
public function store_get_variables($_GET)
{
foreach ($_GET as $key => $value)
{
return $this->cleanvalues[$key] = trim($value);
}
}
protected function display_variables()
{
echo "<pre>";
print_r($this->cleanvalues);
}
}
I know I am doing something silly and I would appreciate any help.
Also, how can I access specific variables like this in my other methods.:
$this->cleanvalues['name'];
$this->cleanvalues['amount'];
$this->cleanvalues['checksum'];
your return statement is the problem....
class helperboy
{
protected $cleanvariables = array();
public function store_get_variables($_GET)
{
foreach ($_GET as $key => $value)
{
$this->cleanvalues[$key] = trim($value);
}
return $this->cleanvalues;
}
protected function display_variables()
{
echo "<pre>";
print_r($this->cleanvalues);
}
}
Well, the problem is that...
public function store_get_variables($_GET)
{
foreach ($_GET as $key => $value)
{
return $this->cleanvalues[$key] = trim($value);
}
}
... the loop here will be executed just once. As soon as function hits return statement, it will abort this loop - and return immediately.
Yet I think there are some bigger problems here. First, I don't buy the idea of some omnipotent helper class that knows everything about everyone. If you intend to work with some cleaner request params, why don't just 'objectize' this instead:
class My_Http_Request
{
private $request;
protected function fillGetParams() {
$this->request['get'] = array_map('trim', $_GET);
}
public function getTrimmedParam($name) {
return $this->request['get'][$name];
}
public function __construct() {
$this->fillGetParams();
}
}
That's just an idea, not ready-made implementation (no checks for missing elements, no returning all params if 'getTrimmedParam' method is called without any arguments, etc.
I want to do a massive assignement of my protected vars, i used this code:
protected $_productName = '';
protected $_price = 0;
protected $_categoyId = 0;
public function setAttributes($attributes)
{
foreach($attributes as $key => $val)
{
$var = '_' . $key;
$this->$var = $val;
}
}
$attributes = array('productName'=>'some Product', 'price' => 10, 'categoryId' => 5) for exapmle.
the code above works for me but I feel that it's not clean. Is there any better solution to do that?
thanx.
Code is clean, nothing bad about it. You could maybe additionally see if class field exists before setting it - so you could assure you are not setting any additional fields, which are not defined in a class.
Also to make the code a little shorter, you could do:
$this->{"_{$key}"} = $val;
This is matter of taste what you like - your variant is fine as well.
What you're doing is fine. I would add a check for the property:
foreach($attributes as $key => $val)
{
$var = '_' . $key;
if (property_exists($this, $var))
{
$this->$var = $val;
}
}
Your code is pretty much as a clean as it gets for mass-assignment. There are alternatives, like using array_walk() instead of a foreach loop, but I find loops to be cleaner and easier to understand quickly in situations like these.
it looks ok to me, but if $attributes is always an array probably you should add this to avoid errors
public function setAttributes($attributes=array())
doing that you won't receive a error if attributes is empty because initialize the $attributes array
You can use Magic Methods. Assign array as property value. And for every time you call variable like $this->var invoke __get method
public function setAttributes($attributes)
{
$this->attributes = $attributes;
}
function __get($var) {
if(isset($this->attributes[$var])) return $this->attributes[$var];
return false;
}
function __set($key, $var) {
}
I also used something like the following code awhile ago as a test:
private $data = array();
public function __get($name)
{
if (array_key_exists($name, $this->data))
{
return $this->data[$name];
}
}
public function __set($name, $value)
{
$this->data[trim($name)] = trim($value);
}
I'm wondering if it's possible, and in case it is, how shoud I achive that:
$this->id <-- i have such thing. but to make it more usable i'd like to have $this->(and here to change the values)
for ex: I might have $this->id $this->allID $this->proj_id
how can I make so that actually I have $this->($myvariable here, that has a unique name in it)?
You can simply use this:
$variable = 'id';
if ( isset ( $this->{$variable} ) )
{
echo $this->{$variable};
}
Here is the solution : http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members
An example of using it is here :
class myClass {
/** Location for overloaded data. */
private $myProperties = array();
public function __set($name, $value)
{
$this->myProperties[$name] = $value;
}
public function __get($name)
{
if (array_key_exists($name, $this->myProperties))
{
return $this->data[$name];
}
}
}
You should check out the variable variables manual on the PHP site.
With that, it could look like:
<?php
echo ${'this->'.$yourvariable};
?>
I prefer to use call_user_func and pass the parameters as array instead.
public function dynamicGetterExample()
{
$property = 'name'; // as an example...
$getter = 'get'.ucfirst($property);
$value = call_user_func(array($this,$getter));
if (empty($value)) {
throw new \Exception('Required value is empty for property '.$property);
}
return $value;
}
Is there such a function like in_array, but can be used on objects?
Nope, but you can cast the object to an array and pass it into in_array().
$obj = new stdClass;
$obj->one = 1;
var_dump(in_array(1, (array) $obj)); // bool(true)
That violates all kinds of OOP principles though. See my comment on your question and Aron's answer.
First of all, arrays and objects are quite different.
A PHP object can not be iterated through like an array, by default. A way to implement object iteration is to implement the Iterator interface.
Concerning your specific question, you probably want to take a look at the ArrayAccess interface:
class obj implements ArrayAccess {
private $container = array();
public function __construct() {
$this->container = array(
"one" => 1,
"two" => 2,
"three" => 3,
);
}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->container[$offset]);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
}
public function offsetGet($offset) {
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
}
Now you can access your object like an array in the following manner:
$object = new obj();
var_dump(isset($obj['two'])); // exists!
var_dump(isset($obj['foo'])); // does not exist
Before you go crazy on this though, please consider why you are actually trying to do this and take a look at the examples at php.net.
Option 2: when you are simply trying to see if a property exists, you can use property_exists() for this:
class foo {
public $bar = 'baz';
}
$object = new foo();
var_dump(property_exists($object, 'bar')); // true
You could cast the object to an array:
$obj = new stdClass();
$obj->var = 'foobar';
in_array( 'foobar', (array)$obj ); // true
function in_object($needle, $haystack) {
return in_array($needle, get_object_vars($haystack));
}
It's unbelievable how all the people miss the point of the usefulness of an in_object PHP method! Here is what I came up with, it is very useful, and you will see why!
Here is a simple function I wrote which will check if a value can be found within an object.
<?php
// in_object method
// to check if a value in an object exists.
function in_object($value,$object) {
if (is_object($object)) {
foreach($object as $key => $item) {
if ($value==$item) return $key;
}
}
return false;
}
?>
This is very useful if an object has been created dynamically (especially from external code, which you don't control, as in an application-plugin, CMS, etc), and you don't know the object's properties.
The above function will return the property, so you will be able to use it in your code later on.
Here is a very good basic example of how useful this function is!
<?php
class My_Class {
function __construct($key, $value) {
$this->$key = $value;
// As you can see, this is a dynamic class, its properties and values can be unknown...
}
}
function in_object($value,$object) {
if (is_object($object)) {
foreach($object as $key => $item) {
if ($value==$item) return $key;
}
}
return false;
}
function manipulate_property($value,$object) {
if ($property = in_object($value,$object)) {
// value found. I can now use this property.
// I can simply echo'it (makes no sense, as I could instead simply echo "value")
echo "<br />I found the property holding this value: ".$object->$property;
// or (here comes the good part)
// change the property
$object->$property = "This is a changed value!";
echo "<br />I changed the value to: ".$object->$property;
// or return it for use in my program flow
return $property;
} else {
echo "Value NOT FOUND!<br />";
return false;
}
}
// imagine if some function creates the class conditionally...
if ( 1 == 1) {
$class = new My_Class("property","Unchanged Value");
} else {
$class = new My_Class("property","Some Other Value");
}
// now let's check if the value we want exists, and if yes, let's have some fun with it...
$property = manipulate_property("Unchanged Value",$class);
if ($property) {
$my_variable = $class->$property;
echo "<br />This is my variable now:".$my_variable;
} else $my_variable = $some_other_variable;
?>
Just run it to see for yourself!
I don't recommend it, because it's very bad practice but you can use get_object_vars.
Gets the accessible non-static properties of the given object according to scope.
There are other limitations you should refer to the documentation to see if it is suitable for you.
if(in_array('find me', get_object_vars($obj)))
This is the most efficient and correct solution. With some modifications it could be applied to check any data type present in any object.
if(gettype($object->var1->var2) == "string"){
echo "Present";
}