Newsgroup: it.comp.www.php
Titolo: motore di ricerca (criterio)

Ciao a tutti.
Premetto che non ho alcun bisogno di un motore di ricerca già fatto, mi
piacerebbe solo far due chiacchiere, con chi ne avesse voglia, della
logica da usare durante la progettazione e realizzazione di un motore in
PHP.
Vi dico a cosa ho pensato; tenete conto che se c'è (e c'è di sicuro)
qualche contorsione o ridondanza, è dovuta alla mia attuale misera
conoscenza del PHP e dell'informatica in senso più esteso. 
Il piano d'azione, almeno per ora, mira al semplice riempimento di un
array con i path delle pagine che contengono la parola chiave "pippo";
riguardo le rifiniture vedremo poi.
Schematicamente.
1. Entro nella prima directory che incontro
    1a. (ciclo tutti i file)
    if (il file[$i] ha estensione ".htm" or ".php") {
    ne leggo il sorgente scartando i <tag> e il loro contenuto 
    [ Va bene fgetss? Se NON va bene gradirei il dito indice
      puntato al manuale]
        if (il testo contiene "pippo") {
         array_push($ar, path della pagina);
        }
 
    } else if (il file[$i] è una directory) {
    riprendo dal punto 1a
    }
Riguardo allo scandagliare l'intero sito (o parte di esso) per mezzo di
cicli credo di potermela già cavare.
Che ne dite, è un metodo "ortodosso" o totalmente fuori dagli schemi?
Se sono sulla buona strada vi parlerò di un dubbio circa l'output PHP,
se invece sto prendendo una cantonata... vi prego di essere diplomatici
nel dirmelo ^_^
Ciao, grazie :)
-- 
Nicoletta

       puntato al manuale]
http://www.php.net/file_get_contents
 (lettura file)
http://www.php.net/strip_tags
 (per i tag oppure preg_replace)
http://www.php.net/preg_match
 (per ricerca case insensitive)
-- 
I am what I am, I do what I can
Vuoi supportarmi? 
http://url.repository.biz/go/3E
Sei un newbie? Leggi questo 
http://url.repository.biz/go/3C
L'uomo, conscio di sbagliare, persevera.

       puntato al manuale]
Qui siamo al componente 2. Niente manuale, ma... come fai a cercare
all'interno di pagine che sono linkate su questa pagina? Se strippi l'html
ti perdi i link! Quindi meglio fare prima una ricerca di eventuali link
(avendo cura di estrarre il testo contenuto tra <a> e </a> e nell'attributo
"title".
Volendo fare i raffinati, discrimini tra i contenuti di <h1> <h2> eccetera
e <div> o <p>, e ti preoccupi in particolar modo dei campi meta.
My 2 cents,
enrico

 Ferma la'. 
Sfortunatamente devo dirmelo da sola: credevo di avere un weekend tutto
mio, per studiare in santa pace, e invece ho un imprevisto che mi terrà
lontana dal PHP e dal gruppo per diversi giorni :'(
Tu comunque aspettami al varco, appena possibile mi riaggancio al thread
e ti rispondo, anche perché - oltre alla difficoltà che avrò per
comprendere tutto - ho già visto 5-6 parole che nemmeno conosco :-)
Per il momento grazie (anche a Setec)
p. s. Non ci sperate: TORNO DAVVERO! :-))
-- 
Nicoletta

 p. s. Non ci sperate: TORNO DAVVERO! :-))
Se continui a proporre quesiti interessanti, ci conto. :-)
Mi spiace che non abbia attirato particolare attenzione :-/
Per una volta che non si chiede "come faccio a togliere l'HMTL da un file?"
enrico

 Mi spiace che non abbia attirato particolare attenzione :-/
