Illegal string offset with php 7.1.6 - php

This code throws a waring under PHP 7.1.6... Under PHP 5.x.x it does not have any problems.
The offending line is $attributes['onclick'] = $onclick;, with the warning Illegal string offset 'onclick'.
Here is my code:
protected function js_anchor($title, $onclick = '', $attributes = '')
{
if ($onclick)
{
$attributes['onclick'] = $onclick;
}
if ($attributes)
{
$attributes = _parse_attributes($attributes);
}
return '<a href="javascript:void(0);"'.$attributes.'>'.$title.'</a>';
}

$attributes is initialized as an empty string. You need to make it an empty array, $attributes = []
protected function js_anchor($title, $onclick = '', $attributes = [])
{
if ($onclick)
{
$attributes['onclick'] = $onclick;
}
if ($attributes)
{
$attributes = _parse_attributes($attributes);
}
return '<a href="javascript:void(0);"'.$attributes.'>'.$title.'</a>';
}

Related

Illegal offset type in my php class function

I am getting illegal offset error in one of my function.
Here is the code
public function translate($str, $namespace = '') {
$namespace = $this->getNamespace($namespace);
$this->load($namespace);
$lang = $this->getLang();
$data = $this->data[$namespace];
$key = md5($str);
if (isset($data[$lang][$key])) {
return $data[$lang][$key];
}
$default = $this->getDefaultLang();
if ($lang == $default) {
if ($this->getSaveOnMissing()) {
$save = array(
'namespace' => $namespace,
'lang' => $lang,
'trans_key' => $key,
'trans_val' => $str
);
$sql = $GLOBALS['db']->strInsert('translate', $save);
if ($GLOBALS['db']->SQL_query($sql)) {
$this->data[$namespace][$lang][$key] = $str;
}
}
return $str;
} elseif (isset($data[$default][$key])) {
return $data[$default][$key];
}
return $str;
}
In this line I am getting this error
elseif (isset($data[$default][$key]))
So there are 3 levels of your value
$data
$default
$key
You can check by three levels first if they are all returning something
elseif(isset($data, $data[$default], $data[$default][$key])

Illegal String Offset 'class' in PHP

I received this warning
Warning: Illegal string offset 'class' in C:\xampp\htdocs\myweb\libraries\cms\html\html.php on line 971
Warning: Illegal string offset 'class' in C:\xampp\htdocs\myweb\libraries\cms\html\html.php on line 972
Warning: Illegal string offset 'class' in C:\xampp\htdocs\myweb\libraries\cms\html\html.php on line 972
On joomla 3.3 (file path \libraries\cms\html\html.php) and the code is:
public static function calendar($value, $name, $id, $format = '%Y-%m-%d', $attribs = null)
{
static $done;
if ($done === null)
{
$done = array();
}
$attribs['class'] = isset($attribs['class']) ? $attribs['class'] : 'input-medium';//happen here
$attribs['class'] = trim($attribs['class'] . ' hasTooltip');//happen here
$readonly = isset($attribs['readonly']) && $attribs['readonly'] == 'readonly';
$disabled = isset($attribs['disabled']) && $attribs['disabled'] == 'disabled';
if (is_array($attribs))
{
$attribs = JArrayHelper::toString($attribs);
}
.......
Shows that it had to do with $attribs['class']. And if I'm correct illegal string offset could mean that $attribs is not an array but a string. So is there any way to correct this?
I'm on PHP5.4
This:
public static function calendar($value, $name, $id, $format = '%Y-%m-%d', $attribs = null)
{
}
Should be:
public static function calendar($value, $name, $id, $format = '%Y-%m-%d', $attribs = array())
{
}
Point is that by setting "null" to the variable by default, you actually say it's an empty string, or an empty variable. By setting "array()", you define the variable being an empty array.
Just by looking a little bit further, there is an array expected, since the code is looking for specific array_keys like: 'readonly' AND 'disabled'.

if finding element with phpsimpledom failed

I am using simplephpdom For finding the title of one speciall page like this :
function get_title_with_dom($url) {
$amounts = array();
$html = file_get_html($url);
$elements = $html->find('title');
return trim($elements[0]->innertext);
}
So, now there is a problem for the pages that does NOT have title !
I will get this error :
Fatal error: Call to a member function find() on a non-object in ...
So, HOW can i say, if could not find element , then return NULL or FALSE ?
I tried to use such this blow function , but it doesn't work (work like code above) :
function get_title_with_dom($url) {
$amounts = array();
$html = file_get_html($url);
if (!($html->find('title'))) {
return false;
} else {
$elements = $html->find('title');
return trim($elements[0]->innertext);
}
}
You don't need both str_get_html and file_get_html. If you're feeding the url just use file_get_html.
function get_title_with_dom($url) {
$data = false;
$html = file_get_html($url);
$title = $html->find('title', 0);
if($title) {
$data = $title->innertext;
}
return $data;
}
var_dump(get_title_with_dom('http://www.google.com')); // Google
var_dump(get_title_with_dom('http://codepad.viper-7.com/moj97E')); // bool(false)

Array to string conversion error in PHP

I have following code to backtrace the error ....but its
$traces = debug_backtrace();
foreach ($traces as $k => $v)
{
if ($v['function'] == 'include'
|| $v['function'] == 'include_once'
|| $v['function'] == 'require_once'
|| $v['function'] == 'require')
{
$args = '';
if (isset($v['args']) && is_array($v['args']))
{
$size = count($v['args']);
foreach ($v['args'] as $key => $arg)
{
$args .= $v['args'][$key];
if($key < $size)
{
$args .= ', ';
}
}
}
$traces .= '#' . $k . ' '
. $v['function']
. '('.$args.') called at ['
. $v['file'].':'.$v['line'].']';
}
else
{
$function = (array_key_exists('function',$v)) ?
$v['function'].'() ' : 'function_name';
$file = (array_key_exists('file',$v)) ?
$v['file'] : 'file_name';
$line = (array_key_exists('line',$v)) ?
$v['line'] : 'line';
$traces .= "#{$k} $function called at {$file}:{$line}\n";//This line giving me notice...
}
}
I am getting notice as Array to string conversion here:
$traces .= "#$k $function called at $file:$line\n";
I actually want to convert this array into string. Is there any method or function which can do the conversion without giving me any notice...
How do I correct this?
you begin with:
foreach($traces as $k=>$v) <- $traces here is an array
then you try to do
$traces.= "xxx" <- $traces here is handled as a string
i would rather define a $tracestr string for aggregating text content.
You are not creating array properly
$args .= $v['args'][$key];
You are creating a string.
$args = array();
if(isset($v['args']) && is_array($v['args']))
{
$size = count($v['args']);
foreach ($v['
args'] as $key => $arg)
{
array_push($args,$v['args'][$key]);
// some of your code
}
$trace = debug_backtrace();
foreach($traces as ...)
There's something wrong here. $trace is a Debug Backtrace array. While you foreach($traces) ... which seems undefined. And you append to $traces which is supposed to be a non-scalar to foreach it.
Just name your variables properly and make names different!

CakePhp: Url based internationalization

I've a small problem with my internationalization:
I want to have some url looking like this: http://mywebsite/eng/controller/action/params...
I found this http://nuts-and-bolts-of-cakephp.com/2008/11/28/cakephp-url-based-language-switching-for-i18n-and-l10n-internationalization-and-localization/
This is working nice most of time. But I've one case where this hasn't the expected result.
When I'm using $this->Html->link with named parameters, I don't get my nice structure, but something like http://mywebsite/controller/action/paramX:aaa/paramxY:bbb/language:eng
I think this is a routing problem, but I can't figure what is going wrong?
Thank you very much
This is because cakephp doens't find a route in routes.php that corresponds to this link. In other words, you'll have to define this route in the routes.php file
Router::connect('/:language/:controller/:action/:paramX/:paramY');
Once this set, $this->Html->link will output a nice url
I finally did this:
I created a custom CakeRoute, in this cakeRoute, I override the "match" url and the _writeUrl method.
Now every thing is working like a charm :)
For those which are interessted by the route class:
<?php
class I18nRoute extends CakeRoute {
/**
* Constructor for a Route
* Add a regex condition on the lang param to be sure it matches the available langs
*
* #param string $template Template string with parameter placeholders
* #param array $defaults Array of defaults for the route.
* #param string $params Array of parameters and additional options for the Route
* #return void
* #access public
*/
public function __construct($template, $defaults = array(), $options = array()) {
//$defaults['language'] = Configure::read('Config.language');
$options = array_merge((array)$options, array(
'language' => join('|', Configure::read('Config.languages'))
));
parent::__construct($template, $defaults, $options);
}
/**
* Attempt to match a url array. If the url matches the route parameters + settings, then
* return a generated string url. If the url doesn't match the route parameters false will be returned.
* This method handles the reverse routing or conversion of url arrays into string urls.
*
* #param array $url An array of parameters to check matching with.
* #return mixed Either a string url for the parameters if they match or false.
* #access public
*/
public function match($url) {
if (empty($url['language'])) {
$url['language'] = Configure::read('Config.language');
}
if (!$this->compiled()) {
$this->compile();
}
$defaults = $this->defaults;
if (isset($defaults['prefix'])) {
$url['prefix'] = $defaults['prefix'];
}
//check that all the key names are in the url
$keyNames = array_flip($this->keys);
if (array_intersect_key($keyNames, $url) != $keyNames) {
return false;
}
$diffUnfiltered = Set::diff($url, $defaults);
$diff = array();
foreach ($diffUnfiltered as $key => $var) {
if ($var === 0 || $var === '0' || !empty($var)) {
$diff[$key] = $var;
}
}
//if a not a greedy route, no extra params are allowed.
if (!$this->_greedy && array_diff_key($diff, $keyNames) != array()) {
return false;
}
//remove defaults that are also keys. They can cause match failures
foreach ($this->keys as $key) {
unset($defaults[$key]);
}
$filteredDefaults = array_filter($defaults);
//if the difference between the url diff and defaults contains keys from defaults its not a match
if (array_intersect_key($filteredDefaults, $diffUnfiltered) !== array()) {
return false;
}
$passedArgsAndParams = array_diff_key($diff, $filteredDefaults, $keyNames);
list($named, $params) = Router::getNamedElements($passedArgsAndParams, $url['controller'], $url['action']);
//remove any pass params, they have numeric indexes, skip any params that are in the defaults
$pass = array();
$i = 0;
while (isset($url[$i])) {
if (!isset($diff[$i])) {
$i++;
continue;
}
$pass[] = $url[$i];
unset($url[$i], $params[$i]);
$i++;
}
/*
//still some left over parameters that weren't named or passed args, bail.
//We don't want this behavior, we use most of args for the matching, and if we have more, we just allow them as parameters
if (!empty($params)) {
return false;
}*/
//check patterns for routed params
if (!empty($this->options)) {
foreach ($this->options as $key => $pattern) {
if (array_key_exists($key, $url) && !preg_match('#^' . $pattern . '$#', $url[$key])) {
return false;
}
}
}
return $this->_writeUrl(array_merge($url, compact('pass', 'named')));
}
function _writeUrl($params) {
if (isset($params['prefix'], $params['action'])) {
$params['action'] = str_replace($params['prefix'] . '_', '', $params['action']);
unset($params['prefix']);
}
if (is_array($params['pass'])) {
$params['pass'] = implode('/', $params['pass']);
}
$instance =& Router::getInstance();
$separator = $instance->named['separator'];
if (!empty($params['named']) && is_array($params['named'])) {
$named = array();
foreach ($params['named'] as $key => $value) {
$named[] = $key . $separator . $value;
}
$params['pass'] = $params['pass'] . '/' . implode('/', $named);
}
$out = $this->template;
$search = $replace = array();
foreach ($this->keys as $key) {
$string = null;
if (isset($params[$key])) {
$string = $params[$key];
} elseif (strpos($out, $key) != strlen($out) - strlen($key)) {
$key .= '/';
}
$search[] = ':' . $key;
$replace[] = $string;
}
$out = str_replace($search, $replace, $out);
if (strpos($this->template, '*')) {
$out = str_replace('*', $params['pass'], $out);
}
$out = str_replace('//', '/', $out);
//Modified part: allows us to print unused parameters
foreach($params as $key => $value){
$found = false;
foreach($replace as $repValue){
if($value==$repValue){
$found=true;
break;
}
}
if(!$found && !empty($value)){
$out.="/$key:$value";
}
}
return $out;
}
}
And you can set the route like this:
Router::connect('/:language/:controller/*', array(), array('routeClass' => 'I18nRoute'));

Categories