PHP Cannot access empty property error - php

I am getting the following error and I can't seem to figure out why or how it's getting triggered.
Fatal error: Cannot access empty property in /home/content/p/l/a/plai1870/html/com/php/Bone/Compiler.php on line 18
Line 18 is
throw new LogicException($this->$compilers[$language]." is not a supported compiler.");
Here is Compiler.php
<?php
namespace Bone;
use LogicException;
class Compiler implements \Bone\Interfaces\Compiler {
protected $compiler;
protected $compilers = array(
"php" => "PHP",
"as3" => "ActionScript3",
"javascript" => "Javascript"
);
public function __construct($language) {
$language = strtolower($language);
if (!isset($this->$compilers[$language])) {
throw new LogicException($this->$compilers[$language]." is not a supported compiler.");
}
$compiler = "\Bone\Compilers\\".$this->$compilers[$language]."\Compiler";
$this->compiler = new $compiler();
}
public function buildDefinition($object, $path = null) {
return $this->compiler()->buildInterface($object, $path);
}
public function buildObject($object, $path = null) {
return $this->compiler->buildObject($object, $path);
}
public function parameters($method) {
return;
}
public function save($data, $path) {
return;
}
}
?>
EDIT
And I'm calling it with:
$compiler = new \Bone\Compiler("php");

Sorry if this is the most obvious, but:
throw new LogicException($this->$compilers[$language]." is not a supported compiler.");
As it has been checked that the property does not exists, shouldn't it be:
throw new LogicException("$language is not a supported compiler.");
?
Edit:
$this->$compilers[$language]
^- variable property
Remove the $ there:
$this->compilers[$language]
Then you can check if the entry in the array is set, not if a propery with the name of the value inside the (unset) array $compilers (local variable) is set.
When developing, always switch on warnings and notices (highest error level you can imagine) to not run into these problems without having PHP warn you first.

Your array is $this->compilers, not $this->$compilers.
$compilers doesn't exist in your function, so $this->$compilers was looking for a blank property.

Related

How to write that in PHP 7.2?

I have this piece of code:
private function _resolveCustomEntries($fields)
{
foreach ($fields as &$value) {
if (array_key_exists('custom', $value)) {
if (method_exists($this, $value['custom'])) {
$value['custom'] = $this->$value['custom'](); //variableInterpolation
}
}
}
return $fields;
}
I ran a PHP 7.2 compatibility check and it complained here with the "variableInterpolation" on the marked line. When I run this code, the PHP log tells me this:
ERR (3): Notice: Array to string conversion in
/public_html/lib/KiTT/Payment/Widget.php on line 217
Thats the same line where the "variableInterpolation" check failed. So how would I rewrite this code so it works in PHP 7.2?
Thanks!
Solution:
$value['custom'] = $this->$value['custom']();
has to look like this:
$value['custom'] = $this->{$value['custom']}();
It's a matter of order variables are evaled.
With
class x {
public function y() {
echo 'ok';
}
}
$x = new x();
$y = array('i' => 'y');
Then
$x->$y['i']();
Fails because PHP first tries to cast the $y variable into a string, and get the matching property of $x (which btw does not exist), then tries to get the index 'i' or that unexisting property, and then tries to run it as a callable.
Hence 3 errors:
Array to string conversion
Undefined property x::$Array
Function name must be a string (nda: the undefined property returns NULL)
Instead, curly brace the variable to set the resolving order:
$x->$y['i']();
Will work. So use $this->{$value['custom']}()
This will throw an array to string conversion in 7.2
class bob{
function foo(){
return 'bar';
}
function getFoo(){
$value['custom'] = 'foo';
$value['custom'] = $this->$value['custom']();
return $value['custom'];
}
}
$bob = new Bob();
var_dump($bob->getFoo());
But it will execute just fine in 5.6.
Then i changed the snippet to this, not calling the method directly casting the array key to function name, but initializing a string (hopefully, there is no type validation in your code) variable with the function name first:
class bob{
function foo(){
return 'bar';
}
function getFoo(){
$value['custom'] = 'foo';
$functionName = $value['custom'];
$value['custom'] = $this->$functionName();
return $value['custom'];
}
}
$bob = new Bob();
var_dump($bob->getFoo());
This will run just fine in php 7.2
You could try rewriting your code using complex (curly) syntax, you can read more about it here.
Your code would look something like this.
$value['custom'] = $this->{$value['custom']}();
Edit: moved the curly braces to correct positions.

URL is not working when it's trying it for routing

