I have this class :
class MyObject{
var $title = null;
var $description = null;
var $items = [];
var $metas = [];
var $image = null;
var $country = 'Belgium';
}
And this data :
$data = new MyObject();
$data->title = 'NEW ITEM';
$data->children = ['CHILD1','CHILD2'];
$data->image = 'image.gif';
$data->country = 'Belgium';
Before storing my data in my database, I would like to remove all the defaults values from the datas, and get this output:
$dataToStore = array(
'title'=>'NEW ITEM',
'children'=>['CHILD1','CHILD2'],
'image'=>'image.gif'
);
I made an attempts with
$blank = new MyObject();
$defaults = (array)$blank;
$dataToStore = array_diff((array)$data, (array)$blank);
But it doesn't work since I get an Array to string conversion.
How could I do ?
Thanks !
Try this:
class MyObject {
public $title = null;
public $description = null;
public $children = [];
public $metas = [];
public $image = null;
public $country = 'Belgium';
protected $default = [];
function getDefault()
{
$reflect = new ReflectionClass(__CLASS__);
$vars = $reflect->getProperties(ReflectionProperty::IS_PUBLIC);
$default = [];
foreach ($vars as $privateVar) {
$default[$privateVar->getName()] = $this->{$privateVar->getName()};
}
return $default;
}
}
$data = new MyObject();
$one = $data->getDefault();
$data->title = 'NEW ITEM';
$data->children = ['CHILD1','CHILD2'];
$data->image = 'image.gif';
$data->country = 'Belgium';
$two = $data->getDefault();
echo '<pre>';
print_r($one);
print_r($two);
$output = [];
foreach($one as $key => $value){
if($value != $two[$key]){
$output[$key] = $two[$key];
}
}
print_r($output);
We get default values and set in $one
After set new data, we get default values and set in $two
Then, we check which key is not changed
First of all. Imagine that you use this class everytime you want to create a Movie entry. (I put this example because your class is very general).
class Movie{
var $title = null;
var $description = null;
var $items = [];
var $metas = [];
var $image = null;
var $country = 'Belgium';
}
Every time you want to create a new Movie record, for database or any other thing (how well have you done before).
You can create a new object.
$movie1 = new Movie();
$movie1->title = 'NEW ITEM';
$movie1->children = ['CHILD1','CHILD2'];
$movie1->image = 'image.gif';
$movie1->country = 'Belgium';
And then, if you need another one, you just have to instantiate a new object (which by default are already initialized; that's what class constructors are for) Well, we don't have a constructor here yet, but now we'll add it later
$movie1 = new Movie();
$movie1->title = 'Another title';
$movie1->items = ['SOME','ITEMS'];
$movie1->metas = ['SOME', 'METAS'];
$movie1->image = 'image.gif';
$movie1->country = 'Belgium';
$movie1->description = "Some description";
// tehere is no need for emtpy
$movie2 = new Movie();
$movie2->title = 'Title movie 2';
$movie2->items = ['SOME','ITEMS', 'MOVIE2'];
$movie2->metas = ['SOME', 'METAS', 'MOVIE"'];
$movie2->image = 'image2.gif';
$movie2->country = 'France';
$movie1->description = "Another description";
$movie1 and $movie2 now are different objects with different data.
But let's make it even better:
<?php
class Movie{
var $title;
var $description;
var $items;
var $metas;
var $image;
var $country;
function __construct($title, $description, $items, $metas, $image, $country) {
$this->title = $title;
$this->description = $description;
$this->items = $items;
$this->metas = $metas;
$this->image = $image;
$this->country = $country;
}
function GetClassVars() {
return array_keys(get_class_vars(get_class($this)));
}
}
$movie1 = new Movie("Ttile one",
"the description",
['SOME','ITEMS'],
['SOME', 'METAS'],
"image.gif",
"Belgium");
$movie2 = new Movie("Ttile two",
"the description of two",
['SOME','ITEMS', 'MORE'],
['SOME', 'METAS', 'AND MORE'],
"image2.gif",
"France");
PrintMovie($movie1);
PrintMovie($movie2);
function PrintMovie($object){
echo "#############################";
$class_vars = $object->GetClassVars();
foreach ($class_vars as $nombre) {
$val = $object->{$nombre};
if(gettype($val) == "array"){
foreach($val as $v){
echo "<pre>";
echo "\t$nombre ->";
echo " " .$v;
echo "</pre>";
}
}
else{
echo "<pre>";
echo "$nombre -> $val";
echo "</pre>";
}
}
echo "#############################\n";
}
As you are seeing in the example. I am creating two different movies (without having to delete the data each time; the constructor takes care of that, to initialize the data each time)
You also have an array with all the names of the properties of the class. In order to iterate over them and print them on the screen. You could even modify its value, since, like the PrintMovie function (it could also be called GetMovieData, if we wanted to modify it instead of printing the value)
The result of
PrintMovie($movie1);
PrintMovie($movie2);
is:
#############################
title -> Ttile one
description -> the description
items -> SOME
items -> ITEMS
metas -> SOME
metas -> METAS
image -> image.gif
country -> Belgium
############################# #############################
title -> Ttile two
description -> the description of two
items -> SOME
items -> ITEMS
items -> MORE
metas -> SOME
metas -> METAS
metas -> AND MORE
image -> image2.gif
country -> France
#############################
As you can see we have not had to delete anything and we have all the names of the properties in an array, to access them dynamically (as long as we have the object). That's why we pass it to the PrintMovie function
We could have put the print function inside the class, but I think it is also understood that way. In any case, I have invented the example so that you understand that with object-oriented programming, each object is different, therefore you do not have to delete anything to reuse it. You simply create a new object.
Related
I want to announce the variable whose name is introduced during execution
class db_handler {
function appendCol(){
// get name col
// get value
}
}
$colname = $_POST("col");
$db = new db_handler();
$db->appendCols()->$colname = "Value";
like this xbase/dbf
example from this lib :
$table = new WritableTable($dbf_file);
$table->openWrite();
$record = $table->appendRecord();
foreach ($fields as $field => $val ) {
$record->$field = $val;
}
$table->writeRecord();
$table->close();
Is it possible to do such a thing?
I've written code that reads data from a cURL source which then processes it to extract records of data.
Each record becomes an instance of an object with several variables set from the data. A function extracts all the data and returns an array of objects.
The problem is that all of the objects have the same value which is the last record to be read from the source data.
After some testing I realize this is a reference problem. Data is read from the source and then assigned to an object which is then added to the array. The same object is reused in a loop that cycles through all the records in the source. Whenever this object is updated all previous values in the objects in the array are also reset to the newest value as they continue to reference the object when it is updated.
How can I make all the values independent?
function get_object_array () {
//reads raw data from cRUL source, returns array of objects
//array to hold objects
obj_arr = [];
//raw data has been split into array called $record, one element for each object
//loops through $record array
foreach ($record as $rec) {
//splits $rec into array of data called $data
//creates new object, but problem here as this object
//is being referenced by all values so last value
//changes all previous objects in array
$obj = new SaleItem();
//populates object with record data array
$obj->set_data($data);
//add object to array
$obj_arr [] = $obj;
}
return $obj_arr;
}
Update: Here is the function to set the data:
function set_data (array $arr) {
global $order_num, $name, $price, $cprice, $cheapest, $category;
try {
$order_num = (int)$arr[0];
$name = $arr[1];
$price = (float)$arr[2];
$cprice = (float)$arr[3];
$cheapest = $this->$price <= $this->$cprice ? true : false;
$category = $arr[5];
return true;
}
catch (Exception $ex) {
echo $ex;
return false;
}
}
Update: Full class code:
class SaleItem {
public $order_num = 12;
public $name = "";
public $price = 3.4;
public $cprice = 5.6;
public $cheapest = true;
public $category = "No Category";
function set_data (array $arr) {
try {
$this->order_num = (int)$arr[0];
$this->name = $arr[1];
$this->price = (float)$arr[2];
$this->cprice = (float)$arr[3];
$this->cheapest = $price <= $cprice ? true : false;
$this->category = $arr[5];
return true;
}
catch (Exception $ex) {
echo $ex;
return false;
}
}
function get_data () {
echo $this->order_num . ' num<br/>';
echo $this->name . ' name<br/>';
echo $this->price . ' price<br/>';
echo $this->cprice . ' cprice<br/>';
echo $this->cheapest . ' cheapest<br/>';
echo $this->category . ' category<br/>';
echo '<br/>';
}
}//end SaleItem class
You are using global variables instead of members. Remove
global $order_num, $name, $price, $cprice, $cheapest, $category;
From the function and preface each assignment with $this->
$this->order_num = (int)$arr[0];
$this->name = $arr[1];
$this->price = (float)$arr[2];
$this->cprice = (float)$arr[3];
$this->cheapest = $this->price <= $this->cprice;
$this->category = $arr[5];
i have this code below:
<?php
class Product {
public $name;
public $desc;
public $price;
public $category;
public $qty;
public $model;
public $manufacturer;
function display() {
$output = '';
$output .= $this->name ."</br>";
$output .= $this->desc . "</br>";
$output .= $this->price "</br>";
$output .= $this->category "</br>";
$output .= $this->qty "</br>";
$output .= $this->model "</br>";
$output .= $this->manufacturer "</br>";
return $output;
}
}
$product = new Product();
$product->name = "Samsung galaxy s6";
$product->desc = "It's kind of good but meh";
$product->price = "1000 GBP";
$product->category = "Phones";
$product->qty = "Quantity:999";
$product->model = "Samsung s6";
$product->manufacturer = "Phone guys";
echo $product->display();
?>
So this function works without a problem by itself when i set the values in:
$product->name = "Samsung galaxy s6";
$product->desc = "It's kind of good but meh";
$product->price = "1000 GBP";
$product->category = "Phones";
$product->qty = "Quantity:999";
$product->model = "Samsung s6";
$product->manufacturer = "Phone guys";
So when i set all the values everything works,but my question is: Is it possible for me to make each one of those an array lets say i want to display 2 products in the browser
When I set the $product->name to $product->name = array("Samsubg","Iphone","Apple");
This by itself displays only **Apple* and i kind of get lost here on what to do
Thanks.
You normally would use a setter method to set variables and it would look like this if you wanted to set it as an array.
private name = array();
public function setName($name) {
$this->name[] = $name;
}
You would want to do this with all your variables. If you wanted to pass in an array you could loop through it and pass one at a time or pass the whole array you would want to set your setter function like this:
private name = array();
public function setName($name) {
$this->name = $name;
}
You could then set it by calling the method and passing in the array.
$product->setName($myArrayOfNames);
With OOP, it doesn't make sense to have a single object with fields that are arrays. That is just procedural programming in an object.
Instead, the fields of each object should describe the state of only the object itself. If you need an array to describe multiple products, then you simply make an array of the Product object.
$products = array();
$product_one = new Product();
$product_one->name = "Samsung galaxy s6";
$product_one->desc = "It's kind of good but meh";
$product_one->price = "1000 GBP";
$product_one->category = "Phones";
$product_one->qty = "Quantity:999";
$product_one->model = "Samsung s6";
$product_one->manufacturer = "Phone guys";
$product_two = new Product();
$product_two->name = "iPhone6";
$product_two->desc = "who knows";
$product_two->price = "10000 GBP";
$product_two->category = "Phones";
$product_two->qty = "Quantity: 1";
$product_two->model = "iPhone";
$product_two->manufacturer = "Apple";
$products[] = $product_one;
$products[] = $product_two;
foreach($products as $product) {
echo $product->display();
}
Define your array property in the class, here is a full working example.
class Body
{
private $name = array();
public function setName($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
}
$user = new Body();
$user->setName(array("Samsubg","Iphone","Apple"));
echo var_dump($user->getName()); This will dump an array, all you have to do is do a for loop over it or get the array values by index: $user->getName[0].
Let's say I have an array of objects.
<?php
$people = array();
$people[] = new person('Walter Cook');
$people[] = new person('Amy Green');
$people[] = new person('Irene Smith');
How can I search an object in this array for a certain instance variable? For example, let's say I wanted to search for a person object with the name of "Walter Cook".
Thanks in advance!
It depends of the person class construction, but if it has a field name that keeps given names, you can get this object with a loop like this:
for($i = 0; $i < count($people); $i++) {
if($people[$i]->name == $search_name) {
$person = $people[$i];
break;
}
}
Here is:
$requiredPerson = null;
for($i=0;$i<sizeof($people);$i++)
{
if($people[$i]->name == "Walter Cook")
{
$requiredPerson = $people[$i];
break;
}
}
if($requiredPerson == null)
{
//no person found with required property
}else{
//person found :)
}
?>
Assuming that name is a public property of the person class:
<?php
// build the array of objects
$people = array();
$people[] = new person('Walter Cook');
$people[] = new person('Amy Green');
$people[] = new person('Irene Smith');
// search name
$searchName = 'Walter Cook';
// ascertain the presence of the name in the array of objects
$isMatch = false;
foreach ($people as $person) {
if ($person->name === $searchName) {
$isMatch = true;
break;
}
}
// alternatively, if you want to return all matches into
// a new array of $results you can use array_filter
$result = array_filter($people, function($person) use ($searchName) {
return $person->name === $searchName;
});
hope this helps :)
well you could try this inside your class
//the search function
function search_array($array, $attr_name, $attr_value) {
foreach ($array as $element) {
if ($element -> $attr_name == $attr_value) {
return TRUE;
}
}
return FALSE;
}
//this function will test the output of the search_array function
function test_Search_array() {
$person1 = new stdClass();
$person1 -> name = 'John';
$person1 -> age = 21;
$person2 = new stdClass();
$person2 -> name = 'Smith';
$person2 -> age = 22;
$test = array($person1, $person2);
//upper/lower case should be the same
$result = $this -> search_array($test, 'name', 'John');
echo json_encode($result);
}
Im .NET programmer, but totally new in PHP. Im fighting with this for hours.
I need to simplyfy data transfer from interface to database. I have something like this:
$default = new stdClass();
// default values - all of them should be set to default value
// some of them will be overwritten later, but only one of them
$default->{'val-string'} = ''; // default values start
$default->{'val-int'} = 0;
$default->{'val-float'} = 0;
$default->{'val-image'} = ' ';
$default->{'val-datetime'} = 0;
$default->{'val-boolean'} = false; // default values end
$container = array();
$row = clone $default;
$row->{'field_id'} = 1;
$row->{'field_name'} = $nameoffield1;
$row->{'val-string'} = 'Diffrent types are filled for diffrent rows';
$container[] = $row;
$row = clone $default;
$row->{'field_id'} = 2;
$row->{'field_name'} = $nameoffield2;
$row->{'val-int'} = $valueoffield2;
$container[] = $row;
$row = clone $default;
$row->{'field_id'} = 3;
$row->{'field_name'} = $nameoffield3;
$row->{'val-datetime'} = current_time();
$container[] = $row;
// there
// is
// a lot
// of these
//rows
$result = $database->insertContainer($db_session, $container);
At the end need something like that "pseudocode .NET mixed with php"
list_of_rows.AddItem(makeRow($field_id1, $name1, (int)$dataforint)));
list_of_rows.AddItem(makeRow($field_id2, $name2, (string)$dataforstring));
list_of_rows.AddItem(makeRow($field_id3, $name3, (date)$datafordate));
list_of_rows.AddItem(makeRow($field_id4, $name4, (boolean)$dataforboolean));
$result = $database->insertContainer($db_session, list_of_rows);
If overloading like this is not possible (or very complicated) in PHP - i will be happy if someone give me any better solution than mine code at the top.
This a possible approach. You can also use the __call method to achieve this. This is just a quick example. Either this, or you might use an ORM like propel to achieve something similair. It really depends on what the task is.
class Row_Builder {
protected $default = array();
public function __construct() {
$this->default['field_id'] = null;
$this->default['field_name'] = null;
$this->default['val-string'] = null;
$this->default['val-int'] = null;
$this->default['val-float'] = null;
$this->default['val-image'] = null;
$this->default['val-datetime'] = null;
$this->default['val-boolean'] = false;
return;
}
public function setValues() {
// we only need the fist argument in this case.
$params= func_get_arg(0);
if(isset($params)) {
foreach($params as $key => $value) {
if(array_key_exists($key,$this->default)) {
$this->default[$key] = $value;
}
}
}
}
public function __get($key) {
if(array_key_exists($key, $this->default)) {
return $this->default[$key];
}
}
}
$row = new Row_Builder;
$row->setValues(array('field_id' => 1, 'field_name' => 'some value', 'val-string' => 'here is a str value'));
print $row->field_name;