Consulta sobre PHP y URLs amigables

TeNSHi

#30 Todo seria probar pero supongo que si. Por cierto aparte de la función friendlyURL has cambiado algo mas para que funcionase?

1 respuesta
Dekard89

#31 No, tan sólo lo que ves. Bueno y el hecho de que he reinstalado el script por si había algún cambio anterior que estuviese entorpeciendo el funcionamiento de las soluciones propuestas.

Vale, he hecho una prueba con una array pero crashea (la página no carga), sugerencias? XD

$replace     = array(' con ', ' de ', ' para ', ' y ', ' en ', ' el ')

he probado sólo con un puñado por ver si tira

1 respuesta
TeNSHi

#32 El array tiene que ser de expresiones regulares, al igual que tienes en los otros preg_replace, te lo pone en la web de php.

http://php.net/manual/es/function.preg-replace.php

Tienes una guía muy buena en este foro para las expresiones regulares, es muy recomendable manejarlas un poco aunque son un dolor de huevos:

http://www.mediavida.com/foro/dev/expresiones-regulares-ahora-modo-facil-468635

1 respuesta
9 días después
Dekard89

#33 Bueno chicos, año nuevo y esfuerzos renovado, vuelvo a la carga con el código maldito

public static function friendlyURL($str)
        {
            setlocale(LC_ALL,'es_ES.UTF8');
            $delimiter  = '-';
            $clean      = iconv('UTF-8', 'ASCII//TRANSLIT', $str);
            $clean      = preg_replace("/[^a-zA-Z0-9\/_|+ -]/", '', $clean);
            $clean      = strtolower(trim($clean, '-'));
            $clean      = preg_replace("/[\/_|+ -]+/", $delimiter, $clean);

        return $clean;
    }

con este fragmento conseguimos que los acentos desaparezcan respetando los caracteres que acompañan a los mismos. El siguiente objetivo era quitar las expresiones regulares con un array. Lo he intentado con un $clean y también con el preg_remplace, pero no parece responder a la lista de palabras incluidas. Sospecho que puede ser algun problema de semántica.

1 respuesta
TeNSHi

#34 Deberías poner como has intentado quitar las palabras.

1 respuesta
7 días después
Dekard89

#35 Vaya descuido por mi parte, claro. Usé las siguientes variaciones

$preg_remplace   =array('con', 'contra', 'desde', 'el', 'ella'...);
$clean                  =array('con', 'contra', 'desde', 'el', 'ella'...);

Miré las páginas que me recomendaste y utilice también un par de ideas basadas en poner varios patrones y su sustitución, pero tampoco daba resultado. Temo que una vez más se trate de un error mio al colocar las lineas donde no deberían estar, o un error de semántica como dije anteriormente.

1 respuesta
TeNSHi

#36 Eso no es lo que tienes puesto no? es que ahí lo que estas haciendo es creando dos variables que contienen un array :S

Tu piensa que preg_replace reemplaza un patrón (expresión regular) encontrado en un string ($str / $clean) por lo que le digas tu (en este caso por '' ), tienes que crear un patrón/patrones (expresión regular) que cuadre/n con las palabras a reemplazar. Si le pasas lo que tienes en ese array no te va a valer mira lo que te va a seleccionar si le pasas contra:

https://regex101.com/r/hK9aL6/1

Por lo que al sustituir por '' te va a dejar palabras cortadas que no querías tocar.

Tienes que entender bien que hace preg_replace y leerte el enlace que te puse de expresiones regulares porque ahí hay algo que necesitas usar.

A ver no te quiero ayudar en exceso porque si es un trabajo que estas haciendo tu, tampoco vas a aprender mucho si te lo doy directamente.

1 respuesta
Dekard89

#37 Bueno bueno, ha costado lo suyo, pero creo que lo he conseguido y bastante limpio. Tengo que agradecer tu insistencia para que mirase las páginas que me pasaste. No me ha quedado claro al 100% todo, puesto que hay una docena de métodos, pero tengo una noción más amplia.
De hecho, te pego el código a continuación, no sea que por alguna cosa que tenga puesta pueda darme problemas en un futuro:

public static function friendlyURL($str)
    {
	setlocale(LC_ALL,'es_ES.UTF8');
        $replace     = array(' con ', ' de ', ' para ', ' y ', ' en ', ' la '); 
	$delimiter  = '-';
	$str     = str_replace((array)$replace, ' ', $str); 
        $clean      = iconv('UTF-8', 'ASCII//TRANSLIT', $str);
        $clean      = preg_replace("/[^a-zA-Z0-9\/_|+ -]/", '', $clean);
        $clean      = strtolower(trim($clean, '-'));
        $clean      = preg_replace("/[\/_|+ -]+/", $delimiter, $clean);

    return $clean;
}
2 respuestas
TeNSHi