Ti sbagli, è l'esatto contrario. Proprio perché da un'occhiata veloce ho
trovato interessante la tua risposta, vorrei riprendere non appena sono
in grado di aver capito (almeno in parte) i concetti che hai espresso.
E vorrei anche dare uno sguardo accurato ai link che mi ha fornito
Setec; ovviamente per farlo occorre tempo disponibile. 
Come dicevo ieri, mi ha bloccato un imprevisto (questioni familiari, ma
niente di spiacevole, solo faccende pratiche da sbrigare quanto prima);
e ne avrò per diversi giorni. Ma poi torno, *TORNO* :-)
Non rileggo, invio il post in fretta e furia e scappo. Se c'è qualche
errore ortografico e/o sintattico ve lo beccate così com'è  ;-P
A prestissimo... spero :)
-- 
Nicoletta

Non so' perchè ...mi ricordi un po'  "Sandy"  la mitica
scoiattola subaquea di Spongebob :-)

 Mi spiace che non abbia attirato particolare attenzione :-/
Non ne sarei tanto convinto, infatti credo che ce ne siano tanti come me che
attendono il seguito del 3d.
Comunque ho sperimentato una soluzione simile a quella proposta da Nicoletta
e va bene se si ha un numero limitato di pagine, se queste sono tante php va
in time-out. Ho provato diverse varianti (db locali, MySql, files di testo
ecc...) ma non completo mai la prima indicizzazione, da qui capisco che sto
sbagliando l'approccio. Mi rimane al momento da provare con un cgi per
ovviare al time out, ma al momento non ho molto tempo da dedicargli.
Ciao ciao e a presto

 sono tante php va in time-out. 
http://www.php.net/set_time_limit
-- 
I am what I am, I do what I can



se fa riferimento al php.ini (ora vado a controllare), già fatto, ma non
sono ancora riuscito a capire per quale strano motivo ricevo l'errore di
time-out con qualsiasi tempo io imposti.
Comunque grazie, vado leggo e ricontrollo le mie impostazioni.

ovviare al time out, ma al momento non ho molto tempo da dedicargli.
Ci possono essere due sistemi un po' mànfani:
1. set_time_limit() e metti un time limit astronomico. Ma occhio, che
   a volte il browser decide per conto suo di smettere di aspettare.
2. trasformi lo script in uno script iterativo. Ti servono tre cose e
   in particolare:
	- una condizione di arresto (per capire quando hai finito)
	- una divisione in punti di ripristino (che potrebbe anche
	  non esserci, o non essere facile da trovare/fabbricare)
	- uno script principale che richiami il tuo
Per esempio c'e' questo script che percorre un albero colossale. Come
punto di ripristino prendiamo il momento in cui si entra in un ramo.
	// VERSIONE 1
	function explore($tree)
	{
		$results	= 0;
		$subdirs = array();
		$dd = opendir($tree)
		while($file = readdir($dd))
		{
			if (0 === strpos($file, '.'))
				continue;
			if (isdir("$tree/$file"))
			{
				$subdirs[] = $file;
				continue;
			}
			$results += explore_file("$tree/$file");
		}
		closedir($dd);
		// In questo modo la ricorsione avviene dopo closedir,
		// cioe' dopo la chiusura della handle. E si risparmia
		// una handle aperta per ogni livello di ricorsione (a
		// qualche OS, molte handle aperte fanno tanta bua).
		foreach($subdirs as $dir)
			$results += explore("$tree/$dir");
		return $results;
	}
In questo caso o usiamo una variabile globale per la condizione di arresto
oppure passiamo l'informazione alla funzione. Questa, poi, a ogni punto di
ripristino deve salvare il proprio stato e decidere se la c.d.a. e' vera o
no:
	// VERSIONE 2
	function explore($tree, $ttl)
	{
		// Aggiunta controllo fine esecuzione
		if (time() > $ttl)
			return 0;
		// Aggiunta controllo sulla chiamata in corso
		if (file_exists("$tree/.finished"))
		{
			$results = file_get_contents("$tree/.finished");
			return (int)$results;
		}
		$results	= 0;
		$subdirs = array();
		$dd = opendir($tree)
		while($file = readdir($dd))
		{
			if (0 === strpos($file, '.'))
				continue;
			if (isdir("$tree/$file"))
			{
				$subdirs[] = $file;
				continue;
			}
			$results += explore_file("$tree/$file");
		}
		closedir($dd);
		// In questo modo la ricorsione avviene dopo closedir,
		// cioe' dopo la chiusura della handle. E si risparmia
		// una handle aperta per ogni livello di ricorsione (a
		// qualche OS, molte handle aperte fanno tanta bua).
		foreach($subdirs as $dir)
			$results += explore("$tree/$dir", $ttl);
		// Preparazione dei dati per le istanze future
		$fp = fopen("$tree/.finished");
		fwrite($fp, "$results\n");
		fclose($fp);
		return $results;
	}
