Missing argument 1 for Product::__construct() - php

So I have this code:
<?php
class Product
{
public $name = 'default_name';
public $price = 0;
public $desc = 'default description';
function __construct($name, $price, $desc){
$this->name = $name;
$this->price = $price;
$this->desc = $desc;
}
public function getInfo(){
return "Product Name: " . $this->name;
}
}
$p = new Product();
$shirt = new Product("Space Juice T-Shirt", 20, "Awesome Grey T-Shirt");
$soda = new Product("Space Juice Soda", 2, "Grape Flavored Thirst Mutilator");
echo $shirt->getInfo();
?>
and PHP reports "Missing argument 1 for Product::__construct()" error. I got this example in one of the leading PHP courses and I'm confused because there seems to be an error somewhere inside this simple code. Help would be much appriciated.

In your code, if you are going to create an instance of Product, passing the parameters are mandatory. Whereas, you already have the default values. So, Make it safe:
<?php
class Product
{
public $name = 'default_name';
public $price = 0;
public $desc = 'default description';
function __construct($name = null, $price = null, $desc = null){
$this->name = $name ?: $this->name;
$this->price = $price ?: $this->price;
$this->desc = $desc ?: $this->desc;
}
public function getInfo(){
return "Product Name: " . $this->name;
}
}
$p = new Product();
$shirt = new Product("Space Juice T-Shirt", 20, "Awesome Grey T-Shirt");
$soda = new Product("Space Juice Soda", 2, "Grape Flavored Thirst Mutilator");
echo $shirt->getInfo();
?>

Your construct doesn't allow nulls for your variables, and so
$p = new Product();
is causing the problem. It's expecting some value, even if it's just empty strings, for $name, $price and $desc.
If you change your construct function to this:
function __construct($name = 'default_name', $price = 0, $desc = 'default description'){
$this->name = $name;
$this->price = $price;
$this->desc = $desc;
}
then it shouldn't throw that error any more.

Related

Assign the value to the Object in php

Actually after fetching the data from the Database, i want to create a new Object and insert this object to the array but when i check the array it shows the NULL value
here is my code:
<?php
$query = "sql query";
$filter_Result = mysqli_query($con, $query);
$newOrders = Array();
while ($row = mysqli_fetch_array($filter_Result)) {
$order;
$orderId = $row['order_id']; //fetch row id
$temp = check_id($newOrders, $orderId);
if ($temp != null) {
$order = $temp;
} else {
echo " <br>";
$order = new Order($row['order_id'], $row['status'], $row['created_Date']);
$newOrders[] = $order;
}
$item = new Item($row['status'], $row['quantity']);
$order->AddItem($item, null);
}
function check_id($newOrders, $orderId) {
$length = count($newOrders);
for ($i = 0; $i < $length; $i++) {
if ($newOrders[$i]->$orderId == $orderId)
return $newOrders[$i];
}
return null;
}
foreach ($newOrders as $order) {
}
?>
You have a variable in your Order class
var $order_Id;
But then you try to assign value to $orderId which does not exist
$this->orderId = $orderId;
I would suggest turning all PHP errors on while developing. You can include this in your php code to see if you get any errors. It is very hard to see all the small errors with naked eye :) Let PHP do it for you.
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
More about error reporting here.
You have several small mistakes, e.g. using "this" incorrectly, using different name for "orderId", plus a wrong name for the constructors. The constructor name should be "Order" or "__construct", same for "Item" constructor.
class Order {
/* Member variables */
var $orderId;
var $status;
var $createdDate;
var $items = array();
function Order($orderId, $status, $createdDate)
{
$this->orderId = $orderId;
$this->status = $status;
$this->createdDate = $createdDate;
}
function AddItem($itemId,$quantity)
{
$item = new Item($itemId,$quantity);
$items[] = $item;
}
}
$c = new Order(1, 'OK', 'today');
print_r($c);
Now i found the Solution in the PHP we have to use __construct() for the creating a Constructor....
So use it __construct instead of class name for more info visit:
__construct() vs SameAsClassName() for constructor in PHP
new_order.php
<?php
class Order {
/* Member variables */
var $order_Id;
var $status;
var $createdDate;
var $items = array();
function __Order($order_Id, $status, $createdDate)
{
$this->order_Id = $order_Id;
$this->status = $status;
$this->createdDate = $createdDate;
}
function AddItem($itemId,$quantity)
{
$item = new Item($itemId,$quantity);
$items[] = $item;
}
}
class Item {
var $productId;
var $productName;
var $quantity;
var $personalization;
function __Item($productId, $quantity)
{
$this->productId = $productId;
$this->productName = $productName;
$this->quantity = $quantity;
$this->personalization = $personalization;
}
}
?>

