I'm getting the following error:
Fatal error: Declaration of Shoppingcart::addToCart() must be compatible with that of Ishoppingcart::addToCart() in klassen.php on line 118
What could be the problem? I can't find it
script:
<?php
// begin
interface Ishoppingcart{
public function addToCart();
public function printOverzicht();
}
abstract class Shoppingcart implements Ishoppingcart
{
protected $producten = array();
public function addToCart( Product $product) {
$this->producten[] = $product;
}
}
class Myshoppingcart extends Shoppingcart {
public function printOverzicht(){
echo ("<table border=1>
<tr>
<td colspan='7'>Bestellingoverzicht</td>
</tr>
<tr>
<td bgcolor=#cccccc> Product ID</td>
<td bgcolor=#cccccc> Beschrijving</td>
<td bgcolor=#cccccc> Merk</td>
<td bgcolor=#cccccc> Model</td>
<td bgcolor=#cccccc> Prijs</td>
<td bgcolor=#cccccc> Aantal</td>
<td bgcolor=#cccccc> Korting</td>
</tr>");
foreach($this->producten as $product){
$rij = "";
$rij .= "<tr>";
$rij .= "<td>".$product->getID()."</td>";
$rij .= "<td>".$product->getBeschrijving()."</td>";
$rij .= "<td>".$product->getMerk()."</td>";
$rij .= "<td>".$product->getModel()."</td>";
$rij .= "<td>".$product->getPrijs()."</td>";
$rij .= "<td>".$product->getAantal()."</td>";
$rij .= "<td>".$product->getKorting()."</td>";
$rij .= "</tr>";
echo ($rij);
}
echo ("</table>");
}
}
class Product {
private $id;
private $beschrijving;
private $merk;
private $model;
private $prijs;
private $aantal;
private $korting;
function __construct($id,
$merk,
$model,
$prijs,
$aantal,
$korting){
$this->id = $id;
$this->beschrijving = $beschrijving;
$this->merk = $merk;
$this->model = $model;
$this->prijs = $prijs;
$this->aantal = $aantal;
$this->korting = $korting;
echo ("<br />Nieuw Product object $beschrijving wordt aangemaakt");
}
public function __destruct(){
// voer benodigde acties uit
echo ("<br />Product object $this->beschrijving wordt verwijderd");
}
// set function
public function setId($id){
$this->id = $id;
}
public function setBeschrijving($beschrijving){
$this->beschrijving = $beschrijving;
}
public function setMerk($merk){
$this->merk = $merk;
}
public function setModel($model){
$this->model = $model;
}
public function setPrijs($prijs){
$this->prijs = $prijs;
}
public function setAantal($aantal){
$this->aantal = $aantal;
}
public function setKorting($korting){
$this->korting = $korting;
}
// get function
public function getId(){
return $this->id = $id;
}
public function getBeschrijving(){
return $this->beschrijving;
}
public function getMerk(){
return $this->merk;
}
public function getModel(){
return $this->model;
}
public function getPrijs(){
return $this->prijs;
}
public function getAantal(){
return $this->aantal;
}
public function getKorting(){
return $this->korting;
}
// printProductInfo
public function printProductInfo(){
$rij = "<tr><td>$this->id</td>";
$rij .= "<td>$this->beschrijving</td>";
$rij .= "<td>$this->merk</td>";
$rij .= "<td>$this->model</td>";
$rij .= "<td>$this->prijs</td>";
$rij .= "<td>$this->aantal</td>";
$rij .= "<td>$this->korting</td>";
echo ($rij);
}
}
// einde
?>
Ishoppingcart::addToCart() states that the method does not take any parameter, while the implementation Shoppingcart::addToCart(Product $product) requires that a parameter of type Product must be passed into the method. This means that both declarations are incompatible and while the implemented interface must be satisfied PHP throws the shown error.
Solution would be to either change Ishoppingcart::addToCart() to Ishoppingcart::addToCart(Product $product) so that it requires a parameter of type Product or to change Shoppingcart::addToCart(Product $product) to allow no parameter to passed into the method: Shoppingcart::addToCart(Product $product = null);
The correct way depends on your application requirements.
The declaration of a public function in a sub class must match that of its parent:
public function addToCart();
public function addToCart( Product $product)
You cannot add a parameter to the signature.
This is closely related to the Liskov substitution principle.
Doesn't apply to this particular question, but if someone there is having this issue, make sure to include the return value if the Interface specifies it.
An interface with a function like this:
abstract public function crawled(Something $some): void;
needs to be implemented as:
public function crawled(Something $some): void {
}
In my case I was missing the : void return type.
Interface Ishoppingcart seems to define addToShoppingCart without parameters, but class Shoppingcart defines the same function taking Product as a parameter. I suppose the method in the interface should take Product as a parameter as well.
I resolved this issue by upgrading to the latest php version
This can also happen if Intelephense sees multiple classes with the same name but with different signatures. They may not be in PHP's scope, but Intelephense allows specifying additional directories and seems to pick up backup directories and the like as well.
Related
I am trying to build some classes for a project and I was wondering how to achieve the following. I am not really sure how to ask this with words but I will provide an example:
class Table{
private $name;
private $fields = [];
public function addField(Field $field){
$this->fields[$field->getName()] = $field;
}
public function getName(){
return $this->name;
}
}
class Field{
private $name;
public function getName(){
return $this->name;
}
public function getTableName(){
//return Table::getName
}
public function getTable(){
//return a ref to the Table object
}
}
$table = new Table();
$field = new Field();
$table->addField($field);
What I am trying to achieve here, once the $field is added to the $table, is there some sort of way to get the reference of the $table from any of the methods in the $field object
I would greatly appreciate any help or ideas how to restructure it so I can achieve my goal
Thank you in advance
class Table{
private $name;
private $fields = [];
public function addField(Field $field){
$this->field->setTable($this);
$this->fields[$field->getName()] = $field;
}
public function getName(){
return $this->name;
}
}
class Field{
private $name;
private $relatedTable;
public function getName(){
return $this->name;
}
public function setName($name){
$this->name = $name;
}
public function getTableName(){
return $this->relatedTable->getName();
}
public function getTable(){
return $this->relatedTable;
}
public function setTable(Table $table){
$this->relatedTable = $table;
}
}
$field = new Field;
$field->setName('Field1');
$table = new Table;
$table->addField($field);
echo $field->getTable()->getName();
Although you have to be aware that when you pass an object to a function, it will be passed by "reference" (I know there's another term for this.)
// in case you're running it in a for loop
$field = new Field;
$table = new Table;
for($i = 0; $i < 3; $i++)
{
$field->setName("Field{$i}");
$table->addField(clone $field); // notice the clone there.
}
I think this approach is kind of similar with Observer Pattern
How pass parameter to PHP class by class()::function()?
class greenHouse{
public function __construct(connection $con){
}
public function show(){
}
}
$nameclass = 'greenHouse';
$namefunction = 'show';
$nameclass::$namefunction();
works
$nameclass = 'greenHouse';
$namefunction = 'show';
$nameclass($con)::$namefunction();
doesn't work
I want to pass a parameter to the class with $nameclass($con)::$namefunction();. How do I do that in PHP?
You are trying to call a function statically with that notation...
$nameclass = 'greenHouse';
$namefunction = 'show';
$class = new $nameclass($con);
$class->$namefunction();
You can instantiate an object and immediately discard it by calling new within braces:
class Test
{
private $name;
function __construct($name)
{
$this->name = $name;
}
function speak()
{
echo $this->name;
}
function __destruct()
{
echo 'dead';
}
}
$class='Test';
$method='speak';
(new $class('David'))->$method();
echo ' is ';
$temp = new $class('John');
$temp->$method();
echo ' is ';
//Daviddead is John is dead
So in your case:
(new $nameclass($con))->$namefunction();
I use a data base ( created with phpmyadmin) in a function for my future website. The query worked but the result is strange : null .
This is my code :
public function select_toutcompetences($requete){
$query = "SELECT niv , nom FROM competences WHERE element = '$requete' ";
$result = $this->_db->query($query);
$tableau = array();
if ($result->rowCount() == 0){
return $tableau;
} else {
while($row = $result->fetch()) {
$tableau[] = new Competence($row->niv,$row->nom);
}
return $tableau;
}
}
In my view :
<?php if (!empty($table)) {?>
<table>
<caption>Les compétences</caption>
<tr>
<th>Niveau</th>
<th>Nom</th>
<tr>
<?php foreach ($table as $i=> $element) { ?>
<tr>
<td><?php echo $element->niveau()?></td>
<td><?php echo $element->nom()?></td>
</tr>
<?php } ?>
</table>
<?php }?>
With a var_dump , I got this :
object(Competence)[5]
private '_niveau' => null
private '_nom' => null
null
My class :
<?php
class Competence {
private $_niveau;
private $_nom;
public function Livre($niveau,$nom) {
$this->_niveau = $niveau;
$this->_nom = $nom;
}
public function niveau() {
return $this->_niveau;
}
public function nom() {
return $this->_nom;
}
}
?>
Thanks you for your help. I searched but I didn't understand why it doesn't work.
PS : I know my query isn't securized. I would it to work first.
Edit : the sql data base : comptences.sql
It is because your class does not have constructor. Method Livre is not called when object is initiating $tableau[] = new Competence($row->niv,$row->nom);. Try this (I have replaced Livre with __construct):
<?php
class Competence {
private $_niveau;
private $_nom;
public function _contruct($niveau,$nom) {
$this->_niveau = $niveau;
$this->_nom = $nom;
}
public function niveau() {
return $this->_niveau;
}
public function nom() {
return $this->_nom;
}
}
Also be sure you have same values in database result.
Try making the variables in your class public as well.
public $_niveau;
public $_nom;
I have this code and the sad thing is i can't change anything or add outside the class STUDENT. I can modify only inside STUDENT and i can't alter the private fields. However I need to display the value of the field $nume in red color. Ideas?
class STUDENT {
private $nume,$prenume;
// Constructor
public function __construct($nume , $prenume){
$this->nume=$nume;
$this->prenume=$prenume;
}
public function __toString(){
return $this->nume.".".$this->prenume;
}
}
$student = new STUDENT("mr","Jack");
echo "student: ". $student ."<hr/>";
You can make the properties public so you can access them from the outside like this:
class STUDENT
{
public $nume;
public $prenume;
// Constructor
public function __construct($nume , $prenume)
{
$this->nume=$nume;
$this->prenume=$prenume;
}
public function __toString()
{
return $this->nume.".".$this->prenume;
}
}
$student = new STUDENT("mr","Jack");
echo "<span style='color:red'>student: ". $student->nume ."</span><hr/>";
Or if you need to keep the private you can create a function inside the class to output it:
class STUDENT
{
private $nume;
private $prenume;
// Constructor
public function __construct($nume , $prenume)
{
$this->nume=$nume;
$this->prenume=$prenume;
}
public function __toString()
{
return $this->nume.".".$this->prenume;
}
public function displayNume()
{
echo "<span style='color:red'>student: ". $this->nume ."</span><hr/>";
}
}
Which you can then access like this:
$student = new STUDENT("mr","Jack");
$student->displayNume();
Have you tried...
public function __toString(){
$red = '<span style="color: red;">' . $this->nume . '</span>';
return $red.".".$this->prenume;
}
?
I'm learning OOP, and got a little problem here with not understanding the code.
Here it is.
class ShopProduct {
private $title;
private $producerMainName;
private $producerFirstName;
protected $price;
private $discount = 0;
function __construct( $name, $firstName, $mainName, $price) {
$this->title = $name;
$this->producerFirstName = $firstName;
$this->producerMainName = $mainName;
$this->price = $price;
}
public function getProducer() {
return "{$this->producerMainName} "."{$this->producerFirstName} \n ";
}
public function setDiscount($num){
$this->discount = $num;
}
public function getDiscount() {
return $this->discount;
}
public function getTitle() {
return $this->title;
}
public function getPrice() {
return ($this->price - $this->discount);
}
public function getSummaryLine() {
$base = "{$this->title} ( {$this->producerMainName}, ";
$base .= "{$this->producerFirstName} )";
return $base;
}
}
class CDProduct extends ShopProduct {
private $playLength = 0;
public function __construct($title, $firstName, $mainName, $price, $playLength) {
parent::__construct($title, $firstName, $mainName, $price);
$this->playLength = $playLength;
}
public function getPlayLength() {
return $this->playLength;
}
public function getSummaryLine() {
$base = parent::getSummaryLine();
$base .= ": {$this->playLength()} minutes";
return $base;
}
}
class BookProduct extends ShopProduct {
private $numPages = 0;
public function __construct($title, $firstName, $mainName, $price, $numPages) {
parent::__construct($title, $firstName, $mainName, $price);
$this->numPages = $numPages;
}
public function getNumberOfPages() {
return $this->numPages;
}
public function getSummaryLine() {
$base = parent::getSummaryLine();
$base .= ": {$this->numPages()} pages";
return $base;
}
}
class ShopProductWriter {
private $products = array();
public function addProduct($shopProduct){
if(! ($shopProduct instanceof ShopProduct) ){
die('object error');
}
$this->products[] = $shopProduct;
}
public function write($shopProduct) {
foreach($this->products as $shopProducts){
$str = "{$shopProduct->getTitle()}: "."{$shopProduct->getProducer()}"." {$shopProduct->getPrice()}$ \n";
}
print $str;
}
}
$product = new CDProduct('Song is the rythm','Zyxel','Beatz',50, 60.33);
$write = new ShopProductWriter();
$write->addProduct($product);
$write->write($product);
The problem is here
class ShopProductWriter {
private $products = array();
public function addProduct($shopProduct){
if(! ($shopProduct instanceof ShopProduct) ){
die('object error');
}
$this->products[] = $shopProduct;
}
public function write($shopProduct) {
foreach($this->products as $shopProducts){
$str = "{$shopProduct->getTitle()}: "."{$shopProduct->getProducer()}"." {$shopProduct->getPrice()}$ \n";
}
print $str;
}
}
As you see there is condition - if the object is not ShopProduct type - goes error.
But as you see i'm creating CDProduct object.
$product = new CDProduct('Song is the rythm','Zyxel','Beatz',50, 60.33);
$write = new ShopProductWriter();
$write->addProduct($product);
$write->write($product);
It should show error. Anybody can say me what i'm doing wrong?
Objects of CDProduct are also of type ShopProduct. In the class definition:
class CDProduct extends ShopProduct {
So it is an object of both types.
http://php.net/manual/en/language.oop5.inheritance.php
If an object extends a parent or implements an interface, it can be considered of that type also.
http://php.net/manual/en/language.operators.type.php
You got already feedback about why a CDProduct is a ShopProduct, so I just add another hint on some code you've written where PHP has already support for:
public function addProduct($shopProduct){
if(! ($shopProduct instanceof ShopProduct) ){
die('object error');
}
$this->products[] = $shopProduct;
}
Instead of doing the check on your own, you can just make use of Type Hinting to reduce your code and make it more expressive:
public function addProduct(ShopProduct $shopProduct) {
$this->products[] = $shopProduct;
}
I hope this helps as you wrote you're currently learning about OOP.