In my PHP file I have created a class as below but I am getting error on line 3rd and 5th line.
class CommonPath{
var $baseurl = 'http://mysite.com/';
var $docroot = realpath(dirname(__FILE__));
var $root = '/';
var $images = $this->root.'/img';
}
My Dreamwaver CS5 showing these lines (3rd & 5th) as erroneous lines and I am getting following error on executing this code.
Parse error: parse error, expecting `','' or `';'' in D:\wamp\www\site\libs\CommonPath.php on line 3
You can have only literals and constants as default values. No functions or other expressions are allowed.
There are two different mistakes. First, you cannot use functions to define class variables (line 3). Moreover, $this does not make sense in line 5, as you have got no object yet.
You can't assign the values like that right when you're declaring your member properties. Assign it in the constructor
class CommonPath{
var $baseurl = 'http://mysite.com/';
var $docroot = '';
var $root = '/';
var $images = '';
function __construct() {
$this->docroot = realpath(dirname(__FILE__));;
$this->images = $this->root.'/img';
}
}
You can not concat string and assign any value to variable which need to call any function, at the time declaring class variable.
Related
For example I have class A in file a.php
namespace Path\To;
class A {
const SOME_VAR = 'value';
// many functions
}
And I have class B in file b.php
use Path\To\A;
class B {
public function foo() {
$i = 1;
$i = 2;
$i = 3;
// other code
$someVar = A::SOME_VAR;
}
// other functions
}
Which time in executing function foo constant variable SOME_VAR loads in RAM. On first line of function foo or on line $someVar = A::SOME_VAR; or line use Path\to\A; or elsewhere?
a.php is read, parsed and executed when $someVar = A::SOME_VAR; is executed inside b.php. That is also when the 'value' string is loaded into memory.
At that same time, everything about class A is loaded. If you where to add const SECOND_VAR = 'another-value'; to class A, once $someVar = A::SOME_VAR; has been executed there is also a bit of RAM that contains 'another-value'.
What the use Path\To\A; line does, is just tell PHP "if class A is requested, what they mean is \Path\To\A". You can add use Some\Non\ExistentClass and use Some\Class\That\Has\ASyntaxErrorInTheCode, and nothing will change, because as long as you don't try to actually do anything with ExistentClass or ASyntaxErrorInTheCode PHP will never read the files that those classes are in.
Memory is being allocated the first time you request the value of the variable. An easy way to test it is the following:
Create a file named Foo.php
<?php
class Foo {
// As of PHP 7.1.0
public const BAR = 'bar';
private const BAZ = 'baz';
}
?>
Use the following file anywhere you want.
And then type the following 2 lines:
$x = FOO::BAR;
$y = FOO::BAZ; // <- this will cause an error, since the variable is private
No error will occur during the use of the file, or while retrieving the value of the previous BAR variable.
This way you can identify that PHP knows nothing about that variable before you attempt to access its value.
got a script which has string variables that represent data fields like they are in the database. because this project is a complete mess this is a stage in cleaning it up and not having to rewrite the field name in numerous locations.
so one script 'DataKeys.php' will have variables set to field names.
//results from query1
$keyField1 = 'field1';
$keyField2 = 'field2';
these two vars above is only a snippet of a much longer list.
I want to access this file and use these vars when I am formatting the data to be more friendly for the front end. this script is being accessed in a class however the fields, $keyField1, defined in the script is not being found in the class. I did have the actual string there but I think single access point would be best so when I make future changes I don't need search the whole project.
class DataFormatter {
//put your code here
public function __construct() {
$documentRoot = filter_input(INPUT_SERVER, "DOCUMENT_ROOT");
include ($documentRoot . '/database/values/DataKeys.php');
}
public function cleanData($data){
if (is_null($data) || empty($data))
{
return;
}
foreach($data as $row){
$field1Value = $row[$keyField1];
unset($row[$keyField1]);
}
}
}
I also tried moving the include outside the class definition.
$documentRoot = filter_input(INPUT_SERVER, "DOCUMENT_ROOT");
include ($documentRoot . '/database/values/DataKeys.php');
The error that is being reported is :
Undefined variable: keyField1
SOULTION
Maybe not the optimal way but I took the include statement and placed it inside the function. The code above is just a demo of what I was trying to achieve not the actual code I am using.
the 2 variables are available just after the "include".
you can for example, put the 2 values in properties of the object
include ...;
$this->keyField1 = $keyField1;
$this->keyField2 = $keyField2;
You have to assign DataKeys.php to class member.
class DataFormatter {
private $keyField1;
private $keyField2;
public function __construct($filename) {
include $filename;
$this->keyField1 = $keyField1;
$this->keyField2 = $keyField2;
}
}
$dataFormatter = new DataFormatter(filter_input(INPUT_SERVER, 'DOCUMENT_ROOT') . '/database/values/DataKeys.php');
With reflection, it's easy to get the start and end line e.g. of a method in the source file: ReflectionFunctionAbstract::getFileName(), ReflectionFunctionAbstract::getStartLine(), ReflectionFunctionAbstract::getEndLine() provide this functionality. However, this doesn't seem to work with properties. What's the best way to extract at least the start line and the file name of a property declaration in a class definition?
It's not trivial but also not too hard.
You can get the class a property is defined in via Reflection. And from there you can get the filename. All you have to do then is either tokenize the file and check at what line the property declaration or simply go over the file line by line and do string matching.
Here is one possible way to do that:
$reflector = new ReflectionProperty('Foo', 'bar');
$declaringClass = $reflector->getDeclaringClass();
$classFile = new SplFileObject($declaringClass->getFileName());
foreach ($classFile as $line => $content) {
if (preg_match(
'/
(private|protected|public|var) # match visibility or var
\s # followed 1 whitespace
\$bar # followed by the var name $bar
/x',
$content)
) {
echo $line + 1;
}
}
And here is a demo to show that it works
Obviously, the above solution assumes the property to be declared in a certain fashion. It also assumes you have one class per file. If you cannot be sure this is the case, tokenization is the better option. But it's also more difficult.
Use roave/better-reflection
$classInfo = (new BetterReflection())
->reflector()
->reflectClass($class);
foreach ( $classInfo->getProperties() as $reflectionProperty) {
$declaringClass = $reflectionProperty->getDeclaringClass()->getFileName();
$declaringSource = $reflectionProperty->getDeclaringClass()->getLocatedSource()->getSource();
$sourceLines = explode("\n", $declaringSource);
$propertySource = join("\n", array_slice($sourceLines, $reflectionProperty->getStartLine(), $reflectionProperty->getEndLine()-$reflectionProperty->getStartLine()));
$properties[$reflectionProperty->getName()] = [
'declaringClass' => $declaringClass,
'source' => $propertySource,
'startLine' => $reflectionProperty->getStartLine(),
'endLine' => $reflectionProperty->getEndLine()
];
}
print_r($properties);
The snippet above will also get the property declaration when that property is declared in a trait or parent class. Obviously, this can be optimized, as it's splitting the source inside the loop.
This is the weirdest bug! It is probably something silly, but I have no idea how to fix it. If anyone could help, I would be most grateful! I have three files, one is called items.php, another is called tableFunctions.php, and the third is called mysql.php. I use two global objects called 'mysql' and 'tableFunctions'. They are stored in the files 'mysql.php', and
'tableFunctions.php', respectively. In each file, I create an instance of its object, assigning it to the global variable $_mysql, or $_table. like this:
In the file mysql.php:
global $_mysql;
$_mysql = new mysql();
In the file tableFunctions.php:
global $_table;
$_table = new tableFunctions();
Here's how it is supposed to work:
The items.php file includes the tableFunctions.php file...
Which in turn, needs the mysql.php file, so it includes it too.
In the items.php file, I call the method getTable(), which is contained in the object tableFunctions.(and in the variable $_table.) Like this:
$t = $_table->getTable('items');
The getTable function calls the method, arrayFromResult(), which is contained within in the object mysql.(and in the variable $_mysql.) Like this:
$result = $_mysql->arrayFromResult($r);
That's where I get the error. PHP says that the variable '$_mysql' is undefined, but I defined it in the 'mysql.php' file.(see above) I also included mysql.php with the following code:
include_once 'mysql.php';
I have no idea what is wrong! If anyone can help that would be much appreciated.
The source files can be downloaded with the following link: https://www.dropbox.com/sh/bjj2gyjsybym89r/YLxqyNvQdn
That's a common mistake, in the place of definition you need only the line:
$_mysql = new mysql();
and when you want to use it inside a function, only there you have to declare it as a global variable (otherwise it is considered like any other function variable):
global $_mysql;
so, for example, if we'll take your method:
function getTable($tableName) {
$r = mysql_query("SELECT * FROM $tableName");
err($r, 'mysql returned null when getting table!');
$result = $_mysql->arrayFromResult($r);
return $result;
}
it should be changed to:
function getTable($tableName) {
global $_mysql;
$r = mysql_query("SELECT * FROM $tableName");
err($r, 'mysql returned null when getting table!');
$result = $_mysql->arrayFromResult($r);
return $result;
}
Please could someone experienced in PHP help out with the following. Somewhere in my code, I have a call to a public static method inside a non-instantiated class:
$result = myClassName::myFunctionName();
However, I would like to have many such classes and determine the correct class name on the fly according to the user's language. In other words, I have:
$language = 'EN';
... and I need to do something like:
$result = myClassName_EN::myFunctionName();
I know I could pass the language as a parameter to the function and deal with it inside just one common class but for various reasons, I would prefer a different solution.
Does this make any sense, anyone? Thanks.
Use the call_user_func function:
http://php.net/manual/en/function.call-user-func.php
Example:
call_user_func('myClassName_' . $language . '::myFunctionName');
I think you could do:
$classname = 'myClassName_' . $language;
$result = $classname::myFunctionName();
This is called Variable Functions
I would encapsulate the creation of the class you need in a factory.
This way you will have a single entry point when you need to change your base name or the rules for mapping the language to the right class.
class YourClassFactory {
private $_language;
private $_basename = 'yourclass';
public YourClassFactory($language) {
$this->_language = $language;
}
public function getYourClass() {
return $this->_basename . '_' . $this->_language;
}
}
and then, when you have to use it:
$yourClass = $yourClassFactoryInstance->getYourClass();
$yourClass::myFunctionName();
As temuri said, parse error is produced, when trying '$className::functionName' :
Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM ...
In my case (static method with 2 arguments), best solutions is to use call_user_func_array with 2 arrays (as suggested by nikc.org):
$result = call_user_func_array(array($className, $methodName), array($ard1, $arg2));
BR
although i think the way you deal is a very bad idea, i think i may have a solution
$className = 'myClassName_'.$language;
$result = $className::myFunctionName();
i think this is what you want
You can easily do next:
<?php
class B {
public static $t = 5;
public static function t($h) {
return "Works!" . $h;
}
}
$g = 't';
$class = 'B';
echo $class::$g('yes'); //Works! Yes
And it will works fine, tested on PHP 5.2 >=
As far as i could understand your question, you need to get the class name which can be done using get_class function. On the other hand, the Reflection class can help you here which is great when it comes to methods, arguments, etc in OOP way.
Solutions like:
$yourClass::myFunctionName();
will not work. PHP will produce parse error.
Unfortunately, the only way is to use very slow call_user_func().
I know it's an old thread, but as of PHP 5.3.0 you should be using forward_static_call
$result = forward_static_call(array('myClassName_EN', 'myFunctionName'));
Using your $language variable, it might look like:
$result = forward_static_call(array('myClassName_' . $language, 'myFunctionName'));