La funzione adesso continua a iterare, ma prima di esaminare una directory
verifica se all'interno esiste un flag-file ".finished". Se c'e' significa
che quella directory e' gia' stata esaminata in un passo successivo, ed il
suo risultato e' contenuto proprio in .finished.
Ovviamente qui i dati sono molto semplici; potrei aver bisogno di usare un
qualche tipo di struttura molto complesso e salvarlo, con serialize(), nel
file .finished.
Una possibile "ottimizzazione" e' quella di verificare la "data" di ultima
modifica del file .finished, per ripetere la ricerca di tanto in tanto. E,
magari, farlo in modo che la creazione di un file .finished uccida tutti i
file .finished nelle sottodirectory, in modo da risparmiare spazio.
A questo punto la routine gira per, diciamo, 20 secondi... dopo 20 secondi
il suo $ttl si e' esaurito (parto con $ttl = time()+20) e in esecuzione ci
possono essere N iterazioni, che hanno tipicamente altri 10 secondi per l'
uscita ordinata: piu' che sufficiente.
Lo script "padre", con un reload (refresh o javascript) ricarica lo script
figlio, e la funzione riparte da zero; ma, adesso, l'esame delle directory
gia' toccate al giro prima e "protette" dal .finished e' rapidissimo, e la
funzione arriva ben presto a esaminare l'area "OLTRE" quella esaminata nel
corso del primo giro. E cosi' via.
Finche' l'overhead di ricerca non supera il $ttl, questo metodo funziona.
Il reload della pagina "padre" puo' anche essere usato per visualizzare un
qualche tipo di animazione passatempo.
Un approccio che io uso abbastanza spesso e':
	- un giro rapido per capire quanto vale N e M (v. sotto)
	- N iterazioni (quante ne servono) per riempire un database
	- M iterazioni (quante ne servono) per ottimizzarlo, es., a
	    colpi di query piccole
	- Nel corso delle N+M iterazioni si visualizza percentuale,
	  stato e riassunto della ricerca
	- al termine, unica query/rielaborazione che presenta tutti
	  i risultati
Leonardo macchinoso
-- 
Avere studiato senza mettere in pratica e' inutile;
mettere in pratica senza avere studiato e' pericoloso.
                                                - Conphpucio

> Leonardo macchinoso
effettivamente può sempbrare macchinoso, ma il concetto è più facile da
realizzare che da spiegare. Premesso che mi devo rileggere con molta più
calma l'idea come l'hai sviluppata tu (io avevo diviso manualmente in
segmenti l'albero da analizzare), il mio problema era la quantità di files
da indicizzare (più di 3 GBytes) e l'aggiornamento periodico del db.
La tua idea del file-flag è utile nel caso in cui ci siano delle cartelle
"statiche", ovvero il cui contenuto non cambia, diversamente anche tu hai
suggerito il controllo delle date ed è quello che farò.
Idea pensata e messa in coda di attesa è un programma autonomo che ad
intervalli prefissati rincontrolli il contenuto della cartelle web e un cgi
che forzi l'aggiornamento su richiesta. Lo scopo è duplice, infatti oltre
"l'archivio" vorrei indicizzare anche i files del server news, ovviamente
tempo permettendo e a scopo didattico.
Ciao ciao, grazie e a presto.

 "title".
Vado a memoria: mi sembra di ricordare che fgetss accetta un parametro
opzionale, che indica appunto i tag da non eliminare. Btw, nella lista
di Setec vedo un file_get_contents e nessun fgetss. Devo studiarci.
Per ora grazie. Mi scuso per l'impossibilità di approfondire un tema che
(a quanto pare) stava interessando anche altre persone. 
Un antico detto recita: prima il dovere poi il piacere, e nel dovere di
adesso c'è da creare un sito che NON necessita di motore di ricerca. Ne
necessitavo io, ma per il solo gusto di capirne la logica. Peccato.
...Peccato PER ORA, perché come vedi mantengo la parola, e non vi
libererete di me troppo facilmente! ^_^
Ciao
-- 
Nicoletta

 Ciao
Meglio cosi', queste cose fanno venir la voglia di fare un po' i "creativi"
:-)
PS: commenti da parte degli "anziani"?
enrico

