Come risolvere "deve essere un'istanza di stringa, stringa fornita" prima di PHP 7?


217

Ecco il mio codice:

function phpwtf(string $s) {
    echo "$s\n";
}
phpwtf("Type hinting is da bomb");

Che si traduce in questo errore:

Errore irreversibile irreversibile: l'argomento 1 passato a phpwtf () deve essere un'istanza di stringa, stringa fornita

È più che un piccolo orwelliano vedere PHP riconoscere e rifiutare il tipo desiderato nello stesso respiro. Ci sono cinque luci, accidenti.

Qual è l'equivalente del tipo di suggerimento per le stringhe in PHP? Considerazione del bonus sulla risposta che spiega esattamente cosa sta succedendo qui.


5
Bene, questo è perché stai sbagliando. Il tuo codice non dovrebbe funzionare, tanto per cominciare. Leggi sul tipo di giocoleria nei documenti PHP. PHP è di tipo dinamico e di tipo debole. Puoi usare (stringa) per trasmettere un argomento a stringa (solo nel corpo della funzione), ma puoi solo suggerire oggetti e matrici come fai nel tuo frammento di codice.
Richard Knop,

7
Il problema è che hai fatto un piccolo errore. Ci sono quattro luci!
CJ Dennis,

@ Gordon, ho provato il 5.6. Ancora niente fortuna.
Pacerier,

@Pacerier Seguire wiki.php.net/rfc per gli ultimi sviluppi.
Gordon,

3
Apparentemente, il suggerimento scalare del tipo (come prevedeva intuitivamente OP come una cosa sopra) è stato finalmente approvato sotto una RFC per PHP * 7 * secondo la fonte . Apparentemente la RFC approvata fornisce anche zucchero sintattico per la verifica del tipo di valori di ritorno e parametri (argomenti). È passato molto tempo.
SeldomNeedy,

Risposte:


204

Prima di PHP 7, il suggerimento sul tipo può essere utilizzato solo per forzare i tipi di oggetti e array. I tipi scalari non sono tipizzabili. In questo caso stringè previsto un oggetto della classe , ma gli stai dando un (scalare) string. Il messaggio di errore può essere divertente, ma all'inizio non dovrebbe funzionare. Dato il sistema di battitura dinamico, questo ha effettivamente una sorta di senso perverso.

Puoi solo manualmente tipi scalari di "suggerimento":

function foo($string) {
    if (!is_string($string)) {
        trigger_error('No, you fool!');
        return;
    }
    ...
}

1
@deceze, esiste una sintassi per i suggerimenti di tipo inverso? Ad esempio tutto tranne che array.
Pacerier,

@Pacerier No, non c'è.
Inganno

4
Questa risposta non è valida per PHP 7
Jose Nobile il

24

Dal manuale di PHP :

I suggerimenti sul tipo possono essere solo di tipo oggetto e matrice (dal PHP 5.1). L'hint di tipo tradizionale con int e stringa non è supportato.

Quindi ce l'hai. Il messaggio di errore non è davvero utile, ti do questo però.

** 2017 Modifica **

PHP7 ha introdotto più dichiarazioni sui tipi di dati delle funzioni e il collegamento sopra menzionato è stato spostato in Argomenti delle funzioni: dichiarazioni di tipo . Da quella pagina:

Tipi validi

  • Nome classe / interfaccia : il parametro deve essere un'istanza della classe o del nome interfaccia indicati. (da PHP 5.0.0)
  • self : il parametro deve essere un'istanza della stessa classe di quella su cui è definito il metodo. Questo può essere utilizzato solo su metodi di classe e istanza. (da PHP 5.0.0)
  • array : il parametro deve essere un array. (da PHP 5.1.0) richiamabile Il parametro deve essere un richiamo valido. PHP 5.4.0
  • bool : il parametro deve essere un valore booleano. (dal PHP 7.0.0)
  • float : il parametro deve essere un numero in virgola mobile. (dal PHP 7.0.0)
  • int : il parametro deve essere un numero intero. (dal PHP 7.0.0)
  • stringa : il parametro deve essere una stringa. (dal PHP 7.0.0)
  • iterable : il parametro deve essere un array o un'istanza di Traversable. (da PHP 7.1.0)

avvertimento

Gli alias per i precedenti tipi scalari non sono supportati. Invece, vengono trattati come nomi di classe o interfaccia. Ad esempio, l'utilizzo di booleano come parametro o tipo restituito richiederà un argomento o un valore restituito che sia un'istanza della classe o dell'interfaccia booleana, anziché del tipo booleano:

<?php
   function test(boolean $param) {}
   test(true);
 ?>

L'esempio sopra mostrerà:

 Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of boolean, boolean given, called in - on line 1 and defined in -:1

