Zur Navigation

Missing Argument...

1 Isildur

Ich hab heute wieder etwas an meiner Webseite weiter geschrieben, lief auch alles gut und dann tauchte auf einmal ein Fehler auf. "Missing argument 1 for all() ..."
Ich kann mir das nicht erklären, vielleicht bin ich auch blind.

Code im Index
include "all_class.php";
$all = new All($all);
Code der Klassendatei(Ausschnitt)
	function All($all){
//usw
}

ps:ist noch PHP4 daher die Synax.

Klingt wieder nach so einem blöden kleinen Fehler aber ich bin irgendwie nicht fündig geworden.

31.08.2006 20:23

2 Jörg Kruse

Müsstest du $all nicht erst einen Wert zuweisen, bevor du es als Argument einer Funktion verwenden kannst?

$all = "irgendwas";
include "all_class.php";
$all = new All($all);

31.08.2006 20:37

3 Isildur

Nach längerem Ausprobieren habe ich den Fehlerbereich eingrenzen können. Zunächst der ges. Konstruktor(kann unlogische und falsche Teile enthalten, ich bin immernoch in einer Lernphase und probiere aus).
	function All($all){
		include "db_class.php";
		include "form_class.php";
		include "navi_class.php";
		include "display_class.php";
		if($_SESSION['objects']!="true"){//if objects are not saved in the session(first visit or failure) they will be set
			$db = new DB;
			$form = new Form;
			$navi = new Navi;
			$display = new Display;
			$objects = array(
								"all"=>$all,
								"db"=>$db,
								"form"=>$form,
								"navi"=>$navi,
								"display"=>$display,
								"obejects"=>"true"
								);
			foreach($objects as $name=>$object){
				$_SESSION['$name'] =& $object;
			}
		}else{//if they are set, the acces is simplified
			$db =& $_SESSION['db'];
			$form =& $_SESSION['form'];
			$navi =& $_SESSION['navi'];
			$display =& $_SESSION['display'];
		}
		//show different parts of the site
		$display->headshow();
		$display->topshow();
		$display->navishow();
		$display->rightshow();
		$display->contentshow();
		$display->footershow();	
	}
Der problematische Teil ist
$db = new DB;
			$form = new Form;
			$navi = new Navi;
			$display = new Display;
Wenn ich die auskommentiere verschwindet der Fehler und es kommt nur noch

Fatal error: Call to a member function on a non-object
bezogen auf die erste Zeile mit $display->...

Nur versteh ich den Zusammnenhang nicht, geschweige denn meinen Fehler.

Achja ich hatte vorhin noch was vergessen, war nur erstmal chronologisch vorgegangen und wollte erst die Warnung beseitigen. Hier die vollständige Fehlermeldung

Warning: Missing argument 1 for all() in D:\XAMPP\xampp\htdocs\myrkwid2\all_class.php on line 6

Fatal error: Cannot redeclare class db in D:\XAMPP\xampp\htdocs\myrkwid2\db_class.php on line 2

31.08.2006 21:33 | geändert: 31.08.2006 21:37

4 Jörg Kruse

Tritt der fatal error noch auf, wenn du db_class.php mit require_once() oder include_once() einbindest?