Enrico Marongiu <enrico....@SICURAgmail.com> wrote:
<snippone>
Enrico, fattelo dire: sei STRAgentile, non scherzo. Del tuo post ho
capito (quasi) tutto, e non vedo l'ora di togliere il "quasi".
Per il momento ti saluto, ti ringrazio e ti auguro buon lavoro,
qualsiasi cosa tu stia facendo di questi tempi.
Appena possibile cercherò di elaborare le informazioni ricevute e di
riprendere il dialogo (*l'interessantissimo* dialogo).
Grazie ancora, ciao :)
-- 
Nicoletta

 Appena possibile cercherò di elaborare le informazioni ricevute
Riprendo il discorso augurandomi che nessuno trovi fastidiosa la
distanza fra un post e l'altro; sfortunatamente mi trovo in una
condizione che allo studio... non lascia troppo spazio. 
Si riparte (piano piano, eh? ^_^ ).
Ho questo array a una dimensione, è un po' la "mappa del sito" con
esclusi i file che non mi interessa analizzare. (In verità l'array è
ancora nella mia immaginazione, di fatto non esiste, ma penso di avere i
mezzi per poterlo creare).
$pagine=array("dir1/pag1.htm",
              "dir1/pag2.htm",
                              "dir1/sotto_dir1/pag1.htm",
                              "dir1/sotto_dir1/pag2.htm",
              "dir2/pag1.htm",
                              "dir2/sotto_dir2/pag1.htm",
              "dir3/pag1.htm"); // e così via
 
/* Facciamo un passo alla volta: ai cicli per scorrere l'array vorrei
pensarci in un secondo momento.
Manuale alla mano, la funzione più idonea per ricavare il testo dal
primo elemento di $pagine mi è sembrata file_get_contents(), e per
eliminare i tag e il loro contenuto strip_tags() */ 
 
$testo=file_get_contents($pagine[0]);
$testo=strip_tags($testo); 
// Ecco la domanda: per ora va tutto bene o c'è qualcosa di sbagliato?
$ParolaDaMatchare="meno";
/* Ancora col manuale sulle ginocchia, e al di là di quello che dovrà
diventare un motore di ricerca, ho fatto un primo passo sulle RegExp.
Intanto ho capito due cose (credo) basilari: la "i" (flag del case
insensitive, al fine di intercettare indifferentemente Meno, MENO meNO,
etc.) e \b (che è il limite di una parola, in modo tale da prendere in
considerazione "MENO" ma non "MENOtti" né "ameno").
Tutto funziona a meraviglia: */
if (preg_match("/\bmeno\b/i", $testo)) {
echo "ho trovato $ParolaDaMatchare";
} else {
echo "NON ho trovato $ParolaDaMatchare";
}
Ed eccoci al primo vero scoglio: io NON posso scrivere "meno" nella
RegExp, ovviamente devo usare $ParolaDaMatchare, cioè una variabile.
I primi tentativi sembrano accettare anche la variabile:
if (preg_match("/\b$ParolaDaMatchare\b/i", $testo)) {
ma non trovando conforto nel manuale, e basandomi unicamente sul test
casalingo, temo di commettere qualche ingenuità. La sto commettendo? Me
lo date voi un po' di conforto? ^_^
Grazie a tutti.
-- 
Nicoletta

 if (preg_match("/\b$ParolaDaMatchare\b/i", $testo)) {
Vai tranquilla! Ma soprattutto, stampa la stringa di match per essere
ancora piu' tranquilla :-)
$stringaMatch="/\b$ParolaDaMatchare\b/i";
if($preg_match($stringaMatch,$testo)) {
...
Inoltre, se vuoi che un certo identificativo non venga valorizzato come
variabile, puoi delimitarlo tra \Q e \E, ad esempio /\Q$noneunavariabile\E/
cerca proprio '$noneunavariabile'.
corine
-- 
nick: corine
L'ascia lascia la scia
http://alnitak.ctt.it/iltuodovere.jpg

 corine
(OT) E' il tuo vero nome o è un nickname? Se è un nick è molto bello, se
è un nome è molto... molto bello ugualmente, ma suona anche molto
straniero :-) (francese?)
-- 
Nicoletta

 straniero :-) (francese?)
Omioddio...
Rileggi il thread e gli autori. non noti niente di "comune"?
:-)


 Rileggi il thread e gli autori. non noti niente di "comune"?
