Jak przekazać parametr do fukncji fwrite ?

0

Mam problem z plikiem. Chodzi o funkcję WriteFile() gdzie do funkcji fwrite przekazuję jako parametr wartość z funkcji ifExist(), tylko pojawia się błąd o treści:

Fatal error: Uncaught TypeError: fwrite(): Argument #1 ($stream) must be of type resource, null given in.

Nie wiem, czemu tak jest.

<?php

class File
{
    public function __construct()
    {
    }

    public function ifExist(): void
    {

        if(file_exists("text.txt"))
        {
          echo 'Plik istnieje';
        }else
            echo "Pliku nie ma";

    }

    public function openFile()
    {
        $plik=fopen("text.txt", "w") or die("Nie udało się utworzyć pliku");

    }

    public function WriteFile(): void
    {
        $zawartosc = "Przykładowa treść, którą umieścimy w pliku.";
        fwrite($this->openFile(), $zawartosc) or die("Nie udało się zapisać danych w pliku");
    }
}
2

Tak na pierwszy rzut oka (ale nie sprawdzę teraz tego, więc może nie mam racji):

Jako parametr fwrite przekazujesz $this->openFile(). W tym openFile() korzystasz z jakiegoś $plik, ale nigdzie go nie przekazujesz dalej, czyli poza tą funkcją $plik nie istnieje, brakuje czegoś w stylu return($plik);. funkcja fwrite oczekuje jakiegoś zasobu, a otrzymuje null'a bo $this->openFile() niczego nie zwraca.

0

Chodzi mi o tą funkcję, nw jaki ona tryb zwraca. Według mnie powinna zwracać void ale wtedy nie mogę dać returna. Próbowałem już stringa, int, ale wtedy pokazuje błąd

public function openFile() {
  $plik=fopen("text.txt", "w") or die("Nie udało się utworzyć pliku");

  return $plik;
}
2

No więc tak, po pierwsze co do fwrite() to to są takie niskopoziomowe funkcje, które są trochę trudniejsze w użyciu niż inne funkcje w PHP, ale za to dają większą kontrolę nad tym co PHP robi z systemem pików, także coś za coś.

Co do fwrite(), to jak zajrzysz do dokumentacji: https://www.php.net/manual/en/function.fwrite.php to zobaczysz że jest dokładnie tak jak @cerrato mówił, czyli pierwszy argument fwrite() to jest resource, wskaźnik na zasób.

Więc jeśli chcesz koniecznie to zapisać tak "żeby działało", to zrób tak:

<?php

class File
{
    public function openFile(): resource
    {
        return fopen("text.txt", "w") or die("Nie udało się utworzyć pliku");
    }

    public function WriteFile(): void
    {
        $zawartosc = "Przykładowa treść, którą umieścimy w pliku.";
        fwrite($this->openFile(), $zawartosc) or die("Nie udało się zapisać danych w pliku");
    }
}

Aczkolwiek tutaj jest kilka dziwnych błędów. Widać że próbujesz to zrobić obiektowo, ale niczego nie enkapsulujesz. Dodatkowo posługujesz się die(), zamiast wyjątakmi, co ma tą wadę że ubijesz proces. Ja bym to zrobił bardziej tak:

<?php

class File
{
    private string $filename;
    
    public function __construct(string $filanem)
    {
      $this->filename = $filename;
    }

    public function exists(): bool
    {
       return file_exists($this->filename);
    }

    public function write(string $data): void
    {
        $result = fwrite($this->openedFile(), $data);
        if ($result === false) {
          throw new Exception("Nie udało się zapisać danych w pliku");
        }
    }

    /**
     * @return resource
     */
    private function openedFile()
    {
        $file = fopen($this->filename, "w");
        if ($file === false) {
           throw new Exception("Nie udało się utworzyć pliku")
        }
        return $file;
    }
}

i użycie:

<?php

