[PHP] Dubbele bestandsnamen hernoemen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb een PHP functie gemaakt die bestandsnamen moet hernoemen op de windows manier. Dus je hebt bestand.jpg, als die al bestaat moet het worden bestand(1).jpg, dan bestand(2).jpg enz. Om de een of andere manier returnt de functie niets bij //HIER. Dit is vreemd, want als ik return "test" doe doet hij het ook niet. Als ik de variabelen voor de return echo dan geeft hij hem wel gewoon weer. De andere 2 returns werken ook gewoon. Heeft iemand een idee waar dit aan kan liggen? Andere opmerkingen zijn ook welkom.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
    public function checkFilename($original)
    {
        if (file_exists($original))
        {
            // haal originele bestandsnaam op
            $getFilename = explode("/",$original);
            $orgFilename = $getFilename[count($getFilename)-1];
            // haal het pad op
            $orgPath = str_replace($orgFilename,"",$original);
            // haal de extensie op
            $getExt = explode(".",$orgFilename);
            $ext = $getExt[count($getExt)-1];
            // haal het gedeelte voor de extensie op (dus bestandsnaam zonder extensie)
            $partBeforeExt = $getExt[count($getExt)-2];
            $length = strlen($partBeforeExt);
            if (substr($partBeforeExt,($length-1),1) == ")")
            {
                // er is al een haakje. haal de posities van de haakjes op om de afstand te bepalen
                $posA = strpos($partBeforeExt,"(");
                $posB = strpos($partBeforeExt,")");
                $distance = $posB - $posA;
                // $n is het nummer tussen de haakjes
                $n = substr($partBeforeExt,($posA+1),($distance-1));
                $newFilename = str_replace("(".$n.")","(".($n+1).")",$orgFilename);
                if (file_exists($orgPath.$newFilename))
                {
                    $this->checkFilename($orgPath.$newFilename);
                } else {
                    //HIER
                    return $orgPath.$newFilename;
                }
            } else {
                return $orgPath.$partBeforeExt."(1).".$ext;
            }
        } else {
            return $original;
        }
    }

Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Het is een recursieve functie en je doet niets met de return-waarde na je recursieve aanroep. Vervolgens gaat je algoritme gewoon door, komt bij het einde van de functie en geeft helemaal niets terug.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Waarom moet je iets doen met de return waarde na de recursieve aanroep? Wat moet je met deze waarde doen dan? Waarom echo't hij wel iets en returnt hij niets? Hoe is dit nu op te lossen?
Het is me nog steeds niet duidelijk waarom het niet werkt.

Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Nu online

MueR

Admin Tweakers Discord

is niet lief

Overigens mag je regel 5 t/m 14 vervangen door de native variant: pathinfo

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Verwijderd schreef op vrijdag 29 januari 2010 @ 15:02:
Waarom moet je iets doen met de return waarde na de recursieve aanroep? Wat moet je met deze waarde doen dan? Waarom echo't hij wel iets en returnt hij niets? Hoe is dit nu op te lossen?
Het is me nog steeds niet duidelijk waarom het niet werkt.
Hij returned wel, maar je doet niets met de return. Het gaat zo:

code:
1
2
3
4
5
6
- start functie
- voer regel 27 uit
  - start functie (recursief !)
  - voer regel 30 uit (de return)
- kom terug op regel 27 en ga verder
- bereik einde van functie en stop


Je doet dus niets met de return die je terug krijgt uit je recursieve aanroep. Je zou regel 27 kunnen vervangen door:

PHP:
1
return $this->checkFilename($orgPath.$newFilename);


Maar iets zegt me dat je dit niet zelf geschreven hebt en je eigenlijk niet weet wat je doet.