Sei Enrico! 
Certo perň, auto-anagrammandoti hai ottenuto, nel nome un aspetto
delicatamente parigino, nel cognome le sembianze di autentico omaccio
peloso, coltivatore diretto :-)))
A presto, grazie di nuovo :)
-- 
Nicoletta

 $parole= preg_split('/[\s,]+/',$_REQUEST['ricerca']);
Da questo tuo input, e in seguito ad una mia fase di scervellamento
acuto, immodestamente, qui lo dico e qui lo nego, sono fiera di
annunciare che ne uscita fuori una funzioncina al bacio :-)
Ho pensato: siccome quel che conta in una ricerca č la "sostanza" (cioč:
per evitare il match di parole/caratteri che si trovano ovunque credo
sia preferibile scartare articoli, preposizioni, spazi bianchi,
parentesi, etc.), mi metto d'impegno e provo a crearmi l'array "ideale".
function Scorpora_e_crea_Array($s) {
$scarti=array("il","lo","la","i","gli","le",""); // da completare
$s=trim($s);
$ar=preg_split("/[^a-z]+/i",$s);
  for ($i=0; $i < count($ar); $i++) {
    if (in_array($ar[$i], $scarti)) {
    array_splice($ar, $i,1);
    }
  }
return $ar;
}
$stringa=" il   cane, (le gatte);     {gli _animali:} la  
/farfalla/.  "; // nota come abbondano gli spazi
$arr_per_Match=Scorpora_e_crea_Array($stringa);
print_r($arr_per_Match);
Ora stampala, dimmi che non č una funzioncina al bacio e ti tolgo il
saluto :-)
A parte gli scherzi, che ne pensi/pensate? Puň andare?
-- 
Nicoletta

 $testo=strip_tags($testo); 
Sta andando tutto bene, ma ora sono in una brutta fase, forse è il
momento più critico.
Come credo sia abitudine di molti di voi, sto prendendo il "vizio" di
rendermi la vita comoda grazie al PHP; ormai non scrivo quasi più
direttamente l'html, lo faccio generare dinamicamente da una o più
funzioni. Faccio un esempio 
function crea_pagina($attributo1,$attributo2,$txt1,etc.) {
echo "<table> etc."// ripeto, è solo un esempio
<td bgcolor=\"$attributo1\">
$txt1
e via dicendo";
}
in modo tale da poter modificare il layout (colori, forme, dimensioni)
quando e come mi pare, lasciando inalterati gli "switch" e gli "if" che,
in subordine alla variabile passata, sono addetti a quale testo/testi
dovrà mostrare la pagina chiamata.
Molto spesso dunque, il testo delle mie pagine è racchiuso in variabili
fra tag php: $gatto="il gatto ha quattro zampe";
Ovviamente (ed è questa la vera crisi) se il motore spulcia all'interno
di pagine passate sotto le grinfie di strip_tags, le parole chiave non
potranno matchare né gatto, né zampe, in quanto "gatto" e "zampe" si
trovano fra tag <php>.
Come vi comportate voi in questi casi?
E' pur vero che, secondo il manuale, le parentesi di strip_tags
accettano un parametro opzionale contenente gli eventuali tag da NON
"strippare". Ma, vi chiedo, accettano anche il tag <php>? Ho provato in
ogni modo ottenendo solo clamorosi fallimenti. Inoltre, ammesso che
esista una scappatoia per farlo, che senso avrebbe far matchare "cane"
con $cane="il *cane* ha una coda" quando il default dello switch (il
testo che apparirebbe senza una particolare variabile passata) fosse "il
gatto ha quattro zampe"?
Insomma, sono un po' in difficoltà, questa la vedo difficile.
Ciao e grazie a chiunque mi stia sopportando ^_^
-- 
Nicoletta

 Ciao e grazie a chiunque mi stia sopportando ^_^