$file = new File("mój plik.php");
if ($file->exists()) {
  echo "plik istnieje";
} else {
  echo "plik nie istnieje";
}
$file->write("Jakieś dane");
1
php22 napisał(a):

I jeszcze mam pytanie, ponieważ w pliku text.txt mam zapisany jakis tekst, i teraz jak wywołuję funkcję write to tamten tekst jest kasowany i zapisywany tylko ten który zapsiuje funkcja. nw czemu funkcja kasuje tamten tekst, tryb otwierania jest przeciez poprawny

No, to zazwyczaj jest spodziewane i pożądane zachowanie. Znaczna większość formatów nie jest "addytywna", tzn nie można sobie po prostu "dokleić treści" na koniec i spodziewać się że format zostanie zachowany, JSON, XML, HTML i masa innych formatów nie ma takiej cechy.

Jest część formatów, w których faktycznie przez doklejenie treści na koniec, w pewnych konkrentych warunkach można uznać za poprawne, np w YAML, i Markdown, ale też nie zawsze - bo np jak nie ma znaku nowej linii \n na końcu pliku, to też możesz zepsuć format.

Także nadpisywanie treści w pliku to jest reguła - 99% użyć. Addytywne dopisywanie do pliku to wyjątek, który często można nazwać optymalizacją. Jak teraz myślę to chyba tylko zapisywanie logów działa addytywnie w miarę rzetelnie. Inne formaty, raczej nie.

Co do trybu otwierania plików, to nie masz racji, bo "w" otwiera plik do zapisu i robi "seek" na początek pliku, czyli od początku odbywa się pisanie.

0
TomRiddle napisał(a):
php22 napisał(a):

Ale teraz pokazuje błąd, że resource nie jest typem zmiennej. Warning: "resource" is not a supported builtin type and will be interpreted as a class name.

1
php22 napisał(a):
TomRiddle napisał(a):
php22 napisał(a):

Ale teraz pokazuje błąd, że resource nie jest typem zmiennej. Warning: "resource" is not a supported builtin type and will be interpreted as a class name.

No bo PHP jest zwalony. Nie możesz zrobić type-hinta z resource.

Jeśli chcesz, to możesz zrobić

/**
 * @return resource
 */
public function file() {
}
0

Taki kod stworzyłem, mam nadzieję ze jest poprawny, poza tym wszystko działa jak należy. Usunąłem tę funkcję odpowiadającą za otwarcie pliku, ponieważ musiał bym wtedy 2 stworzyć, wiec moim zdaniem nie ma to sensu.

<?php

class File
{
    private string $filname;
    public function __construct(string $filname)
    {
        $this->filname = $filname;
    }

    public function ifExist(): bool
    {
        return file_exists($this->filname);
    }

    public function Write(array $data): void
    {
        $file = fopen($this->filname, "w");
        $dane = implode($data);

        $result= fwrite($file, $dane);

        if($result === false){
            throw new Exception("Nie udało się zapisac danych do pliku");
        }
    }

    public function Read(): string
    {
        $file = fopen($this->filname, "r");
        $content = '';

        while (!feof($file))
        {
            $line = fgets($file);
            $content .= $line;
        }
        return $content;
    }
}
1
php22 napisał(a):

Taki kod stworzyłem, mam nadzieję ze jest poprawny, poza tym wszystko działa jak należy. Usunąłem tę funkcję odpowiadającą za otwarcie pliku, ponieważ musiał bym wtedy 2 stworzyć, wiec moim zdaniem nie ma to sensu.

Dużo małych funkcji nie zawsze jest gorsze niż jedna duża. Taki podział poprawia czytelność.

A co do samego kodu, słyszałeś o takich funkcjach jak file_get_contents() oraz file_put_contents()? Uprościłyby Ci troszkę tę klasę.

https://www.php.net/manual/en/function.file-get-contents.php
https://www.php.net/manual/en/function.file-put-contents.php

PS: Czemu nazywasz funkcję ifExist() zamiast exists()?

1 użytkowników online, w tym zalogowanych: 0, gości: 1