Se posso, queste sono le mie due versioni alternative di cui una alloca sempre spazio e l'altra cerca di risparmiarlo permettendo l'accesso alle proprietà tramite operatore ->. La classe URL costa di due soli metodi e non ha bisogno di metodi d'accesso. L'accesso in scrittura è ovviamente negato.
Versione spendacciona:
Codice PHP:
<?php
class OggettoCostante {
private $iDati = [];
public function __construct(array $valori) {
foreach ($valori as $nomeProprieta => $valore) {
if (is_object($valore))
$valore = clone $valore;
$this->iDati[$nomeProprieta] = $valore;
}
}
public function __get($name) {
if (isset($this->iDati[$name]))
return $this->iDati[$name];
throw new Exception("La proprieta non e' definita");
}
public function __set($name, $value) {
throw new Exception("Non e' ammessa la modifica dello stato dell'oggetto");
}
}
final class URL extends OggettoCostante {
public function __construct(array $url) {
if (!isset($url['url']) or !filter_var($url['url'], FILTER_VALIDATE_URL, array(FILTER_FLAG_SCHEME_REQUIRED, FILTER_FLAG_HOST_REQUIRED))) {
throw new Exception("Parametro non correttamente formattato o url non valido.");
}
$purl = parse_url($url['url']);
$scheme = $purl['scheme'];
$host = $purl['host'];
$path = (isset($purl['path'])) ? $purl['path'] : '';
$query = (isset($purl['query'])) ? $purl['query'] : '/';
parent::__construct(array('url' => $url['url'], 'scheme' => $scheme, 'host' => $host, 'path' => $path, 'query' => $query));
}
public function addQuery(array $params) {
if (empty($params))
throw new Exception('I parametri non sono validi');
$querystring = '';
foreach ($params as $key => $value)
$querystring .= '&' . $key . '=' . urlencode($value);
$querystring = (empty($this->query)) ? trim($querystring, '&') : $this->query . $querystring;
$url = $this->scheme . '://' . $this->host . $this->path . '?' . $querystring;
return new URL(['url' => $url]);
}
}
$url = new URL(['url' => 'h*t*t*p://www.html.it']);
//aggiungiamo alcuni parametri
$nuovoUrl = $url->addQuery(array('uid' => 1, 'name' => 'Paolo'));
if ($url == $nuovoUrl)
echo 'I due "value URL object" sono uguali';
else
echo 'I due "value URL object" NON sono uguali';
//output: I due "value URL object" NON sono uguali
?>
Versione che non istanzia nuovi oggetti a fronte del ripresetnarsi di stati già utilizzati:
Codice PHP:
<?php
class OggettoCostante {
private static $gliOggetti = [];
private $iDati = [];
/**
* Crea un nuovo oggetto costante. In $valori vanno specificate coppie
* [nomeProprietà => valore, ...]. Le proprietà saranno poi accessibili
* tramite la sintassi $oggetto->nomeProprietà in sola lettaura
* @param array $valori
* @return type
*/
public static function creaNuovoOggetto(array $valori) {
$hash = hash("sha256", serialize($valori)); //tengo le dita incrociate
$class = get_called_class();
if (!isset(self::$gliOggetti[$class][$hash]))
self::$gliOggetti[$class][$hash] = static::istanziaOggetto($valori);
return self::$gliOggetti[$class][$hash];
}
protected static function istanziaOggetto(array $valori){
return new OggettoCostante($valori);
}
protected function __construct(array $valori) {
foreach ($valori as $nomeProprieta => $valore) {
if (is_object($valore))
$valore = clone $valore;
$this->iDati[$nomeProprieta] = $valore;
}
}
public function __get($name) {
if (isset($this->iDati[$name]))
return $this->iDati[$name];
throw new Exception("La proprieta non e' definita");
}
public function __set($name, $value) {
throw new Exception("Non e' ammessa la modifica dello stato dell'oggetto");
}
}
final class URL extends OggettoCostante {
/**
* Crea un nuovo oggetto url costante. Il parametro è un array del tipo:
* ['url' => 'http://www.google.com']
* @param array $url
* @throws Exception
*/
public static function creaNuovoOggetto(array $url) {
if (!isset($url['url']) or !filter_var($url['url'], FILTER_VALIDATE_URL, array(FILTER_FLAG_SCHEME_REQUIRED, FILTER_FLAG_HOST_REQUIRED))) {
throw new Exception("Parametro non correttamente formattato o url non valido.");
}
$purl = parse_url($url['url']);
$scheme = $purl['scheme'];
$host = $purl['host'];
$path = (isset($purl['path'])) ? $purl['path'] : '/';
$query = (isset($purl['query'])) ? $purl['query'] : '';
return parent::creaNuovoOggetto(array('url' => $url['url'], 'scheme' => $scheme, 'host' => $host, 'path' => $path, 'query' => $query));
}
protected static function istanziaOggetto(array $valori) {
return new URL($valori);
}
public function addQuery( array $params ) {
if ( empty( $params ) )
throw new Exception( 'I parametri non sono validi' );
$querystring = '';
foreach ( $params as $key=>$value )
$querystring .= '&' . $key . '=' . urlencode( $value );
$querystring = (empty($this->query))? trim($querystring, '&'):$this->query . $querystring;
$url = $this->scheme . '://' . $this->host . $this->path . '?' . $querystring;
return self::creaNuovoOggetto(['url' => $url]);
}
}
$url = URL::creaNuovoOggetto( ['url' => 'h*t*t*p://www.html.it']);
//aggiungiamo alcuni parametri
$nuovoUrl = $url->addQuery( array( 'uid'=>1, 'name'=>'Paolo' ) );
if ( $url == $nuovoUrl ) {
echo 'I due "value URL object" sono uguali';
} else {
echo 'I due "value URL object" NON sono uguali';
}
//output: I due "value URL object" NON sono uguali
?>
Inutile dire che l'output prodotto è quello atteso. Non capisco perchè non posso postre indirizzi web nel codice e mi tocca aggiungere gli *