0

I have PHP 5.6.10 under MAMP in my local testing server and this class working fine. But when I upload it to the web host server with PHP 5.6.31, it displays the following error:

Warning: Invalid argument supplied for foreach() in /.../_amb.php on line 79

The class (_amb.php) is for creating a simple object with data and some functions about the environment (default paths, urls, etc.). Let's see the class...

// Ambiente do sistema
class _amb {

    var $erro = FALSE; // Boolean FALSE | String
    var $msg = "";
    var $descr = "Indefinido...";

    // String
    var $host;
    var $protocolo;

    // String
    var $dir;
    var $dirBibPhp;
    var $dirBibJs;
    var $dirJGp;
    var $url;
    var $urlBibPhp;
    var $urlBibJs;
    var $urlJGp;

    var $Hosts = [];

    var $HostsPerms = FALSE; // Boolean FALSE | Array

    var $HostsIni = ["localhost"=>[
            "descr"=>"Servidor de testes local",
            "dir"=>'/Applications/MAMP/htdocs/js_bib/',
            "dirBibPhp"=>'/Applications/MAMP/htdocs/php_bib/',
            "dirBibJs"=>'/Applications/MAMP/htdocs/js_bib/',
            "dirJGp"=>'/Applications/MAMP/htdocs/jGp/',
            "url"=>'{protocolo}://{host}/js_bub/',
            "urlBibPhp"=>'{protocolo}://{host}/php_bib/',
            "urlBibJs"=>'{protocolo}://{host}/js_bib/',
            "urlJGp"=>'{protocolo}://{host}/jGp/'
        ]];

    public function _amb($XtraHosts=FALSE, $HostsPerimitidos=FALSE){
        $this->host = $_SERVER["HTTP_HOST"];
        $P = explode("/", $_SERVER["SERVER_PROTOCOL"]);
        $this->protocolo = $P[0];
        $this->Hosts = $this->HostsIni;
        if($HostsPerimitidos) $this->HostsPerms = (gettype($HostsPermitidos)=="string")? explode(",", $HostsPerimitidos) : $HostsPermitidos ;
        if($XtraHosts) {
            $this->import($XtraHosts);
        } else {
            $this->def();
        }
    }

    private function def(){
        $teste = (gettype($this->HostsPerms)=="array")? in_array($this->host, $this->HostsPerms) : TRUE ;
        if(!$teste){
            $this->reset();
            $this->erro = "não permitido";
            $this->msg = "Host ".$this->host." não permitido.";
        } else {
            $Defs = $this->Hosts[$this->host];
            if(gettype($Defs)!="array"){
                $this->reset();
                $this->erro = "não identificado";
                $this->msg = "Host ".$this->host." não identificado.";
            } else {
                foreach($Defs as $var=>$val){
                    $v = $val;
                    $v = str_replace("{raiz}", getcwd(), $v);
                    $v = str_replace("{protocolo}", $this->protocolo, $v);
                    $v = str_replace("{host}", $this->host, $v);
                    $this->$var = $v;
                }
                $this->erro = FALSE;
                $this->msg = "";
            }
        }
    }

    private function reset(){
        foreach($this->HostsIni[0] as $var=>$val){ //<--line 79
            $this->$var = NULL;
        }
    }

    public function isMobile() {
        return (bool)preg_match('#\b(ip(hone|od)|android\b.+\bmobile|opera m(ob|in)i|windows (phone|ce)|blackberry'.
                    '|s(ymbian|eries60|amsung)|p(alm|rofile/midp|laystation portable)|nokia|fennec|htc[\-_]'.
                    '|up\.browser|[1-4][0-9]{2}x[1-4][0-9]{2})\b#i', $_SERVER['HTTP_USER_AGENT'] );
    }

    public function export($saida="json"){
        $Def = [
            "erro"=>$this->erro,
            "msg"=>$this->msg,
            "descr"=>$this->descr,
            "dir"=>$this->dir,
            "dirBibPhp"=>$this->dirBibPhp,
            "dirBibJs"=>$this->dirBibJs,
            "dirJGp"=>$this->dirJGp,
            "url"=>$this->url,
            "urlBibPhp"=>$this->urlBibPhp,
            "urlBibJs"=>$this->urlBibJs,
            "urlJGp"=>$this->urlJGp
            ];
        switch($saida){
            case "json":
                return json_encode((object)$Def);
                break;
            case "html":
                $html = '<table>';
                foreach($Def as $var=>$val){
                    $html .= '<tr><td>'.$var.'</td><td>'.$val.'</td></tr>';
                }
                $html .= '</table>';
                return $html;
                break;
            case "array":
                return $Def;
                break;
        }
    }

    public function import($Hosts){
        switch(gettype($Hosts)){
            case "array":
                $this->Hosts = array_merge($this->Hosts, $Hosts);
                $this->def();
                break;
            case "string":

                break;
            default:
                $this->reset();
                $this->erro = "Hosts";
                $this->msg = "Argumento inválido para ::import (".gettype($Hosts).")";
        }
    }
}

?>

The line 79 is the "foreach" of the reset method (private function reset()), a simple routine to clear the data. The class is working properly, the website works, despite the error message. It could be a context error, the Array is not found, but in my local MAMP, the PHP do find it.

Can't understand why it works in my notebook and not in the web host. Is there a difference I don't know between those PHP versions?

Gustavo
  • 1,673
  • 4
  • 24
  • 39
  • 1
    `$this->HostsIni[0]` should be `$this->HostsIni['localhost']` based on your property definition – Mark Baker Nov 01 '17 at 15:58
  • 2
    and please don't use `var` for defining properties; give them a proper visibility; `var` is a throwback to PHP4 – Mark Baker Nov 01 '17 at 15:58
  • Using var in classes: https://stackoverflow.com/questions/1206105/what-does-php-keyword-var-do – Nic3500 Nov 01 '17 at 16:02
  • @MarkBaker I really didn't know about that! So should I replace it by private or public? Will update all my classes, never liked var anyway... – Gustavo Nov 01 '17 at 16:20

1 Answers1

0

You probably don't get the error because the error level is different on the web host and the warning is ignored, and you your server the error reporting level is lower so you get this. The problem is that you don't have an element with key 0 in your array, as I see it. You should do something like this:

private function reset(){
    foreach($this->HostsIni as $host=>$arr){
        foreach($arr as $var=>$val){ //<--line 79
            $this->$var = NULL;
        }
    }
}
KiloByte
  • 94
  • 3
  • In my notebook, I use ini_set("display_errors", "1"); error_reporting(E_ALL ^ E_NOTICE);. Your suggestion works! However, the point is to get the first (or any) of HostsIni only to have the keys - will be always the same keys. I just ask you to complete your answer with this solution: to get the first item of HostsIni to a single foreach. – Gustavo Nov 01 '17 at 16:29