L'ultimo avvertimento è in realtà significativo per comprendere l'errore "L'argomento deve essere di tipo stringa, stringa fornita"; dato che principalmente sono consentiti solo nomi di classe / interfaccia come tipo di argomento, PHP cerca di individuare un nome di classe "stringa", ma non ne trova nessuno perché è un tipo primitivo, quindi fallisce con questo errore imbarazzante.


8

PHP consente il "suggerimento" in cui si fornisce una classe per specificare un oggetto. Secondo il manuale di PHP, "I suggerimenti sul tipo possono essere solo di tipo oggetto e matrice (dal momento che PHP 5.1). Il suggerimento di tipo tradizionale con int e stringa non è supportato." L'errore è confuso a causa della tua scelta di "stringa" - metti "myClass" al suo posto e l'errore leggerà diversamente: "L'argomento 1 passato a phpwtf () deve essere un'istanza di myClass, stringa data"


3

Come altri hanno già detto, il suggerimento sui tipi attualmente funziona solo per i tipi di oggetti. Ma penso che il particolare errore che hai innescato potrebbe essere in preparazione del tipo di stringa imminente SplString .

In teoria si comporta come una stringa, ma poiché è un oggetto passerebbe la verifica del tipo di oggetto. Purtroppo non è ancora in PHP 5.3, potrebbe arrivare in 5.4, quindi non l'ho provato.


2

Dal PHP 7.0 dichiarazioni di tipo consentono tipi scalari, in modo che questi tipi sono ora disponibili: self, array, callable, bool, float, int, string. I primi tre erano disponibili in PHP 5, ma gli ultimi quattro sono nuovi in ​​PHP 7. Se usi qualcos'altro (ad es. integerO boolean) che verrà interpretato come un nome di classe.

Consulta il manuale di PHP per ulteriori informazioni .


0

Forse non è sicuro e carino ma se devi:

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

    public function __toString()
    {
        return $this->Text;
    }
}

function Test123(string $s)
{
    echo $s;
}

Test123(new string("Testing"));

5
Potrei ancora creare unnew string(array(1,2,3))
Jimmy T. il

0

Ho ricevuto questo errore quando ho invocato una funzione da un controller Laravel a un file PHP.

Dopo un paio d'ore, ho riscontrato il problema: stavo usando $ this all'interno di una funzione statica.


Using $this when not in object contextè davvero un messaggio criptico.
Ben Fransen,

0

(originariamente pubblicato da leepowers nella sua domanda)

Il messaggio di errore è confuso per un grande motivo:

I nomi dei tipi primitivi non sono riservati in PHP

Di seguito sono riportate tutte le dichiarazioni di classe valide:

class string { }
class int { }
class float { }
class double { }

Il mio errore è stato nel pensare che il messaggio di errore si riferisse esclusivamente al tipo di stringa primitiva - la parola 'istanza' avrebbe dovuto darmi una pausa. Un esempio per illustrare ulteriormente:

class string { }
$n = 1234;
$s1 = (string)$n;
$s2 = new string();
$a = array('no', 'yes');
printf("\$s1 - primitive string? %s - string instance? %s\n",
        $a[is_string($s1)], $a[is_a($s1, 'string')]);
printf("\$s2 - primitive string? %s - string instance? %s\n",
        $a[is_string($s2)], $a[is_a($s2, 'string')]);

Produzione:

$ s1 - stringa primitiva? sì - istanza di stringa? no

$ s2 - stringa primitiva? no - istanza di stringa? sì

In PHP è possibile che stringa sia un stringtranne quando in realtà è un string. Come con qualsiasi linguaggio che utilizza la conversione di tipo implicito, il contesto è tutto.


-1

Penso che il typecasting su php all'interno del blocco, String su PHP non sia oggetto come lo so:

<?php
function phpwtf($s) {
    $s = (string) $s;
    echo "$s\n";
}
phpwtf("Type hinting is da bomb");

2
È possibile aggiungere la convalida is_string () all'interno della funzione per impedire che altri valori vengano passati alla funzione.
subosito

1
(string) $spotrebbe generare un errore se $sè un oggetto che non può essere inserito in una stringa (non ha alcun __toString()metodo implementato), quindi non è così semplice
Yanick Rochon,

Sì Yanick hai ragione. Ma non possiamo costringere tutti gli input a essere stringhe, giusto? ecco perché l'eccezione viene a giocare. Possiamo combinare una sorta di convalide e cogliere l'eccezione per il resto;)
subosito

Sto solo dicendo che il cast di una variabile su stringa senza prima verificare se la variabile può essere lanciata dovrebbe essere evitato, principalmente perché catturare le eccezioni è costoso e porta a cattivi modelli di progettazione / habbit di codifica.
Yanick Rochon,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.