#38 Si he entendido bien lo que quieres hacer, a ese código le veo varios problemas así a ojo.

En:

$str     = str_replace((array)$replace, ' ', $str); 

Sustituyes por un espacio con lo cual si la palabra a quitar esta al principio te queda un espacio que va a ser sustituido mas tarde por un guion, para la frase de ejemplo para este texto no funciona te quedaría -este-texto-no-funciona

Ademas eso solo sustituye las palabras marcadas en minúscula y que tenga un espacio delante y otro detrás para la frase Para este texto no funciona te quedaría para-este-texto-no-funciona.

Igual sin usar expresiones regulares puedes hacerlo funcionar pero te va a quedar un poco feo y aunque son un dolor de huevos es raro que en el futuro no las vayas a usar.

1 respuesta
Dekard89

#39 Otra vez a empezar XD. Si tientes razón. Las mayúsculas no desaparecen, en ningún caso, haya o no espacios. He probado quitando espacios, incluso en el str_remplace por "". He leído que hay formas de hacer que no haya distinción entre minúsculas o mayúsulas a la hora de eliminar las stopwords.

$str        = str_replace((array)$remplace, "", $str); 

He intentado como en otro ejemplo que he visto, poniendo la versión en mayúscula.

$remplace  = array("con", "Con", "de", "De"); 

Ya cuando creía estar tan cerca...jajaja. Ha sido como un cubo de agua fría.

Ah, una cosa más, he encontrado un enlace sobre el tema del difereciador entre minúsculas y mayúsculas en el archivo .htaccess: http://stackoverflow.com/questions/20103413/friendly-urls-spaces-to-hyphens-uppercase-to-lowercase

No se si investigando por aquí voy bien encaminado... XD

TeNSHi

#38 Si no me equivoco vas a tener el problema que te comentaba en #37

Para De donde conoces a ese te devolverá don oces a ese.

Puedes probar este código en http://phpfiddle.org/ :

$test = array('De', 'de', 'con', 'Con');
echo str_replace($test, "", "De donde conoces a ese");

A ver yo tampoco soy experto e igual hay otra solución en la que ahora no caigo, pero con lo que te dije que te mirases se puede hacer, si te lees lo de las expresiones regulares me parecería muy raro que no encontrases una cosa que es lo que tu necesitas.

1 1 respuesta
Dekard89

#41 Nuevo descubrimiento. No se si es "bueno" per se, porque aparece un nuevo problema. Puedo eliminar las stopwords mayúsculas y minúsculas pero a cambio se quedan los separadores (-).

   public static function friendlyURL($str)
{
    setlocale(LC_ALL,'es_ES.UTF8');
    $delimiter  = '-';
    $clean      = iconv('UTF-8', 'ASCII//TRANSLIT', $str);
    $clean      = preg_replace("/[^a-zA-Z0-9\/_|+ -]/", '', $clean);
    $clean      = strtolower(trim($clean, '-'));
    $clean      = preg_replace("/[\/_|+ -]+/", $delimiter, $clean);
    
$stopwords = array('the', 'The'. 'etc'); return str_replace($stopwords, '', $clean); }

Alguna idea? Sigo investigando!

1 respuesta
TeNSHi

#42 Deberías poner para que caso te falla. Prueba a hacer primero el str_replace y después a lo que te salga le haces un trim.

1 respuesta
Dekard89

#43 Hoy es un día de novedades XD. Acabo de encontrar una solución para los guiones. Ahora se eliminan las palabras puestas en el array con los separadores que les acompañan.

	public static function friendlyURL($str)
{
    setlocale(LC_ALL,'es_ES.UTF8');
    $delimiter  = '-';
    $clean      = iconv('UTF-8', 'ASCII//TRANSLIT', $str);
    $clean      = preg_replace("/[^a-zA-Z0-9\/_|+ -]/", '', $clean);
    $clean      = strtolower(trim($clean, '-'));
    $clean      = preg_replace("/[\/_|+ -]+/", $delimiter, $clean);

$stopwords     = array('el', 'la', 'los', 'las', 'El', 'La', 'Los', 'Las', 'un', 'una', 'uno', 'unas', 'unos', 'Un', 'Una', 'Uno', 'Unas', 'Unos');
$clean         = explode ('-', $clean);
$clean         = array_diff($clean, $stopwords);
   
return implode ('-', $clean);
}

