So like the title says, I am having a hard time making an array property of one of my classes have it's values be declared as properties & methods.
I can successfully do this if the array is not a property of a class, but as soon as the array is dropped into a class, the script doesn't like those values, and throws me this error.
Fatal error: Constant expression contains invalid operations in C:\xampp\htdocs_webdevepos\mcf\static\inc\classes\class.catalogue.php on line 17
I have both classes being included in a different .php
called inc.classes.php
. That file is then included in each page. Here is some code to better illustrate my issue,
Master Class File:
inc.classes.php
// config
require_once('config/config.php'); // config file
// other tools
require_once(ROOT_DIR . 'inc/parsedown/Parsedown.php'); // tool that I am using for parsing .md files
// my classes
require_once(ROOT_DIR . 'inc/classes/class.vendor.php');
require_once(ROOT_DIR . 'inc/classes/class.catalogue.php');
Class A:
class.vendor.php
class Vendor
{
public $vendor = array(
'foo' => array(
'name' => 'Foo Inc.',
'image' => (VENDOR_IMG . 'foo/foo-logo.png'),
),
'bar' => array(
'name' => 'Bar Co.',
'image' => (VENDOR_IMG . 'bar/bar-logo.png'),
),
);
public function get($data) {
if (array_key_exists($data, $this->vendors)) {
return $this->vendors[$data];
} else {
// throw error
}
}
// Class methods...
}
Class B:
class.catalogue.php
class Catalogue
{
public $catalogue = array(
'1' => array(
$section = $markdown->text(file_get_contents(ROOT_DIR . catalogue/markdown/section1.md')),
$link = 'catalogue/pdf/section1.pdf,
$pdf = (ROOT_DIR . $link),
'title' => 'Section One',
'content' => mdReplace($section, $pdf, $link),
'theme' => 'purple',
'vendors' => array(
1 => $vendor->get('foo'),
2 => $vendor->get('bar'),
),
),
// '2' ...
);
// Class methods...
}
(
mdReplace()
is a small function located in a seperate php file calledinc.functions.php
. It's purpose is to replace a few keywords inside of the.md
files that contain the sections' content.)
Apologies in advance if I am just blind as a bat right now and am missing something obvious.
If you read php oop manual carefully, here what you will see:
Class member variables are called "properties"... They are defined by using one of the keywords public, protected, or private, followed by a normal variable declaration. This declaration may include an initialization, but this initialization must be a constant value--that is, it must be able to be evaluated at compile time and must not depend on run-time information in order to be evaluated.
See the words
must not depend on run-time information
And your current definition of public $catalogue
is dependant of some data that will be evaluated later. That's why you have fatal error.
So, as said the solution is to fill $catalogue
data by calling some function - either explicitly or in a __construct
for example.
You can't run methods on a class property like that. You'd need to set that up inside your construct:
class Catalogue
{
public $catalogue = array();
public function __construct()
{
$this->catalogue = array(
'1' => array(
$section = $markdown->text(file_get_contents(ROOT_DIR . catalogue/markdown/section1.md')),
$link = 'catalogue/pdf/section1.pdf,
$pdf = (ROOT_DIR . $link),
'title' => 'Section One',
'content' => mdReplace($section, $pdf, $link),
'theme' => 'purple',
'vendors' => array(
1 => $vendor->get('foo'),
2 => $vendor->get('bar'),
),
),
// '2' ...
);
}
// Class methods...
}
As Farkie said, you can't run method calls on a class property like the way you did.
The reason is, those objects which you are trying to use are not initialised, and in order for them to work they must be initialised first.
Ex variables which can't directly be used in properly as they are not available to be used
$markdown
$section
So for Class B you need to have your code written inside the constructor.
However whatever you have done for Class A is perfectly acceptable and it should work. I could see that you have a typo in the variable name. It should be $vendors
as you are trying to refer it inside the function get()
as $this->vendors[$data];
The following will work
class Vendor
{
public $vendors = array(
'foo' => array(
'name' => 'Foo Inc.',
'image' => (VENDOR_IMG . 'foo/foo-logo.png'),
),
'bar' => array(
'name' => 'Bar Co.',
'image' => (VENDOR_IMG . 'bar/bar-logo.png'),
),
);
public function get($data) {
if (array_key_exists($data, $this->vendors)) {
return $this->vendors[$data];
} else {
// throw error
}
}
// Class methods...
}