I'm trying to catch the URL from my localhost, here it is
http://localhost/mvc/index.php?url=Index/category and things are going well but when I'm trying to use the URL /category it is showing error. Here is the error
Notice: Array to string conversion in C:\xampp\htdocs\mvc\index.php on line 21
Notice: Undefined property: Index::$Array in C:\xampp\htdocs\mvc\index.php on line 21
Fatal error: Uncaught Error: Function name must be a string in C:\xampp\htdocs\mvc\index.php:30 Stack trace: #0 {main} thrown in C:\xampp\htdocs\mvc\index.php on line 21
<?php
include_once "system/libs/main.php";
include_once "system/libs/Dcontroller.php";
include_once "system/libs/Load.php";
?>
<?php
$url = isset($_GET['url']) ? $_GET['url'] : NULL;
if ($url != NULL) {
$url = rtrim($url,'/');
$url = explode("/", filter_var($url,FILTER_SANITIZE_URL));
} else {
unset($url);
}
if (isset($url[0])){
include 'app/controllers/'.$url[0].'.php';
$ctlr = new $url[0]();
if (isset($url[2])) {
$ctlr->$url[1]($url[2]);
} else {
if (isset($url[1])) {
$ctlr->$url[1](); //Here is the line where I'm getting the
error
} else {
}
}
}else{
include 'app/controllers/Index.php';
$ctlr = new Index();
$ctlr->home();
}
?>
But when I'm using
category() instead of $url[1]
it's working fine. Here is the Index class.
<?php
class Index extends Dcontroller
{
public function __construct()
{
parent::__construct();
}
public function home()
{
$this->load->view("home");
}
public function category()
{
$data = array();
$catModel = $this->load->model("CatModel");
$data['cat'] = $catModel->catList();
$this->load->view("category", $data);
}
}
two things straight away: "/" is not legal in a url param as part of a get string. you need to encapsulate it with URL encodeing
EG:
http://localhost/mvc/index.php?url=Index%2Fcategory
it's also the fact that "$ctlr->$url[1]" simply doesn't have a function called it.. eg: whatever "$ctlr->$url[1]" resolves to ??category()?? doesn't exist, you need to MAKE it.
add this to your code
function category() {
Index tmp = new Index();
tmp->category();
}
EDIT : I've just noticed, it's even more idiotic than I thought.. your string says Index/category doesn't it?.. make the class method static.. (this code is dreadful by the way it displays almost no sound knowledge of design whatsoever) there is no Index/category because you can't call category inside a class except if it's a static method.
Learn to code.

Set a referenced variable to a newly initialized class

