{"id":736,"date":"2020-07-17T15:22:01","date_gmt":"2020-07-17T20:22:01","guid":{"rendered":"https:\/\/drmad.org\/blog\/?p=736"},"modified":"2021-03-02T22:12:44","modified_gmt":"2021-03-03T03:12:44","slug":"php8-on-fire-%f0%9f%94%a5","status":"publish","type":"post","link":"https:\/\/drmad.org\/blog\/php8-on-fire-%f0%9f%94%a5.html","title":{"rendered":"PHP8 on fire \ud83d\udd25"},"content":{"rendered":"\n<p>Hace a\u00f1os escrib\u00ed en este blog <a href=\"https:\/\/drmad.org\/blog\/aclaracion-odio-java-y-un-poco-de-switchcase.html\">mi odio a Java<\/a>, por que su lenguaje se parece a C, que tiene estructuras que s\u00f3lo tienen sentido en C. Tambi\u00e9n inclu\u00ed a PHP en la mezcla, por casi la misma raz\u00f3n. Pero por una oportunidad de ser profesor de PHP, me percat\u00e9 que hab\u00eda madurado bastante, y a partir de la versi\u00f3n 7 ha tenido cambios muy  interesantes debido a que corrigieron la forma c\u00f3mo se interpreta el c\u00f3digo fuente, y ahora usan un <a href=\"https:\/\/wiki.php.net\/rfc\/abstract_syntax_tree\">\u00e1rbol de sintaxis abstracto<\/a> previo a la compilaci\u00f3n, usado en casi todos los dem\u00e1s lenguajes de programaci\u00f3n. Eso les abri\u00f3 las puertas para poder a\u00f1adir nuevas caracter\u00edsticas, que siguen hasta ahora.<\/p>\n\n\n\n<p>Y al final me qued\u00e9 programando para la web en PHP \ud83d\ude05 <\/p>\n\n\n\n<p>A fin de a\u00f1o saldr\u00e1 la siguiente mayor versi\u00f3n de PHP, la 8, y realmente ando emocionado con varios de sus nuevos <em>features<\/em>, muchos para normalizar algunas incongruencias, y otros son cosas que siempre he extra\u00f1ado de otros lenguajes. Aqu\u00ed mi <em>top-10<\/em> de los 11 <em>features<\/em> que me parecen m\u00e1s interesantes \ud83e\udd2a: <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">::class en objetos<\/h2>\n\n\n\n<p><code>::class<\/code> es usado para obtener el nombre \u00abtotalmente calificado\u00bb de una clase (\u00abFQCN\u00bb) como un <em>string<\/em>, resolviendo todos los <em>namespaces <\/em>. Pero no funcionaba <em>en los objetos<\/em>, donde deb\u00edas usar la funci\u00f3n <code>get_class()<\/code>. Ya no m\u00e1s \ud83d\ude03 Ahora <code>$object::class<\/code> devuelve el FQCN como un <em>string<\/em>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">M\u00faltiples tipos en par\u00e1metros y retorno<\/h2>\n\n\n\n<p>Ahora ser\u00e1 posible a\u00f1adir varios tipos aceptados en la declaraci\u00f3n de par\u00e1metros y retorno de funciones. E.g.:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">function a\u00f1adir_precio(int|float $precio): int|float|null\n{\n   \/\/...<\/pre>\n\n\n\n<p><code>$precio<\/code> puede ser \u00fanicamente <code>int<\/code> o <code>float<\/code> y el resultado puede ser de \u00e1mbos tipos, o <code>null<\/code>. Era dif\u00edcil ciertas ocasiones usar un \u00fanico tipo, yo personalmente acababa dej\u00e1ndolo de lado, y usando un m\u00e9todo de verificaci\u00f3n de tipo en el cuerpo de la funci\u00f3n, como <code>is_string()<\/code>o similares.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><code>catch<\/code> sin variable<\/h2>\n\n\n\n<p>Este es uno chiquito. Ahora ser\u00e1 posible no especificar una variable en el <code>catch<\/code> de un <code>try<\/code>. Muchas veces es innecesario. E.g.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">try {\n   CambiarContrase\u00f1a($nueva_contrase\u00f1a);\n} catch (NoAuthorizedException) {\n   exit (\"\u00a1Sin autorizaci\u00f3n!\");\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Nuevas funciones de b\u00fasqueda de cadenas<\/h2>\n\n\n\n<p>Buscar si una cadena est\u00e1 dentro de otra sol\u00eda ser engorroso en PHP, a pesar que es algo muy com\u00fan. PHP8 traer\u00e1 nuevas funciones de b\u00fasqueda de cadenas:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">str_starts_with ( string $haystack , string $needle ) : bool\nstr_ends_with ( string $haystack , string $needle ) : bool\nstr_contains ( string $haystack , string $needle ) : bool<\/pre>\n\n\n\n<p>Estas tres funciones se usar\u00e1n para ver si una cadena empieza con otra (<code>str_starts_with()<\/code>), si termina con otra (<code>str_ends_with()<\/code>) o si la contiene en cualquier lugar (<code>str_contains()<\/code>).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Coma suelta al final de la lista de par\u00e1metros<\/h2>\n\n\n\n<p>Empezamos con las novedades interesantes \ud83d\ude03 En los arrays, en los <em>namespaces<\/em> compuestos, y en los argumentos en la llamada a funciones es posible colocar una coma suelta al final del \u00faltimo elemento. Si colocas cada elemento en una l\u00ednea, a\u00f1adir una nueva l\u00ednea se siente natural:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$par\u00e1metros = [\n   'nombre' => 'Oliver',\n   'direcci\u00f3n' => 'Av. Probando 123',\n];<\/pre>\n\n\n\n<p>En el ejemplo, vas a la l\u00ednea 4, escribes el nuevo elemento, y presionas <code>enter<\/code>. Pero eso no pasa en la lista de par\u00e1metros en la definici\u00f3n de una funci\u00f3n. Cuando son muchos los par\u00e1metros, o son muy largos, es m\u00e1s legible (y recomendado en el <a href=\"https:\/\/www.php-fig.org\/psr\/psr-12\/\">PSR-12<\/a>) colocar cada par\u00e1metro en una l\u00ednea. Pero a\u00f1adir un par\u00e1metro m\u00e1s al final <em>no es posible<\/em> sin ir primero a la \u00faltima l\u00ednea, ir al final de ella, y a\u00f1adir una coma, por que es actualmente ilegal dejar la coma suelta al final. A parte, los <code>diffs<\/code> del c\u00f3digo fuente tienen que registrar dos l\u00edneas cuando s\u00f3lo est\u00e1s a\u00f1adiendo una.<\/p>\n\n\n\n<p>Ahora PHP8 permite esa coma suelta al final:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Notas\n{\n   public function __construct(\n      Alumno $alumno,\n      Profesor $profesor,\n      Clase $clase, \/\/ UFFF Al f\u00edn :-)\n   ) {\n      \/\/...<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Promoci\u00f3n de propiedades del constructor<\/h2>\n\n\n\n<p>Es com\u00fan pasar argumentos al constructor de una clase, para que este a su vez los guarde en propiedades de dicha clase. E.g.:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Hasher\n{\n   private Database $database;\n   private Logger $logger;\n\n   public function __construct(\n      Database $database,\n      Logger $logger\n   )\n   {\n        $this->database = $database;\n        $this->logger = $logger;\n    }<\/pre>\n\n\n\n<p>PHP8 permitir\u00e1 remover la redundancia, promoviendo los par\u00e1metros del constructor a propiedades de la clase. El c\u00f3digo anterior se podr\u00e1 escribir as\u00ed:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Hasher\n{\n   public function __construct(\n      private Database $database,\n      private Logger $logger,\n   ) {\n\n   }<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">JIT<\/h2>\n\n\n\n<p>PHP 8 incluir\u00e1 un \u00abcompilador al vuelo\u00bb (\u00ab<em>just-in-time compiler<\/em>\u00ab) que acelerar\u00e1 ciertos procesos que usan intensivamente el CPU. <\/p>\n\n\n\n<p>Actualmente cada instrucci\u00f3n de PHP es convertida a un c\u00f3digo intermedio parecido al <em>assembler<\/em> conocido como \u00abopcode\u00bb, que luego es \u00abinterpretado\u00bb al vuelo a c\u00f3digo m\u00e1quina del CPU donde est\u00e1 siendo ejecutado. El objetivo del JIT es convertir PHP directo al c\u00f3digo m\u00e1quina del CPU, para que no sea necesario interpretar un <em>opcode<\/em>, lo cual acelerar\u00e1 su ejecuci\u00f3n.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Expresi\u00f3n <code>match<\/code><\/h2>\n\n\n\n<p>Whoa&#8230; El ejemplo principal de mi odio a Java (y de paso, PHP) <a href=\"https:\/\/drmad.org\/blog\/aclaracion-odio-java-y-un-poco-de-switchcase.html\">era la instrucci\u00f3n switch<\/a>, porque su sintaxis solo <em>ten\u00eda<\/em> sentido en C, y los lenguajes modernos usan versiones m\u00e1s elegantes (ojo con el \u00abten\u00eda\u00bb, C ya no usa la tabla de saltos&#8230; eso se merece otro post luego).<\/p>\n\n\n\n<p>Bueno pues, ya que es bastante com\u00fan usar <code>switch<\/code> solo para cambiar el valor de una variable, ahora PHP8 tiene la expresi\u00f3n <code>match<\/code> que retorna un valor seg\u00fan una lista de comparaciones. <\/p>\n\n\n\n<p>Este es un caso real de uso de <code>switch<\/code>, <a href=\"https:\/\/github.com\/doctrine\/orm\/blob\/72bc09926df1ff71697f4cc2e478cf52f0aa30d8\/lib\/Doctrine\/ORM\/Query\/Parser.php#L816\">del analizador de consultas de Doctrine<\/a>:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">switch ($this->lexer->lookahead['type']) {\n    case Lexer::T_SELECT:\n        $statement = $this->SelectStatement();\n        break;\n\n    case Lexer::T_UPDATE:\n        $statement = $this->UpdateStatement();\n        break;\n\n    case Lexer::T_DELETE:\n        $statement = $this->DeleteStatement();\n        break;\n\n    default:\n        $this->syntaxError('SELECT, UPDATE or DELETE');\n        break;\n}<\/pre>\n\n\n\n<p>Varias cosas pueden ir mal usando <code>switch<\/code> para este tipo de casos: <\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Puedes olvidar escribir esos horribles <code>break<\/code> y el c\u00f3digo se ejecutar\u00e1 sin problemas.<\/li><li>Puedes escribir mal la variable que recibir\u00e1 el valor (en el ejemplo se repite 3 veces la variable <code>$statement<\/code>) y el c\u00f3digo se ejecutar\u00e1 sin problemas.<\/li><li>O simplemente puede no funcionar como esperas, ya que PHP tiene unas reglas de igualdad extra\u00f1as&#8230; ya sabes, <code>\"hola\" == 0<\/code> es <code>true<\/code>&#8230;<\/li><\/ul>\n\n\n\n<p>El mismo c\u00f3digo usando <code>match<\/code> se ver\u00e1 as\u00ed:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$statement = match ($this->lexer->lookahead['type']) {\n    Lexer::T_SELECT => $this->SelectStatement(),\n    Lexer::T_UPDATE => $this->UpdateStatement(),\n    Lexer::T_DELETE => $this->DeleteStatement(),\n    default => $this->syntaxError('SELECT, UPDATE or DELETE'),\n};<\/pre>\n\n\n\n<p><code>match<\/code> compara <em>estrictamente <\/em>el valor del par\u00e1metro con cada opci\u00f3n (igual que el operador de identidad <code>===<\/code>), y retorna su expresi\u00f3n relacionada. Si no existe una opci\u00f3n con el valor del par\u00e1metro, y no hay una opci\u00f3n <code>default<\/code>, se lanzar\u00e1 una excepci\u00f3n <code>UnhandledMatchError<\/code>, lo cual evitar\u00e1 un mont\u00f3n de posibles errores.<\/p>\n\n\n\n<p>Tambi\u00e9n es posible tener varias opciones para una expresi\u00f3n resultante. E.g.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">echo match(1) {\n   1, 2 => '\u00a1Hola',\n   3, 4 => 'mundo!',\n}\n\n\/\/ Imprimir\u00e1 '\u00a1Hola' <\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Operador &#8216;nullsafe&#8217;<\/h2>\n\n\n\n<p>Este operador est\u00e1 aun en proceso de votaci\u00f3n, pero al 17 de julio tiene 95% de aprobaci\u00f3n con 24 votos, as\u00ed que es muy probable que acabe en PHP8. En este c\u00f3digo:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$usuario = $usuarios->obtener(199);\nvar_dump($usuario->nombre);<\/pre>\n\n\n\n<p>Si <code>$usuarios-&gt;obtener(199)<\/code> devuelve <code>null<\/code> (quizas el usuario no existe), la 2da l\u00ednea emitir\u00e1 un <em>warning<\/em>: \u00ab<em>Trying to get property &#8216;nombre&#8217; of non-object<\/em>\u00ab. Si <code>$usuarios<\/code> es <code>null<\/code>, la 1ra l\u00ednea fallar\u00e1 con un \u00ab<em>Call to a member function obtener() on null\u00bb.<\/em><\/p>\n\n\n\n<p>El operador \u00abnullsafe\u00bb <code>?-&gt;<\/code> devuelve <code>null<\/code> si la expresi\u00f3n a su izquierda es <code>null<\/code> y no procesa todas las expresiones que est\u00e1n a su derecha (corto-circuito completo). De lo contrario, se comporta como el operador <code>-&gt;<\/code>. El c\u00f3digo:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$usuario = $usuarios?->obtener(199);\nvar_dump($usuario?->nombre);<\/pre>\n\n\n\n<p>Si uno de los dos errores detallados arriba sucede, imprimir\u00e1 <code>NULL<\/code> sin fallar. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Atributos<\/h2>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><strong>Actualizaci\u00f3n 9 de octubre<\/strong>: Despu\u00e9s de haber sido aceptado los atributos, <a href=\"https:\/\/derickrethans.nl\/\">Derick Rethans<\/a> et al. presentaron un nuevo <a href=\"https:\/\/wiki.php.net\/rfc\/shorter_attribute_syntax_change\">RFC para modificar la sintaxis de los atributos<\/a>. El RFC fue aprobado, as\u00ed que he actualizado la sintaxis en esta secci\u00f3n.<\/p><\/blockquote>\n\n\n\n<p>Esto es grande. Los atributos son metadatos que se le podr\u00e1n a\u00f1adir a clases, propiedades, m\u00e9todos, argumentos y constantes. Java los llama &#8216;<a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/technotes\/guides\/language\/annotations.html\">anotaciones<\/a>&#8216;, y Python tiene algo parecido llamados &#8216;<a href=\"https:\/\/www.python.org\/dev\/peps\/pep-0318\">decoradores&#8217;<\/a> (que son realmente <em>wrappers<\/em>).<\/p>\n\n\n\n<p>Hasta ahora hemos estado usando un bloque de comentarios para a\u00f1adir metadata, inspirado en <a href=\"https:\/\/www.phpdoc.org\/\">phpDocumentor<\/a>. Pero al ser texto simple, hay que analizarlo para poder obtener la informaci\u00f3n, lo cual es tedioso y lento. E.g.:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Persona\n{\n   \/**\n    * @Field\\VarChar(12)\n    *\/\n   private $nombre;\n\n   \/\/ ...<\/pre>\n\n\n\n<p>Luego usando <a href=\"https:\/\/www.php.net\/manual\/en\/book.reflection.php\">reflexiones<\/a> obtenemos el bloque de comentario para analizarlo. Ya que tradicionalmente las anotaciones son clases, viene el problema de <a href=\"https:\/\/stackoverflow.com\/questions\/43351573\/build-fqcn-from-a-string\">obtener el FQCN de la clase en la anotaci\u00f3n<\/a>, lo cual requiere un <em>hack<\/em> bastante feo.<\/p>\n\n\n\n<p>En PHP8 el c\u00f3digo se vuelve lindo:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Persona\n{\n   #[Field\\VarChar(12)]\n   private $nombre;\n\n   \/\/ ...<\/pre>\n\n\n\n<p>PHP se encarga de la resoluci\u00f3n del FQCN, y tambi\u00e9n de la instanciaci\u00f3n de la clase de la anotaci\u00f3n.<\/p>\n\n\n\n<p>Los frameworks son quienes har\u00e1n uso extensivo de esto. Originalmente en <a href=\"https:\/\/vendimia.in\">Vendimia<\/a> usaba <em>arrays<\/em> para definir el objeto que tendr\u00eda una propiedad (algo como <code>$nombre = [Field\\VarChar::class, 12]<\/code> , y despu\u00e9s le a\u00f1ad\u00ed soporte para usar el <em>docblock<\/em> con el <em>hack<\/em> feo que mencion\u00e9 anteriormente. Ahora estar\u00e1 m\u00e1s elegante. \ud83d\ude0b<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Argumentos con nombre<\/h2>\n\n\n\n<p>\u00c9ste es uno de los <em>features<\/em> que he extra\u00f1ado m\u00e1s de otros lenguajes \ud83d\ude22 No solo simplifica ciertas llamadas a m\u00e9todos, ayuda a la autodocumentaci\u00f3n, y evita problemas de orden que tienen algunos par\u00e1metros similares en ciertas funciones de PHP. A\u00fan est\u00e1 en votaci\u00f3n, est\u00e1 algo ajustado (requiere 66% de aprobaci\u00f3n, tiene actualmente 74%), y espero que el universo nos permita que lo a\u00f1adan a PHP 8. \ud83d\ude05<\/p>\n\n\n\n<p>\u00c9sta es la declaraci\u00f3n del m\u00e9todo <code>Write()<\/code> de <a href=\"https:\/\/tcpdf.org\/\">TCPDF<\/a>, una librer\u00eda para generar PDFs en PHP:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public Write( $h, $txt, $link = '', $fill = false, $align = '', $ln = false, $stretch = 0, $firstline = false, $firstblock = false, $maxh = 0, $wadj = 0, $margin = '' )<\/pre>\n\n\n\n<p>Si quieres a\u00f1adir un texto con todas las opciones con su valor por defecto, excepto el margen (par\u00e1metro <code>$margin<\/code>), tienes que escribir:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$pdf->Write(10, \"\u00a1Hola mundo!\", '', false, '', false, 0, false, false, 0, 0, [1, 1, 1, 1]);<\/pre>\n\n\n\n<p>\ud83d\ude12&#8230; Tienes que conocer la cantidad, el orden, los valores por defecto de cada par\u00e1metro, y eventualmente el significado de cada uno cuando quieras modificar algo de este caos tiempo despu\u00e9s. Y tener cuidado al escribir, a\u00f1adir u omitir un argumento es muy f\u00e1cil. A parte, se ve m\u00e1s feo que el a\u00f1o 2020.<\/p>\n\n\n\n<p>Si aprueban el <a href=\"https:\/\/wiki.php.net\/rfc\/named_params\">RFC de argumentos con nombre<\/a>, esta llamada podr\u00eda verse as\u00ed:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$pdf->Write(10, \"\u00a1Hola mundo!\", margin: [1, 1, 1, 1]);<\/pre>\n\n\n\n<p>\ud83e\udd29 hermoso. Y ya sabes qu\u00e9 significa el \u00faltimo par\u00e1metro. <\/p>\n\n\n\n<p>Otro ejemplo. Estas son las declaraciones de las funciones <code>strpos()<\/code>y <code>in_array()<\/code>:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"> strpos ( string $haystack , mixed $needle [, int $offset = 0 ] ) : int\n in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] ) : bool<\/pre>\n\n\n\n<p>&#8230;<code>$needle<\/code> y <code>$haystack<\/code> est\u00e1n en distinto orden \ud83d\ude1d. Esta confusi\u00f3n se puede evitar usando argumentos con nombre:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$pos = strpos(needle: 'er', haystack: 'Per\u00fa');<\/pre>\n\n\n\n<p>La sintaxis aun est\u00e1 por definirse, otras propuestas incluyen usar el mismo operador de asignaci\u00f3n en arrays <code>=&gt;<\/code>, o usar el nombre de la variable en vez de una constante de caracteres: <code>$pos = strpos($needle: 'er', $haystack: 'Per\u00fa');<\/code>. Personalmente prefiero el uso de los dos puntos.<\/p>\n\n\n\n<p>Este RFC tambi\u00e9n propone a futuro implementar una sintaxis corta cuando el nombre del par\u00e1metro y el nombre de la variable de valor son el mismo. En vez de escribir:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ejecutar (contacto: $contacto, venta: $venta, opciones: $opciones);<\/pre>\n\n\n\n<p>Puedes escribir:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ejecutar (:$contacto, :$venta, :$opciones);<\/pre>\n\n\n\n<p>Y si esa sintaxis la trasladan a los arrays asociativos, ya podr\u00edamos dejar de usar la funci\u00f3n <code>compact()<\/code>, y se ver\u00eda m\u00e1s elegante.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>PHP 8 tiene aun varios otros cambios aceptados y por aceptar, la p\u00e1gina <a href=\"https:\/\/php-rfc-watch.beberlei.de\/\">PHP RFC Watch<\/a> muestra el avance de las votaciones de todos esos cambios. En este momento est\u00e1 disponible la mayor\u00eda de nuevos <em>features<\/em> en la versi\u00f3n <a href=\"https:\/\/www.php.net\/archive\/2020.php#2020-07-09-1\">Alpha 2 de PHP 8<\/a>, por si quieres probarlos.<\/p>\n\n\n\n<p>Los argumentos con nombre era una de las dos cosas que m\u00e1s deseaba en PHP, la otra es sobrecarga de operadores. Esperemos que sea pronto. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Se acerca el lanzamiento de PHP 8.0, y varios de sus nuevos features son increibles.<\/p>\n","protected":false},"author":1,"featured_media":757,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[14],"tags":[32,33],"class_list":["post-736","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-php","tag-php","tag-php8"],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/drmad.org\/blog\/wp-content\/uploads\/2020\/07\/elephpants.jpg?fit=1920%2C540&ssl=1","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p6p3z1-bS","jetpack-related-posts":[],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/posts\/736","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/comments?post=736"}],"version-history":[{"count":32,"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/posts\/736\/revisions"}],"predecessor-version":[{"id":801,"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/posts\/736\/revisions\/801"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/media\/757"}],"wp:attachment":[{"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/media?parent=736"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/categories?post=736"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/tags?post=736"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}