Piero V.

Singleton in PHP + annesso bug

È da un po’ di tempo che sto programmando in C++ ma oggi sono tornato a programmare un po’ in PHP.

Devo dire che ormai mi sembra strano non dover dichiarare più variabili, non aver più gli header e poter implementare i metodi fuori dalla classe stessa.

Però mi ha fatto bene questa pausa di PHP perché ho imparato una tecnica molto interessante, quella delle “singleton”.

In pratica le singleton sono classi che possono avere una sola istanza.

Il loro metodo si riduce praticamente ai metodi statici, però sono più eleganti, secondo me.

Ci sono due principali metodi in C++ per fare i singleton: impostare il costruttore private, in modo da impedire la chiamata al di fuori della classe e dopo chiamarlo o da un metodo statico oppure tramite l’overriding dell’operatore new.

Implementare il primo metodo in PHP è facilissimo, mentre implementare il secondo dovrebbe essere fattibile tramite il metodo magico __call. Però non funziona, ma per farvi vedere come sarebbe lo metto lo stesso nel codice, che è il seguente:

<?php

class MiaClasse {

	/**
	 * L'istanza del singleton.
	 *
	 * @var MiaClasse object
	 * @access private
	 */
	private static $msSingleton = null;

	/**
	 * Un numero per fare una prova.
	 *
	 * @var integer
	 * @access public
	 */
	public $prova = 0;

	/**
	 * Il costruttore.
	 *
	 * È privato perché così si può creare una nuova istanza
	 * solamente da altri metodi di questa classe.
	 */
	private function __construct()
	{
		echo "Costruisco la classe\n";
	}

	/**
	 * Ritorno (o creo, se non esiste) il singleton.
	 */
	public static function getSingleton()
	{
		if(is_null(self::$msSingleton)) {
			self::$msSingleton = new MiaClasse();
		}

		return self::$msSingleton;
	}

	/**
	 * Fallback per le chiamate ai metodi privati.
	 *
	 * Se per caso si prova a creare una nuova istanza, tramite
	 * questa funzione chiamo sempre getSingleton.
	 * È un po' come l'overriding dell'operatore new in C++.
	 */
	public function __call($name, $arguments)
	{
		echo '__call called. $name = ' . $name;
		if($name == '__construct') {
			return self::getSingleton();
		}
	}

}

$a = MiaClasse::getSingleton();
$a->prova = 20;

$b = MiaClasse::getSingleton();
echo $b->prova . "\n";
$b->prova = 27;
echo $a->prova . "\n";

$c = $a->__construct();
$c->foo = 32;
echo $a->foo . "\n";

/*$d = new MyClass();
echo $d->foo . "\n";
$d->foo = 29;
echo $a->foo . "\n";*/

Come vedete se modifico $b modifico anche $a. … [Leggi il resto]

Flatpress: far vedere post non (apparentemente) collegati

Italiano

Scrivendo un plugin per i tag mi sono chiesto: “Come si potrebbe far vedere tutti i post con uno stesso tag?”

Andando avanti a pensare mi sono detto: “una specie di categoria”: ed ecco qui la risposta: quando ce n’è il bisogno, si fa creare una falsa categoria durante il filtro init.

Le categorie sono gestite dalla classe FPDB che le carica solo una volta e flatpress ne crea solo un’istanza.

Ecco il codice di base:

class plugin_tag_walker {
	var $valid=true;
	function current_key() {
		return current($this->array);
	}
	function next() {
		$n=next($this->array);
		if($n==false)
			$this->valid=false;
		return $n;
	}
}

class plugin_tag_fpdb {
	function length() {
		return $this->len;
	}
	function walker($p1=null) {
		$a=new plugin_tag_walker();
		$a->array=$this->array;
		return $a;
	}
}

function prova_cat() {
	global $fpdb, $fp_params;
	if(isset($_GET['tag'])) {       ### Solo se c'è il parametro GET tag
		$fp_params['cat']=-50;  ### L'id della categoria
		$p=new plugin_tag_fpdb();
		$p->array=array(
			'100715151839', ### Quali sono i post
			'100715163207',
			'100808220001'
		);
		$p->len=count($p->array);
		if($fp_params['count']>$p->len)
			$fp_params['count']=$p->len;
		$fpdb->_indexer[$fp_params['cat']]=&amp;$p;
	}
	return true;
}

add_filter('init', 'prova_cat');

Praticamente la funzione prova_cat assegna alla categoria -50 un oggetto che ne restituisce un altro che una volta chiamato dal codice di flatpress restituisce i post. … [Leggi il resto]