function All($all){
include_once "db_class.php";

31.08.2006 23:15

5 Isildur

Ja es tritt dann immernoch auf, je nachdem welche ich auskommentiere wird es periodisch. Ich habe aber etwas anderes festgestellt. Es scheint mit dem extends zusammen zu hängen. Ich habe die anderen Klasse als
class Navi extends All{...}
etc definiert. Dadurch scheint PHP bei der Erzeugung einer Intanz der Klasse Navi ebenfalls einen Parameter zu erwarten. Wenn ich nun leere Konstruktoren für die Klassen erstelle scheint es zu funktionieren.

01.09.2006 14:43

6 Rudy

Wenn Du eine extends-Klasse schreibst, dann erwartet das erbende Objekt auch die Konstruktor-Parameter des Parents. Sonst kann ja der Parent nicht erzeugt werden, der aber einen Teil des Childs ist, dass Du mit extends definierst. Du kannst nur Parameter hinzugeben, aber keine weglassen.

Zu Deinem vorigen Problem: Das scheint mir alles sehr unlogisch aufgebaut zu sein, und das ist auch der Knackpunkt : es kann so nicht funktionieren.

1) Du bindest die Klassen-Files innerhalb des Konstruktors von All ein (das soll ein Repository werden, oder?) - das finde ich schon mal sehr gewagt, würde ich nicht dazu raten - kA ob das überhaupt funktioniert, ich hab nie getestet, Klassen innerhalb eines Konstruktors zu deklarieren

2) $_SESSION['objects'] wird nie true (da steht obejects)

3) Du verwendest in All lokale Variablen des Konstruktors, anstatt deklarierte Objekt-Variablen ($this), d.h. das Repository ist damit ziemlich unnütz, denn als Variablen stehen Dir die Objekte nur im Konstruktor von All zur Verfügung, außerhalb bzw. in einer anderen Methode von All musst Du immer wieder an die Session linken.

4) Alle Objekte in der Session sind beim Neuaufruf verloren, weil Du die Session an lokale Objekte bindest und nicht umgekehrt (der Speicherbereich, den Du mit new definierst, gilt nur innerhalb des Konstruktors)

5) den Parameter $all im Konstruktor von All verstehe ich nicht :) Wozu ist der da?

Ich würde Dir zu einer sichereren Variante raten (vorsicht, ungetestet):

<?php

require_once "db_class.php";
require_once "form_class.php";
require_once "navi_class.php";
require_once "display_class.php";
 
class All {

  var $db;
  var $form;
  var $navi;
  var $display;

  function All(){
  
   if(!isset($_SESSION['objects']) || !$_SESSION['objects']){
      //if objects are not saved in the session(first visit or failure) they will be set
 	  $_SESSION['db'] = new DB;
	  $this->db =& $_SESSION['db'];
	  $_SESSION['form'] = new Form;
	  $this->form =& $_SESSION['form'];
	  $_SESSION['navi'] = new Navi;
	  $this->navi =& $_SESSION['navi'];
	  $_SESSION['display'] = new Display;
	  $this->display =& $_SESSION['display'];
	  $_SESSION['objects'] = true;
    } else {
	  //if they are set, the access is simplified
	  $this->db =& $_SESSION['db'];
	  $this->form =& $_SESSION['form'];
	  $this->navi =& $_SESSION['navi'];
	  $this->display =& $_SESSION['display'];
    }
  }
  
  function showSiteParts() {
	//show different parts of the site
	$this->display->headshow();
	$this->display->topshow();
	$this->display->navishow();
	$this->display->rightshow();
	$this->display->contentshow();
	$this->display->footershow();
  }

 session_start();