Ahora bien. Aunque aparentemente funciona, no quisiera meter la pata y que luego me cause problemas. Que te parece?

1 respuesta
TeNSHi

#44 No se, tendrías que probarlo bien, igualmente puede que las variantes con mayúsculas no te hagan falta porque en teoría haces strtolower antes, prueba a ver si quitando las que empiezan con mayúsculas te funciona.

1 1 respuesta
Dekard89

#45 Muy cierto, no hace falta poner las versiones en mayúsculas, no me había percatado. Bueno pues, de momento funciona, así que gracias por el esfuerzo conjunto que hemos hecho por aquí xD. Lo hemos logrado. Si en algún momento vuelve a fallar volvere a dar parte a través del foro. Conociendo la ciencia mágica de la informática eso puede ser dentro de 5 minutos o 6 meses jajaja.
Pongo el código final resultante aquí:

public static function friendlyURL($str)
{
    setlocale(LC_ALL,'es_ES.UTF8');
    $delimiter  = '-';
    $clean      = iconv('UTF-8', 'ASCII//TRANSLIT', $str);
    $clean      = preg_replace("/[^a-zA-Z0-9\/_|+ -]/", '', $clean);
    $clean      = strtolower(trim($clean, '-'));
    $clean      = preg_replace("/[\/_|+ -]+/", $delimiter, $clean);

$stopwords     = array('el', 'la', 'los', 'las', 'un', 'una', 'uno', 'unas', 'unos');
$clean         = explode ('-', $clean);
$clean         = array_diff($clean, $stopwords);
   
return implode ('-', $clean);
}
1
Dekard89

#46 Bien, lo dicho. No se sabe cuando iba a volver a la carga conociendo estas cosas XD. Nuevo detalle del que no me percaté. La url ahora se construye bien, eliminando las stopwords y los caracteres raros, pero previamente no aparece su categoría.
Me explico: elmundo.com/internacional/elecciones-grecia-syriza

Un amigo me ha dicho que los cambios los tengo que hacer sobre estos archivos:
No me entran los dos XD, así que pongo el primero y si algo se puede hacer pongo el segundo. El tema es que no reconozco la mitad de las órdenes que veo y no se donde tendría que hacer los cambios.

spoiler
Dekard89

#47 Añado, que no me entraba en el otro post. Mi amigo me ha dicho que tendría que modificar seguramente algún modulo en este archivo php, pero que por la pinta que tiene seguramente tenga que crear un query nuevo en otro que ya tengo localizado. Ahora bien, de este último código que he publicado, no se que modulo tendría que cambiar y aún me estoy informando de lo que es un query XD. Una vez más perdón por mi ignorancia XD.

eXtreM3

Vaya tocho la virgen.

Para la categoría tienes que hacer lo mismo que para el nombre del post y contatenarlo en la url. Asumo que tienes un htaccess correctamente configurado para que sea capaz de interpretar algo así

RewriteRule ^categoria(.*)/nombre(.*)$ blog.php(param1,param2)

Entonces en la vista, cuando muestres los enlaces hacia el post, debes añadir tu friendlyUrl($categoria)

1 respuesta
Dekard89

#49 Mi reacción fue exáctamente la misma XD. No asumamos que tengo nada bien configurado, teniendo en cuenta que la página la estoy remodelando desde cero XD (y llevo poco menos que un par de meses estudiando lenguajes de programación web). Voy a pegarte lo que tengo en ese archivo:

<IfModule mod_rewrite.c>
    RewriteBase /
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

RewriteEngine On

#1and1 to enable PHP 5.4
AddHandler x-mapp-php6 .php 

# Redirect Trailing Slashes...
RewriteRule ^(.*)/$ /$1 [L,R=301]

# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>

Por un lado, ¿en qué punto debería implementar esa regla de reescritura?. Y por otro lado, si funciona después introduciendo el resto de cambios sólo en mi friendlyUrl, me vas a alegrar el día cosa mala XD. Este es mi friendlyUrl para que te hagas una idea:

1 respuesta
eXtreM3

#50 el htaccess va por jerarquía, lo que pongas encima tiene preferencia sobre lo que pongas debajo, si la regla que lee le sirve y la interpreta bien, termina ahí. Por lo tanto:

<IfModule mod_rewrite.c>
    RewriteBase /
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

RewriteEngine On

#1and1 to enable PHP 5.4
AddHandler x-mapp-php6 .php 

# Redirect Trailing Slashes...
RewriteRule ^(.*)/(.*)$ post.php?categoria=$1&post=$2
RewriteRule ^(.*)/$ /$1 [L,R=301]

# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>

Con eso le estás diciendo que el archivo post.php debe recibir dos parámetros, el nombre de la categoría y el nombre del post (es aconsejable que metas ids para que sean únicos). Entrando a la url

web.com/eventos/campus-party-2015

debe cargar tu categoría y tu post. Si no te dará un error 500.

Hay varios posts sobre htaccess aquí en mv, te recomiendo que los visites, en casi todos están resueltas las dudas ;)

1 1 respuesta
Dekard89

#51 En efecto, error 500 de los gordos jajaja. Tengo tres categorías: nacional, internacional y otros. Al configurarlas en el admin de la página este me los guarda en las tablas sql que he subido en el servidor. El servidor es 1&1 como puedes ver. Me esta dando más disgustos que otra cosa. De hecho, el htacces original que me pasaron no funcionaba bien con 1&1 así que busque una solución por Internet y me encontré con eso.
Las categorías, tal cual las he citado, tienen las ids "1", "2" y "3" en las tablas sql. De ahí ya no se como hacer para que coja el category_url de la tabla y lo haga figurar en sus correspondientes posts.

Dekard89

Nada, por más explicaciones que leo no consigo que funcione. ¿A alguno se le ocurre como puedo hacer para que tire?. No se como hacer para que me coja las puñeteras categorías y en teoría es fácil. Poca experiencia con los htaccess me temo.

He probado con lo siguiente:

<IfModule mod_rewrite.c>
    RewriteBase /
    <IfModule mod_negotiation.c>
    Options -MultiViews
    </IfModule>

RewriteEngine On

#1 and1 to enable PHP 5.4
AddHandler x-mapp-php6 .php

# Redirect Trailing Slashes...
RewriteRule ^nacional/([^/]*)/([^/]*)$ /post.php?category=$1&title=$2
RewriteRule ^internacional/([^/]*)/([^/]*)$ /post.php?category=$1&title=$2
RewriteRule ^otros/([^/]*)/([^/]*)$ /post.php?category=$1&title=$2
RewriteRule ^(.*)/$ /$1 [L,R=301]

# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>

Curiosamente, no me da error 500 pero tampoco hace nada más. Qué debería hacer a continuación? Teniendo en cuenta que vaya por buen camino claro...

1 respuesta
eXtreM3

#53 si no te da error 500 al cargar una url del tipo

web.com/eventos/campus-party-2015

ya lo tienes hecho. Recoges con $_GET el valor de "category" (que así se lo has puesto en el htaccess) y ya está.

Arriba del todo de post.php pon

echo $_GET["category"];

Si te pinta algo ya lo tienes, si no di qué error te da :P

EDIT: no había visto la regla, la tienes mal. Debe ser así:

RewriteRule ^(.*)/(.*)$ post.php?category=$1&title=$2

Así le estás diciendo que post.php va a ser así en la url: dominio.com/loquesea/loquesea (loquesea = (.*)). Puto htaccess y las peleas eternas xD

1 respuesta
Dekard89

#54 No hay manera.
Si lo dejo así ahora me da error 500:

<IfModule mod_rewrite.c>
    RewriteBase /
    <IfModule mod_negotiation.c>
    Options -MultiViews
    </IfModule>

RewriteEngine On

#1 and1 to enable PHP 5.4
AddHandler x-mapp-php6 .php

# Redirect Trailing Slashes...
RewriteRule ^(.*)/(.*)$ post.php?category=$1&title=$2
RewriteRule ^(.*)/$ /$1 [L,R=301]

# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>

¿Alguna idea de por qué pasa esto? Por cierto, todos los ejemplos que veo hacen referencia al archivo post.php, pero el caso es que yo tengo tres archivos con ese nombre. De hecho, el archivo que configura las friendlyUrls lo tengo en otro sitio.

Dekard89

Actualizo añadiendo el archivo post.php correcto, que al final he dado con el:

spoiler
1 respuesta
Mujiwara

#56 Una observación, los campos input hidden que te sirven para las peticiones AJAX, es simple pijerio/postureo, pero podrías meter los valores como .data() en algún elemento:

<article id="post" data-ajax-url="<?php echo $post['post_url'];?>" data-ajax-prev="<?php echo $show['prev'];?>" data-ajax-next="<?php echo $show['next'];?>">
<header>
...
</header>
</article>

Y lo lees así:

var ajax_url = $('article#post').data('ajax-url');
var ajax_prev = $('article#post').data('ajax-prev');
var ajax_next = $('article#post').data('ajax-next');