[ Voor 4% gewijzigd door HuHu op 29-01-2010 15:12 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
MueR schreef op vrijdag 29 januari 2010 @ 15:09:
Overigens mag je regel 5 t/m 14 vervangen door de native variant: pathinfo
Thanks, dat is wel handig inderdaad. Het is nu dit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    public function checkFilename($original)
    {
        if (file_exists($original))
        {
            $pathInfo = pathinfo($original);
            $partBeforeExt = $pathInfo['filename'];
            $ext = $pathInfo['extension'];
            $orgFilename = $pathInfo['basename'];
            $orgPath = $pathInfo['dirname']."/";
            $length = strlen($partBeforeExt);
            if (substr($partBeforeExt,($length-1),1) == ")")
            {
                // er is al een haakje. haal de posities van de haakjes op om de afstand te bepalen
                $posA = strpos($partBeforeExt,"(");
                $posB = strpos($partBeforeExt,")");
                $distance = $posB - $posA;
                // $n is het nummer tussen de haakjes
                $n = substr($partBeforeExt,($posA+1),($distance-1));
                $newFilename = str_replace("(".$n.")","(".($n+1).")",$orgFilename);
                if (file_exists($orgPath.$newFilename))
                {
                    $this->checkFilename($orgPath.$newFilename);
                    return false;
                } else {
                    //HIER
                    return $this->checkFilename($orgPath.$newFilename);
                }
            } else {
                return $orgPath.$partBeforeExt."(1).".$ext;
            }
        } else {
            return $original;
        }
    }
HuHu schreef op vrijdag 29 januari 2010 @ 15:11:
[...]

Hij returned wel, maar je doet niets met de return. Het gaat zo:

code:
1
2
3
4
5
6
- start functie
- voer regel 27 uit
  - start functie (recursief !)
  - voer regel 30 uit (de return)
- kom terug op regel 27 en ga verder
- bereik einde van functie en stop


Je doet dus niets met de return die je terug krijgt uit je recursieve aanroep. Je zou regel 27 kunnen vervangen door:

PHP:
1
return $this->checkFilename($orgPath.$newFilename);


Maar iets zegt me dat je dit niet zelf geschreven hebt en je eigenlijk niet weet wat je doet.
Waarom gaat hij door na een return? Ik dacht dat het script dan altijd stopte. Moet ik er dan een break achter zetten ofzo?

PHP:
1
return $this->checkFilename($orgPath.$newFilename);


Dat werkt ook niet...

Ik heb het script 100% zelf geschreven, ik weet niet waarom je denkt dat ik het niet zelf geschreven heb. Het is wel de eerste keer dat ik een recursieve functie schrijf.

[ Voor 40% gewijzigd door Verwijderd op 29-01-2010 15:28 ]


Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Oké, het is ook een lastig begrip soms, recursieve functies.

Maar recursieve aanroepen stapelen zich op elkaar. Dus als je functie zichzelf recursief aanroept, dan wacht je "huidige" functie en wordt er een nieuwe functie opgestart (wat dus toevallig dezelfde is). Die functie wordt uitgevoerd en komt bij de return.

Op dat moment kom je dus terug in je originele functie, die de recursieve aanroep deed. Net als bij een normale functie, dan kom je ook terug op de plek waar je gebleven was. Op die plek moet je dus iets doen met de waarde die wordt gereturned door de functieaanroep.

Voorbeeld:

PHP:
1
2
3
4
5
6
7
8
9
10
function a() {
  $a = 2 + 3;
  return $a;
}

function b() {
  $b = 3;
  $a = a();
  return $a + $b;
}


Hier doe je in b() dus iets met de waarde die terug komt uit de functie a. Neem nu een recursieve functie:

PHP:
1
2
3
4
5
6
7
function n($n) {
  if ($n == 0) {
    return 1;
  } else {
    return $n * n($n - 1);
  }
}


Hier gaat hetzelfde als dat b() een aanroep doet naar a(), alleen nu roept n() dus zichzelf aan. Maar het stopt niet automatisch na een return. Na de return ga je terug naar waar je gebleven was in de reeks van aanroepen.

n(5) levert dus 120 op. Schrijf dit maar uit op papier bijvoorbeeld, dan zul je zien hoe het werkt:

code:
1
2
3
4
5
6
7
8
9
n = 5
return 5 * n(4)
  n = 4
  return 4 * n(3)
  ...
    n = 0
    return 1

= 5 * 4 * 3 * 2 * 1 * 1 = 120

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Thx voor de uitleg. Het n() voorbeeld is iets ingewikkelder als mijn functie of ligt dat aan mij?
Ik vind het geheel nog steeds een vaag verhaal, misschien moet ik de recursieve functies eens minder vermijden. Ik snap nu echter nog steeds niet hoe ik mijn probleem op kan lossen.

Acties:
  • 0 Henk 'm!

  • Twan V
  • Registratie: Oktober 2001
  • Laatst online: 16-09 15:39

Twan V

...en er stralend uitzien

"In order to understand recursion, one must first understand recursion."

Recursieve functies zijn een kwestie van even doorhebben.

Zie bijvoorbeeld http://www.phptuts.nl/view/25/3/ of http://www.phpfreakz.nl/a...ecursieve-functies-in-PHP

Blaat het niet dan schaadt het niet...
Reflex Discoshow - Het beste wat je bruiloft kan overkomen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Oke, ik snap nu hoe een recursieve functie werkt. Eigenlijk is er niets veranderd want ik dacht al dat het zo werkte. Toch begrijp ik nog steeds niet waarom mijn functie niet werkt. Hoe kan ik ervoor zorgen dat mijn script de juiste waarde returnt en daarna stopt?

Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Nu online

MueR

Admin Tweakers Discord

is niet lief

Door de recursieve aanroep ook te laten returnen zoals je in Verwijderd in "[PHP] Dubbele bestandsnamen hernoemen" ook al vroeg. Dan wordt de functie eerst nog een keer aangeroepen (of zovaak als nodig is) en de uiteindelijke uitkomst geretourneerd.

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ow, nu snap ik het! Ik was trouwens op regel 29 bezig waardoor ik het niet snapte... Het is in ieder geval een stuk duidelijker geworden. Bedankt voor jullie hulp allemaal!

EDIT: heb nog een kleine aanpassing gemaakt want hij deed het niet helemaal. Als je x.jpg had en x.jpg en x(1).jpg bestonden al, gaf hij x(1).jpg terug, terwijl dit x(2).jpg moet zijn. Hieronder nog de hele functie voor als iemand hem wil gebruiken:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
    public function checkFilename($original)
    {
        if (file_exists($original))
        {
            $pathInfo = pathinfo($original);
            $partBeforeExt = $pathInfo['filename'];
            $ext = $pathInfo['extension'];
            $orgFilename = $pathInfo['basename'];
            $orgPath = $pathInfo['dirname']."/";
            $length = strlen($partBeforeExt);
            if (substr($partBeforeExt,($length-1),1) == ")")
            {
                // er is al een haakje. haal de posities van de haakjes op om de afstand te bepalen
                $posA = strpos($partBeforeExt,"(");
                $posB = strpos($partBeforeExt,")");
                $distance = $posB - $posA;
                // $n is het nummer tussen de haakjes
                $n = substr($partBeforeExt,($posA+1),($distance-1));
                $newFilename = str_replace("(".$n.")","(".($n+1).")",$orgFilename);
                if (file_exists($orgPath.$newFilename))
                {
                    return $this->checkFilename($orgPath.$newFilename);
                } else {
                    return $orgPath.$newFilename;
                }
            } else if (file_exists($orgPath.$partBeforeExt."(1).".$ext)) {
                // er is nog geen haakje, maar er is wel een bestand (1)
                return $this->checkFilename($orgPath.$partBeforeExt."(1).".$ext);
            } else {
                return $orgPath.$partBeforeExt."(1).".$ext;
            }
        } else {
            return $original;
        }
    }

[ Voor 81% gewijzigd door Verwijderd op 29-01-2010 20:33 ]

Pagina: 1