 $all = new All;
 $all->showSiteParts();
 
?>

01.09.2006 20:33

7 Isildur

Vielen Dank!
Zu 1. Ja das funktioniert durchaus.
2.&3.Jap danke war mir auch aufgefallen
4.Ups äh ja man sollte schon aufpassen was man da schreibt
5.War gedacht um auch das Objekt "all" den Sessions übergeben zu können, ob das sinnvoll ist keine Ahnung, das ganze hat sowieso mehr Experiementcharakter aber so lern ich am meisten, ausprobieren und gucken obs geht^^.

Es geht jetzt soweit, vielen Dank nochmal für die Mühe!
Was allerdings noch ein Problem ist, wenn ich nun die Methode eines dieser Objekte aufrufen möchte und schreibe
$this->navi->methode();
kommt
Fatal error: Call to a member function on a non-object
Wie mach ich das dann richtig?

02.09.2006 00:52 | geändert: 02.09.2006 01:04

8 Rudy

Innerhalb einer Methode des Objekts 'all' rufst Du wie Du richtig gesagt hast mit $this->navi->methode(); auf - stell aber sicher, dass Du die Session abbrichst, bevor Du eine neue hinzugefügte Methode ausprobierst (Browser ganz schließen), sonst ist immer noch das alte erzeugte Objekt im Speicher.
Ein einfacher Mechanismus mit dem Du $_SESSION['objects'] auf false stellst wäre auch tauglich um die Objekte während der selben Session neu zu laden.

Außerhalb von $all rufst Du die Methode - nachdem das $all objekt erzeugt wurde - mit $all->navi->methode(); auf.

'Non object' heißt, dass da was ziemlich schiefgelaufen ist, d.h. das Objekt wurde nicht erzeugt, in der Zwischenzeit überschrieben oder falsch an die Variable gelinkt - im Beispiel oberhalb kann ich das aber nicht nachvollziehen.

02.09.2006 15:38 | geändert: 02.09.2006 15:45

9 Isildur

Ich habe die Seite jetzt nochmal umstrukturiert und jetzt gehts(siehe unten). Ich habe allerdings noch eine Frage. Wenn ich einer einer Extendsklasse ein Attribut der Klasse All änder, ändert es sich dann ist es dann für alle Klasse die auf dieses Attribut der Klasse all geändert? Kurzes Bsp.
//in all
var $att;
//in navi(extends all)
$this->att = "blub";
//in display(extends all)
echo $this->att;//gibt das jetzt blub aus?
Der Code jetzt
Index
include "all_class.php";
include "form_class.php";
include "navi_class.php";
include "display_class.php";
include "db_class.php";
$_SESSION['all'] = new All;
$_SESSION['all']->start();
Klasse all
function All(){
		$this->db =& $_SESSION['db'];
		$this->form =& $_SESSION['form'];
		$this->navi =& $_SESSION['navi'];
		$this->display =& $_SESSION['display'];

	}
	function start(){
		$_SESSION['db'] = new DB;
		$_SESSION['form'] = new Form;
		$_SESSION['navi'] = new Navi;
		$_SESSION['display'] = new Display;
		$this->db->connect();
		//show different parts of the site
		$this->display->showhead();
		$this->display->showtop();
		$this->display->shownavi();
		$this->display->showright();
		$this->display->showcontent();
		$this->display->showfooter();
	}

02.09.2006 18:40

10 Rudy

Jetzt erzeugst Du bei jedem Aufruf die Objekte neu, aber das wolltest Du wohl so? Vergiss nicht, dass dadurch alle Werte auf dem Objekt zurückgesetzt werden, also was Du einmal auf dem Objekt speicherst, ist beim 2. Aufruf verloren, die Klassendefinitionen müssen zugleich immer neu ausgelesen werden.

gibt das jetzt blub aus?
Nein. Extends funktioniert etwas anders als Du es glaub ich annimmst.

class A {
  var $var1;
  function foo() {
    echo $var1;
  }
}

class B extends A {
  var $var2;
  function bar() {
    $this->foo(); //gibt $var1 aus
    echo $var2;
  }
}

$b = new B;
$a = new A;

$b->var1 = 3;
$a->var1 = 2;

echo $b->var1; //ist immer noch 3

Du extendest die Klasse, nicht das Objekt. Das aus der Klasse 'B' erzeugte Objekt erbt nur die Deklaration der Variable $var1 und die Funktion foo(), nicht aber die Werte der Variablen (außer der Default-Werte, aber die sind nicht angegeben, also sind nach dem Erzeugen der Objekte die Variablen $var1(A und B), $var2(B) leer).
Wenn Du irgendwo in ein aus der Klasse 'A' erzeugtes Objekt einen Wert schreibst, hat das keine Auswirkungen auf 'B', denn es ist ein anderes Objekt - nur die Klassendefinition wird geerbt.


02.09.2006 19:24