E chi ti ha detto che ti sopportiamo??? :-P


 E chi ti ha detto che ti sopportiamo??? :-P
Prendi questa e porta a casa :-PPPPPPPPPP  *DOVRETE* sopportarmi! :-)
Ciao e grazie :)
-- 
Nicoletta

 Prendi questa e porta a casa :-PPPPPPPPPP  *DOVRETE* sopportarmi! :-)
E' il destino di tutti noi. Sopportare.
e supportare
:-)


 :-)
Bene. Oggi mi hai sopportato piů a lungo del solito, vediamo se riesci
anche a supportarmi.
Ciao, grazie a te e grazie anche agli altri del gruppo. Mi riferisco
ovviamente alla loro sOpportazione :-)
-- 
Nicoletta

 parlando) fra "ricorsivo" e "iterativo", per adesso non ha importanza.
Ricorsiva: una funzione che richiama se stessa, solitamente per scomporre
sempre di piu` il problema, e solitamente (se vuoi evitare cicli infiniti)
con una condizione di terminazione (che fa in modo che la funzione non
venga richiamata ulteriormente).
Iterativa: una funzione eseguita un certo numero (solitamente
predefinito) di volte (solitamente con for o while).
Bye.

 predefinito) di volte (solitamente con for o while).
Ecco perché non mi tornava! Essendo "iterare" sinonimo di "ripetere",
non trovavo (e a dire il vero ancora non trovo) azzeccatissimo
l'aggettivo; sarebbe un po' come chiamarla "ripetitiva" (sottintendendo
N volte) anziché "ripetuta" (N volte). Personalmente, una funzione
eseguita un certo numero di volte la chiamerei "iterata" o "reiterata",
non "iterativa".
Ma sono sfumature, niente di importante; importante invece è che tu mi
abbia chiarito il concetto, grazie :) 
-- 
Nicoletta

 ovviamente alla loro sOpportazione :-)
ho postato su questo NG un codice che faceva proprio questo.. se non sbaglio
non più di 2 settimane fa.. 
prova a ricercare..
-- 
www.iuz-lab.info


Date: Tue, 12 Oct 2004 15:14:47 GMT
-- 
www.iuz-lab.info

> predefinito) di volte (solitamente con for o while).
Una citazione: "To Iterate is Human, to Recurse, Divine"


 ho postato su questo NG un codice che faceva proprio questo.. 
L'ho trovato. Per ora ti ringrazio, mi faccio viva tra qualche giorno. 
p. s. Ormai dovete prendermi per quella che sono: una rompiscatole che
rompe le scatole con molta calma, senza fretta, senza frenesia, senza
agitazione. Io le scatole le rompo a rate, mica in contanti ^_^
-- 
Nicoletta

 agitazione. Io le scatole le rompo a rate, mica in contanti ^_^
Cacchio! Due messaggi in un mese!!! Sarai mica impazzita? :-)
CMQ meglio che le rompa a rate...
:-D


 Cacchio! Due messaggi in un mese!!! Sarai mica impazzita? :-)
Sono stata eccessiva, è vero; in futuro cercherò di limitarmi: un solo
messaggio a semestre ritengo possa bastare. Magari, ecco, lo invierò di
una lunghezza pari a quella dell'Enciclopedia Britannica ;-)))
-- 
Nicoletta

 ho postato su questo NG un codice che faceva proprio questo.. 
Ciao iuz, come vedi ho mantenuto la parola di rompiscatole in
rateizzazioni diluite ^_^
Senti, ho provato il tuo script, ma per quanto l'abbia trovato carino e
funzionale, mi crea delle difficoltà (in certi casi taglia le parole, è
un problema che non sono riuscita a risolvere). Mi sono dunque
rimboccata le maniche e ho provato qualcosa di totalmente diverso, è uno
script che fa uso di una RegExp e di una serie di passaggi che in teoria
non dovrebbero causare inconvenienti. Ti dispiace provarlo?
$testo="La vispa Teresa tra l'erbetta rincorrea
la farfalletta, la vispa Teresa la la la la";
$metcha="erbetta";
if (preg_match("/(.{0,30})(\b$metcha\b)(.{0,30})/is",$testo,$matches)) {
$arPrima=explode(" ",$matches[1]);
$prima="";
$lunghezzaArPrima=count($arPrima);
$quanteParolePrima=3;
  for ($i=0; $i < $lunghezzaArPrima; $i++) {
    if ($i > ($lunghezzaArPrima-$quanteParolePrima-1) ) {
    $spazio=($i== $lunghezzaArPrima-1 )?"":" ";
    $prima.= $arPrima[$i] . $spazio;
    }
 }
 
$arDopo=explode(" ",$matches[3]);
$dopo="";
$lunghezzaArDopo=count($arDopo);
$quanteParoleDopo=3;
  for ($i=0; $i < $lunghezzaArDopo; $i++) {
    if ($i <= $quanteParoleDopo ) {
    $dopo.= $arDopo[$i] . " ";
    }
 } 
$definitiva="..." . $prima . "<b>" .$matches[2] . "</b>" . $dopo .
"..."; 
echo $definitiva;
}
L'unica cosa di cui sono (quasi) certa è che con una RegExp un po' più
"mirata" si eliminerebbe una gran bella fetta di codice, credo basti
fare un buon uso del carattere speciale \w prima e dopo \b$metcha\b. E
sai, c'ho provato in ogni modo, ma evidentemente sbaglio qualcosa, non
riesco a cavare un ragno dal buco.
Grazie a te e grazie a coloro che vorranno fare un tentativo di
ottimizzazione dello script. Ciao :)
-- 
Nicoletta

 "mirata" si eliminerebbe una gran bella fetta di codice, 
Ho provato a buttar giů due righe:
if (preg_match("/(\w+.| *){0,3}(\b$metcha\b)(.\w+.| *){0,4}/is",$testo, $matches)) {
$definitiva=preg_replace("/$metcha/i", "<b>" . $matches[2] . "</b>",$matches[0]);
echo "[...] ". $definitiva . " [...]";
}
(variando il secondo numero tra parentesi graffe si ottengono piů o meno
parole prima e dopo $metcha) 
A occhio e croce non mi pare il massimo della vita; se interviene un
esperto con un parere un tantino piů autorevole del mio mi sa che sia
meglio per te e per me (che ne approfitto per capire qualcosa) ^__-
-- 
mailto: y = i
----------------------------------------
Vivo nel terrore di non essere frainteso 
(Oscar Wilde)

 
Alternativa:
$arrayDiTesto=preg_split('/(\W)+/',$testo);
if($pos=array_search($metcha,$arrayDiTesto)){
	print $arrayDiTesto[$pos-1]. " " . $arrayDiTesto[$pos] . " " .
$arrayDiTesto[$pos+1];
}
Al posto del semplice $arrayDiTesto[$pos-1] potrebbe esserci un 
join(' ',array_slice($arrayDiTesto,$pos-$prec-1,$prec))
ed al posto del semplice $arrayDiTesto[$pos+1] potrebbe esserci un
join(' ' ,array_slice($arrayDiTesto,$pos+1,$succ);
hope it helps!