Generate nested JSON from SQL using PHP

I'm trying to generate a JSON API using PHP to be used as remote server interface for my Android application database.
I managed to generate JSON like this:
{
products: [
{
product_name: "Samsung",
product_category: "phones",
shop_name: "Gadget Store",
user_id: "1",
price: "1999",
date: "2015-04-05",
time: "11:14:44"
},
{
product_name: "Samsung",
product_category: "phones",
shop_name: "IT Store",
user_id: "1",
price: "1899",
date: "2015-04-01",
time: "13:00:00"
},
{
product_name: "Motorola",
product_category: "phones",
shop_name: "IT Store",
user_id: "1",
price: "1499",
date: "2015-04-02",
time: "10:31:29"
}
]
}
But I guess I need a nested JSON which is something like this:
{
products: [
{
product_name: "Samsung",
product_category: "phones",
shops: [
{
shop_name: "Gadget Store",
user_id: "1",
price: "1999",
date: "2015-04-05",
time: "11:14:44"
},
{
shop_name: "IT Store",
user_id: "1",
price: "1899",
date: "2015-04-01",
time: "13:00:00"
}
],
},
{
product_name: "Motorola",
product_category: "phones",
shops: [
shop_name: "IT Store",,
user_id: "1",
price: "199",
date: "2015-04-02",,
time: "10:31:29"
],
}
]
}
How can I achive this result?
The sql query is from 3 different table.
Below is my current code:
class productDB
{
public $product_name = "";
public $product_category = "";
public $shop_name = "";
public $user_id = "";
public $price;
public $date = "";
public $time = "";
function __construct($product_name, $product_category, $shop_name, $user_id, $price, $date, $time)
{
$this->product_name = $product_name;
$this->product_category = $product_category;
$this->shop_name = $shop_name;
$this->user_id = $user_id;
$this->price = $price;
$this->date = $date;
$this->time = $time;
}
class Shop
{
public $shop_name = "";
public $user_id = "";
public $price;
public $date = "";
public $time = "";
function __construct($shop_name, $user_id, $price, $date, $time)
{
$this->shop_name = $shop_name;
$this->user_id = $user_id;
$this->price = $price;
$this->date = $date;
$this->time = $time;
}
}
class product
{
public $product_name = "";
public $product_category = "";
public $shop = "";
function __construct($product_name, $product_category, $shop_name, $user_id, $price, $date, $time)
{
$this->product_name = $product_name;
$this->product_category = $product_category;
$this->shop = new Shop($shop_name, $user_id, $price, $date, $time);
}
}
$query = "SELECT a.product_name, a.product_category,
b.shop_name,
c.user_user_id, c.price, c.date, c.time
FROM price c, item a, shop b
WHERE c.product_product_id = a.product_id AND c.shop_shop_id = b.shop_id";
$product_array = array();
if ($result = $dbc->query($query)) {
while ($obj = $result->fetch_object()) {
$temp_product[] = new ProductDB(
$obj->product_name,
$obj->product_category,
$obj->shop_name,
$obj->user_id,
$obj->price,
$obj->date,
$obj->time);
$product_array = $temp_product;
}
//Give a name to the array
$array_name = 'products';
$product_array = (array($array_name=>$product_array));
$product_object = json_encode($product_array);
echo $product_object;
Here you have a solution which does not require subqueries.
It looks like at least in this example you do not need the ProductDB so we will use directly Product class
To keep the shops in the Product object we need the holder there. We will change $shop into $shops which will hold an array with Shop objects.
Product class:
class Product
{
public $product_name = "";
public $product_category = "";
public $shops = null;
function __construct($product_name, $product_category, $shop_name, $user_id, $price, $date, $time)
{
$this->product_name = $product_name;
$this->product_category = $product_category;
$this->shops = array(new Shop($shop_name, $user_id, $price, $date, $time));
}
public function addShop($shop_name, $user_id, $price, $date, $time)
{
// because $shops is a public property we can check if it still is an array
if (!is_array($this->shops)) {
$this->shops = array();
}
$this->shops[] = new Shop($shop_name, $user_id, $price, $date, $time);
}
}
Ass you can see there is a new function which adds new shops to the array.
Now the part which will group the shops into the products.
$product_array = array();
$currProduct = null;
if ($result = $dbc->query($query)) {
while ($obj = $result->fetch_object()) {
// check if it is a first product or if we have encountered product with different name or category
if ($currProduct === null
|| $currProduct->product_name !== $obj->product_name
|| $currProduct->product_category !== $obj->product_category) {
// create new Product with one position in the shops array
$product = new Product(
$obj->product_name,
$obj->product_category,
$obj->shop_name,
$obj->user_id,
$obj->price,
$obj->date,
$obj->time);
$product_array[] = $product;
// set created product as a currently used
$currProduct = $product;
} else {
// if name and category is the same add shop data to the current product
$currProduct->addShop(
$obj->shop_name,
$obj->user_id,
$obj->price,
$obj->date,
$obj->time);
}
}
$product_array = array('products' => $product_array);
$product_json = json_encode($product_array);
echo $product_json;
}
TO group the data properly it is necessary to sort the products data. So add at the end of the query ORDER BY a.product_name, a.product_category.
That's it :) Let me know how if it worked (if you will use it)
Also if you would like to declare the class properties private and still use json_encode to get the JSON representation of your classes, you can use JsonSerializable interface.
Shop class
class Shop implements \JsonSerializable
{
private $shop_name = "";
private $user_id = "";
private $price;
private $date = "";
private $time = "";
function __construct($shop_name, $user_id, $price, $date, $time)
{
$this->shop_name = $shop_name;
$this->user_id = $user_id;
$this->price = $price;
$this->date = $date;
$this->time = $time;
}
public function JsonSerialize()
{
return get_object_vars($this);
}
}
Product class
class Product implements \JsonSerializable
{
private $product_name = "";
private $product_category = "";
private $shops = null;
function __construct($product_name, $product_category, $shop_name, $user_id, $price, $date, $time)
{
$this->product_name = $product_name;
$this->product_category = $product_category;
$this->shops = array(new Shop($shop_name, $user_id, $price, $date, $time));
}
public function addShop($shop_name, $user_id, $price, $date, $time)
{
$this->shops[] = new Shop($shop_name, $user_id, $price, $date, $time);
}
function getName()
{
return $this->product_name;
}
function getCategory()
{
return $this->product_category;
}
public function JsonSerialize()
{
return get_object_vars($this);
}
}
Main code
[...]
if ($currProduct === null
|| $currProduct->getName() !== $obj->product_name
|| $currProduct->getCategory() !== $obj->product_category) {
[...]
Have fun :)
To keep a consistent JSON structure, the second part would look like this:
{
product_name: "Motorola",
product_category: "phones",
shops: [
shop_name: "IT Store",
user_id: "1",
price: "1499",
date: "2015-04-02",
time: "10:31:29"
]
}
How about something like this:
$queryStr_products = "Select * FROM item";
$queryStr_price = "Select b.shop_name, c.user_user_id, c.price, c.date, c.time FROM price c, shop b WHERE b.shop_id = c.product_product_id and c.product_product_id =";
$product_array = array();
if ($result = $dbc->query($queryStr_products)) {
//Iterate over all products returned
while ($obj = $result->fetch_object()) {
$product_array[] = array (
'product_name' => $obj->product_name,
'product_category' => $obj->product_category,
'shops' => getPricesForProducts($obj->product_id)
);
}
$result->close();
}
echo json_encode(array('products'=>$product_array));
/**
* For clarity purposes
* This returns an array of all product prices for a particular productID
*/
function getPricesForProducts ($productID) {
//You may need to get a new DB connection
if ($result = $dbc2->query($queryStr_price.$productID)) {
$price_array = array();
while($obj = $result->fetch_object()) {
$price_array[] = array (
'shop_name' => $obj->b.shop_name,
'user_id' => $obj->c.user_user.id,
'price' => $obj->c.price,
'date' => $obj->c.date,
'time' => $obj->c.time,
);
}
$result->close();
return $price_array;
} else {
//Maybe you want to set shop_name to "No Prices Found" and user_id = 0;
return array();
}
}

Creating a PHP Class for only Known Variables

Hello Fellow Stack Over Flow members, I hope you guys can help with me something that I have been unable to figure out. I have been unable to write a class for the below code, I was hoping one of you php experts could help
$obj = new ClassName ();
$obj->setName ('Name of Something');
$obj->price = 500.00;
$obj ['address_primary'] = 'First Line of Address';
$obj->address_secondary = 'Second Line of Address';
$obj->city = 'the city';
$obj->state = 'ST';
$obj->setZip (12345);
echo 'Name :: ', $obj->name, PHP_EOL;
echo 'Price :: $', $obj ['price'], PHP_EOL;
echo 'Address :: ', $obj->address_primary, ' ', $obj->getAddressSecondary (), PHP_EOL;
echo 'City, State, Zip :: ', $obj->city, ', ', $obj ['state'], ' ', $obj->getZip ();
Every time I attempt to write a class it either prints out blank or Web Storm is throwing an error about method not being declared in class.
code I used:
var $name; // House Name
var $price; // Price of House
var $address_1; // Address 1
var $address_2; // Address 2
var $city; // City
var $state; // state
var $zip; // zip
// Class Constructor
function Property($name, $price, $address_1, $address_2, $city, $state, $zip) {
$this->setName = $name;
$this->price = $price;
$this->address_primary = $address_1;
$this->address_secondary = $address_2;
$this->city = $city;
$this->state = $state;
$this->zip = $zip;
}
// Getter/Setter functions
function get_name() {
return $this->name;
}
function set_name($newname) {
$this->name = $newname;
}
function get_price() {
return $this->price;
}
function set_price($newprice) {
$this->price = $newprice;
}
function get_address_1() {
return $this->address_primary;
}
function set_address_1($newaddress_1) {
$this->address_primary = $newaddress_1;
}
function get_address_2() {
return $this->address_secondary;
}
function set_address_2($newaddress_2) {
$this->address_secondary = $newaddress_2;
}
function get_city() {
return $this->city;
}
function set_city($newcity) {
$this->city = $newcity;
}
function get_state() {
return $this->state;
}
function set_state($newstate) {
$this->state = $newstate;
}
function get_zip() {
return $this->setZip;
}
function set_zip($newzip) {
$this->setZip = $newzip;
}}
any code suggestions would greatly be appreciated!
that's kind of a big mess! :) You're mixing setters/getters and direct access, and are using old school constructors. You can clean it up really quickly.
class Property
{
public function __construct($name, $price, $address_1, $address_2, $city, $state, $zip)
{
$this->name = $name;
$this->price = $price;
$this->address_primary = $address_1;
$this->address_secondary = $address_2;
$this->city = $city;
$this->state = $state;
$this->zip = $zip;
}
}
If you set up your class like such with all your variables in the constructor, then you should be using it like:
$obj = new Property(
"Name of Something",
500,
"First Line",
"Second Line",
"City",
"State",
"90210"
);
echo 'Name :: ', $obj->name, PHP_EOL;
echo 'Price :: $', $obj->price, PHP_EOL;
echo 'Address :: ', $obj->address_primary, ' ', $obj->address_secondary, PHP_EOL;
echo 'City, State, Zip :: ', $obj->city, ', ', $obj->state, ' ', $obj->zip;
Marked issues with your code were:
You're mixing members with functions. This kind of stuff in your constructor is major breakage:
$this->setName = $price
You're also mixing substring access [] with -> and using getters on top ->getName(). Be consistent, and in this case, respect the semantic of public variables.
Lastly, you had parameters in your constructor, but weren't using it at all.
Alternative would be to assign values to your constructor signature variables by default to make them optional.
public function __construct($name = "", $price = 0, $address_1 = "", $address_2 = "", $city = "", $state = "", $zip = "" )
And then use the public member access as you had:
$obj = new Property();
$obj->name = "Some Name";
Good luck with your learning.

PHP5 - OOP - Polymorphism - Help me to rewrite this simple switch

Assuming i have this classic switch, i know that when we are building classes is not a good practice use the switch method, so, how i can rebuild this into a class without using switch but Polymorphism and i would like to understand the approach.
/**
* globals below are holding unique id
* $Franklin['Franklin_id'] ,
* $Granny_Smith['Granny_Smith_id'] ,
* etc etc...
*/
global $Fuji, $Gala, $Franklin, $Granny_Smith;
switch($Apple) {
case 'Fuji':
$Color = 'Yellowish green';
$Size = 'medium';
$Origin = 'Japan';
$Season = 'October - January';
$AppleId = $Fuji['Fuji_id'];
break;
case 'Gala':
$Color = 'yellow';
$Size = 'medium';
$Origin = 'New Zealand';
$Season = 'October - January';
$AppleId = $Gala['Gala_id'];
break;
case 'Franklin':
$Color = 'Well-colored';
$Size = 'medium';
$Origin = 'Ohio';
$Season = 'October';
$AppleId = $Franklin['Franklin_id'];
break;
case 'Granny_Smith':
$Color = 'Green';
$Size = 'medium';
$Origin = 'Australia';
$Season = 'October - December';
$AppleId = $Granny_Smith['Granny_Smith_id'];
break;
}
then i would like to be able to use it something like this
$AppleProps = new getApple('Granny_Smith'); // $AppleProps->Color, etc etc
Thank you in advance and hope this can help someone else.
Kind Regards
Luca
thank's to http://www.allaboutapples.com/ for Apples Informations ;)
If you really want to use OO for this, then what you should do is create an appleFactory class, then have separate classes for each kind of apple...
class appleFactory
{
public static function getApple( $name )
{
$className = $name.'_apple';
return new $className( );
}
}
class fuji_apple
{
public function __construct( )
{
$this->color = 'Yellowish green';
$this->size = 'medium';
$this->origin = 'Japan';
$this->season = 'October - January';
$this->appleId = $Fuji['Fuji_id'];
}
}
class gala_apple
{
public function __construct( )
{
$this->color = 'Yellow';
$this->size = 'medium';
$this->origin = 'New Zealand';
$this->season = 'October - January';
$this->appleId = $Gala['Gala_id'];
}
}
Then use it like so...
$fuji = appleFactory::get( 'fuji' );
$gala = appleFactory::get( 'gala' );
I'm not complete sure what your IDs mean, but this code gives you an AppleFactory that will "stamp" each new apple with a unique ID.
class AppleFactory {
static $id = 0;
static public function getApple($className) {
$apple = new $className();
$apple->id = self::$id++;
return $apple;
}
}
class Apple {
public $id;
public $color;
public $size;
public $origin;
public $season;
}
class GrannySmith extends Apple {
public function __construct() {
$this->color = 'Green';
$this->size = 'medium';
$this->origin = 'Australia';
$this->season = 'October - Desember';
}
}
$a = AppleFactory::getApple('GrannySmith');
print_r($a);
There's no need for object-orientation here. But the switch can be replaced by a much simpler construct. If you use a data array, you can even skip the function:
$apple_data = array(
'Fuji' => array(
'Color' => 'Yellowish green';
'Size' => 'medium';
'Origin' => 'Japan';
'Season' => 'October - January';
'AppleId' = 1234567890,
),
'Gala' => array(
'Color' => 'yellow';
'Size' => 'medium';
'Origin' => 'New Zealand';
'Season' => 'October - January';
'AppleId' => 1234598760,
),
...
);
To access the attributes just use:
$id = $apple_data["Granny_Smith"]["AppleId"]
Or if you really want all those local variables:
extract($apple_data["Granny_Smith"]);
// creates $Color, $Size, $Origin, $Season, $AppleId in local scope
If you really want the object-syntax, then try:
$AppleProps = new ArrayObject($apple_data["Fuji"], 2);
print $AppleProps->Color;
But since the apples are not doing anything, you probably don't want to create a class or real objects for them. (Damn apples. Just sitting there and doing nothing.)

Laravel insert data twice when timeout occurs

I noticed laravel re-preform the insertion action when the timeout occurs
How can I shop it from retiring to insert the data again when timeout error fires ?
loop
foreach ($comments_data as $comment_data)
{
if ( ! empty($comment_data['date']))
{
$total_rating[] = $this->check_rating_value($comment_data['rating']);
$comment_id = ( new Comment() )->saveComments($shop, $comment_data, $product_id, $urls, $shop_options);
( new Comments_images() )->save_images($comment_id, $shop, $comment_data['images']);
}
}
inserting code
public function saveComments($shop, $comments_data, $product_id, $url, $shop_options)
{
$date = Carbon::parse($comments_data['date']);
if ($shop_options->filter_status == 1)
{
$comments = str_replace(explode(',', $shop_options->filter_find_words), explode(',', $shop_options->filter_alter_words), $comments_data['comment']);
} else
{
$comments = $comments_data['comment'];
}
$faker = Factory::create();
$this->shop_name = $shop;
$this->comment = $comments;
$this->rating = $this->check_rating_value($comments_data['rating']);
$this->product_id = $product_id;
$this->user_name = $faker->userName;
$this->product_url = $url;
$this->created_at = $date->toDateTimeString();
$this->country = $comments_data['country'] == 'IL' ? 'PS' : $comments_data['country'];
$this->view = 1;
$this->save();
return $this->id;
}

Categories