I have a method, which takes a reference
// CarService.php
public function getCars(&$carCollection = null)
{
$promise = // guzzle request for getting all cars would be here
$promise->then(function (ResponseInterface $response) use (&$carCollection) {
$cars= json_decode($response->getBody(), true);
$carCollection= new CarCollection($cars);
});
}
However, when accessing the collection and trying to reuse it, I'm getting the error
Argument 1 passed to {placeholder} must be an instance of {placeholder}, null given
I know that the reason for this is, that the constructor returns nothing, but how can I still assign my variable to a new instance of the CarCollection (which extends Doctrine's ArrayCollection)
I even tried it with a static method as a work around
// CarCollection.php
public static function create(array $cars): CarCollection
{
$carCollection = new CarCollection($cars);
return $carCollection;
}
// CarService.php
public function getCars(&$carCollection = null)
{
$cars = // curl request for getting all cars would be here
$carCollection = CarCollection::create($cars)
}
but it's still null. Why is that? How can I set a referenced variable to a new class?
I access the method like this
$carService = $this->get('tzfrs.vehicle.services.car');
$carCollection = null;
$promises = [
$carService->getCars($carCollection)
];
\GuzzleHttp\Promise\unwrap($promises);
var_dump($carCollection); // null
When I set the reference directly, eg.
// CarService.php
public function getCars(&$carCollection = null)
{
$carCollection = new CarCollection([]);
}
it works without any problems. Seems like the callback is somehow the problem.
Whoever downvoted this, can you please elaborate why and why you voted to close?
I might be misunderstanding the question, but you should be able to modify an object when passing by reference. See here for an example: https://3v4l.org/KtFvZ
In the later example code that you added, you shouldn't pass $carCollection by reference, the & should only be in the method/function defintion, not provided when you call it. I don't think that is your problem though, that should be throwing an error in php7.

Fatal error: Call to a member function isUploaded() on a non-object [duplicate]

This question already has answers here:
Reference - What does this error mean in PHP?
(38 answers)
Closed 8 years ago.
I'm facing an error message:
Fatal error: Call to a member function isUploaded() on a non-object in /www/htdocs/nether/http/123factuur/application/controllers/Helpers/ImportXls.php on line 30
To my understanind this error message pops-up because I'm calling a method which doesn't exists in the object. But I'm sure that isUploaded() does exists.
The function isUploaded is defined in the class Zend_Form_Element_File. To check if $xls is an instance of the Zend_Form_Element_File I debugged the $xls variable.
Zend_Debug::dump($xls); //OUTPUT: object(Zend_Form_Element_File)#141 (29) {
exit;
Line 30 looks like this:
if ( $xls->isUploaded() ) {
The first thing I did was to check the expression value.
Zend_Debug::dump($xls->isUploaded()); //the output was: bool(true)
exit;
Then I checked the type of the $xls variable.
echo gettype($xls); //the output was object
exit;
I'm not fully understanding the error. Perhaps, I'm not interpreting the error message as it should be interpreted. Anyway, assistance is needed.
The code snippet:
At the controller:
public function importAction() {
$form = $this->getImportFrom();
$this->view->form = $form;
$this->view->allowedHeaders = array();
$this->importInvoices($form);
$this->importInvoiceArticles($form);
$this->importInvoiceServices($form);
foreach ($this->_lookupIssues as $issue) {
$this->_flashMessenger->addMessage($issue);
}
}
public function importInvoiceArticles($form) {
$model = 'Invoice_article';
$config = Zim_Properties::getConfig($model);
$Model = new Zim_Model($model, $config->model);
$headerMapping = array_flip(array_intersect_key($Model->getHeaders(true), array_flip($this->_allowedArticleImportHeaders)));
$this->getHelper('ImportXls')->handleImport($form, $headerMapping, $Model->getName(), $this->_modelName, null, null, array($this, 'saveImportedArticleData'), 'invoiceArticle');
}
At the helper:
class F2g_Helper_ImportXls extends Zend_Controller_Action_Helper_Abstract {
public function handleImport($form, $allowedHeaders, $tableName, $modelName, $onDuplicateImportCallback, $importMethod = null, $saveMethod = null, $name = 'xls') {
if ($this->getRequest()->isPost()) {
$xls = $form->getElement($name);
if ( $xls->isUploaded() ) {
//some code
}
}
}
}
I'm quite sure that the handleImport() method is called multiple times, possibly inside a loop, probably with different values for the $name parameter. You echo the variable and die in order to debug it, which works perfectly if the provided value for $name is correct on the first run - but since you kill the script - you don't get any debug information about subsequent calls.
Make sure the object has that method before calling it. You can either call method_exists() or instanceof to make that determination.
Code:
if ($xls instanceof Zend_Form_Element_File) {
// object of correct type - continue (preferred version)
}
// or
if (method_exists($xls, 'isUploaded')) {
// avoids the error, but does not guarantee that
// other methods of the Zend_Form_Element_File exist
}
Add this to your condition to avoid the Fatal Error :
if ( !empty($xls) && is_object($xls) && $xls->isUploaded() ) {
// do your job with serenity :)
}

How to read complex variables?

<?php
class config {
public static function get($path = null) {
if ($path) {
$config = $GLOBALS['config'];
$path = explode('/', $path);
foreach($path as $bit) {
if (isset($config[$bit])) {
$config = $config[$bit];
}
}
return $config;
}
return false;
}
}
?>
I'am following this tutorial http://www.youtube.com/watch?v=S6vDgLwJ7n8&list=PLfdtiltiRHWF5Rhuk7k4UAU1_yLAZzhWc from phpacademy. I got lost and can't understand this lines
function get ($path = null) ---- what does this mean? from my understanding it says "get the value of $path". but it leads me to another question, where can I get the value of $path? please enlighten me and translate this statement in english.
if ($path) ----- does this check if $path has a value?
$config = $config[$bit] ---- this is my first time to encounter this, I can't understand because there is a bracket with a variable in it. please enlighten me and teach me how can I translate this and read it in plain english.
function get($path = null)
That line declares a function named get which will accept one parameter named path. It has also provided a default value for path which is null. In plain that means if no path is sent to this function, then consider the path to be a null value.
This can be better explained with a different example
function display($message="Hello World")
{
echo $message;
}
If this function is called like
display("Testing"); // It will output `Testing`
display(); // It will output `Hello World`
Secondly
$config[$bit];
Means the value in $config array which has an index which is stored in $bit variable.
For example
$a=array();
$a["test"]=1;
$index="test";
echo $a["test"]; //echoes 1
echo $a[$index]; //echoes 1
function get($path = null)
This is a function declaration where the default value for $path is already set. Nothing more or less. The default value is NULL which means ... well, nothing. You can still hand over an argument and overwrite the default.

Categories