Jump to content

Recommended Posts

Posted

Boas.

Eu fiz um CMS para o meu site, e como a parte do blog me estava a dar mais problemas de fazer á mão (porque ainda não sou grande espingarda em orientação a objectos), acabei por ir buscar uma classe a um tutorial e adapta-la ás minhas necessidades (integração/bilingue etc...)

Agora que já estou a finalizar o trabalho resolvi substituir os "hello world's" e "lorem ipsum's" por algo mais palpável.

Mas vi que o PHP está a ter problemas com o encoding.

Do lado da base de dados, já tentei latin e utf-u. Quer um, quer outro me aparecem na perfeição no PhpMyAdmin (acentos/caracteres expeciais etc...), mas por algum motivo estão a ter diversos problemas a aparecer correctamente no site.

Antes de mais nada(Antes de ser despromovido a "muito noob"):

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

Está presente no head.

Já experimentei abrir uma query sozinha, sem templates ou qualquer outra coisa, e apareceu igualmente mal.

Mas se colocar o conteúdo estaticamente, vai aparecer tudo bem, com acentos e tudo mais.

A classe que faz os query's é assim:

<?php
class Article {
// Properties
/**
 * @var int The article ID from the database
 */
public $id = null;
/**
 * @var int When the article is to be / was first published
 */
public $publicationDate = null;
/**
 * @var string Full title of the article
 */
public $title = null;
public $titlept = null;
/**
 * @var string A short summary of the article
 */
public $summary = null;
public $summarypt = null;
/**
 * @var string The HTML content of the article
 */
public $content = null;
public $contentpt = null;
/**
 * Sets the object's properties using the values in the supplied array
 *
 * @param assoc The property values
 */
public function __construct($data = array()) {
	if (isset($data['id']))
		$this->id = (int) $data['id'];
	if (isset($data['publicationDate']))
		$this->publicationDate = (int) $data['publicationDate'];
	if (isset($data['title']))
		$this->title = preg_replace("/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['title']);
	if (isset($data['titlept']))
		$this->titlept = preg_replace("/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['titlept']);
	if (isset($data['summary']))
		$this->summary = preg_replace("/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['summary']);
	if (isset($data['summarypt']))
		$this->summarypt = preg_replace("/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['summarypt']);
	if (isset($data['content']))
		$this->content = $data['content'];
	if (isset($data['contentpt']))
		$this->contentpt = $data['contentpt'];
}
/**
 * Sets the object's properties using the edit form post values in the supplied array
 *
 * @param assoc The form post values
 */
public function storeFormValues($params) {
	// Store all the parameters
	$this->__construct($params);
	// Parse and store the publication date
	if (isset($params['publicationDate'])) {
		$publicationDate = explode('-', $params['publicationDate']);
		if (count($publicationDate) == 3) {
			list ( $y, $m, $d ) = $publicationDate;
			$this->publicationDate = mktime(0, 0, 0, $m, $d, $y);
		}
	}
}
/**
 * Returns an Article object matching the given article ID
 *
 * @param int The article ID
 * @return Article|false The article object, or false if the record was not found or there was a problem
 */
public static function getById($id) {
	$conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
	$sql = "SELECT *, UNIX_TIMESTAMP(publicationDate) AS publicationDate FROM articles WHERE id = :id";
	$st = $conn->prepare($sql);
	$st->bindValue(":id", $id, PDO::PARAM_INT);
	$st->execute();
	$row = $st->fetch();
	$conn = null;
	if ($row)
		return new Article($row);
}
/**
 * Returns all (or a range of) Article objects in the DB
 *
 * @param int Optional The number of rows to return (default=all)
 * @param string Optional column by which to order the articles (default="publicationDate DESC")
 * @return Array|false A two-element array : results => array, a list of Article objects; totalRows => Total number of articles
 */
public static function getList($numRows = 1000000) {
	$conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
	$sql = "SELECT SQL_CALC_FOUND_ROWS *, UNIX_TIMESTAMP(publicationDate) AS publicationDate FROM articles
		ORDER BY publicationDate DESC LIMIT :numRows";
	$st = $conn->prepare($sql);
	$st->bindValue(":numRows", $numRows, PDO::PARAM_INT);
	$st->execute();
	$list = array();
	while ($row = $st->fetch()) {
		$article = new Article($row);
		$list[] = $article;
	}
	// Now get the total number of articles that matched the criteria
	$sql = "SELECT FOUND_ROWS() AS totalRows";
	$totalRows = $conn->query($sql)->fetch();
	$conn = null;
	return ( array("results" => $list, "totalRows" => $totalRows[0]) );
}
/**
 * Inserts the current Article object into the database, and sets its ID property.
 */
public function insert() {
	// Does the Article object already have an ID?
	if (!is_null($this->id))
		trigger_error("Article::insert(): Attempt to insert an Article object that already has its ID property set (to $this->id).", E_USER_ERROR);
	// Insert the Article
	$conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
	$sql = "INSERT INTO articles ( publicationDate, title, summary, content ) VALUES ( FROM_UNIXTIME(:publicationDate), :title, :summary, :content )";
	$st = $conn->prepare($sql);
	$st->bindValue(":publicationDate", $this->publicationDate, PDO::PARAM_INT);
	$st->bindValue(":title", $this->title, PDO::PARAM_STR);
	$st->bindValue(":summary", $this->summary, PDO::PARAM_STR);
	$st->bindValue(":content", $this->content, PDO::PARAM_STR);
	$st->execute();
	$this->id = $conn->lastInsertId();
	$conn = null;
}
/**
 * Updates the current Article object in the database.
 */
public function update() {
	// Does the Article object have an ID?
	if (is_null($this->id))
		trigger_error("Article::update(): Attempt to update an Article object that does not have its ID property set.", E_USER_ERROR);
	// Update the Article
	$conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
	$sql = "UPDATE articles SET publicationDate=FROM_UNIXTIME(:publicationDate), title=:title, summary=:summary, content=:content WHERE id = :id";
	$st = $conn->prepare($sql);
	$st->bindValue(":publicationDate", $this->publicationDate, PDO::PARAM_INT);
	$st->bindValue(":title", $this->title, PDO::PARAM_STR);
	$st->bindValue(":summary", $this->summary, PDO::PARAM_STR);
	$st->bindValue(":content", $this->content, PDO::PARAM_STR);
	$st->bindValue(":id", $this->id, PDO::PARAM_INT);
	$st->execute();
	$conn = null;
}
/**
 * Deletes the current Article object from the database.
 */
public function delete() {
	// Does the Article object have an ID?
	if (is_null($this->id))
		trigger_error("Article::delete(): Attempt to delete an Article object that does not have its ID property set.", E_USER_ERROR);
	// Delete the Article
	$conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
	$st = $conn->prepare("DELETE FROM articles WHERE id = :id LIMIT 1");
	$st->bindValue(":id", $this->id, PDO::PARAM_INT);
	$st->execute();
	$conn = null;
}
}
?>

Poderá isto ajudar? http://php.net/manua...set-charset.php

Se sim, como aplico nesta classe?

(A unica parte da classe que é usada, é o recurso de busca á BD, o resto vai ser removido quando tiver tempo para ver se nada vai causar problemas)

Para verem o que quero dizer: http://www.claudiop.com

(Troquem a lingua para portugues e vejam um post no blog.

Dependendo do browser e do O.S., aparecem ou espaços ou pontos de interrogação no lugar dos acentos)

PS: Se fizerem o favor, podem dizer alguma desformatação que vejam no template? (Tambem só tem alguns dias)

Cumprimentos

Posted (edited)

Já tentaste:

http://www.php.net/m...truct.php#96325

?

Poderá isto ajudar? http://php.net/manua...set-charset.php

Se sim, como aplico nesta classe?

(A unica parte da classe que é usada, é o recurso de busca á BD, o resto vai ser removido quando tiver tempo para ver se nada vai causar problemas)

Isso não é uma classe, é uma função. 😉

Para verem o que quero dizer: http://www.claudiop.com

(Troquem a lingua para portugues e vejam um post no blog.

Dependendo do browser e do O.S., aparecem ou espaços ou pontos de interrogação no lugar dos acentos)

Pois... Isso é charset errado e parece-me o charset errado na ligação com a DB.

Já agora, não existe utf-u, é utf-8.


Tens a página com uma formatação (CSS) um pouco má. Há coisas fora do sítio.

Já vi o problema principal. O HTML é inválido.

Por exemplo, tens um <a> como child de <ul>.

Edited by brunoais
(emoticon para evitar interpretação errada)

"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Posted (edited)

Já tentaste:

http://www.php.net/m...truct.php#96325

?

Isso não é uma classe, é uma função. 😉

Pois... Isso é charset errado e parece-me o charset errado na ligação com a DB.

Já agora, não existe utf-u, é utf-8.


Tens a página com uma formatação (CSS) um pouco má. Há coisas fora do sítio.

Já vi o problema principal. O HTML é inválido.

Por exemplo, tens um <a> como child de <ul>.

Deixei agora assim:

public static function getList($numRows = 1000000) {
       $conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''));

E continua mal. Era a isso que te referias?

Com classe referia-me ao "article" (o ficheiro todo que fiz paste).

Desculpa, enganei-me a escrever. O u está em baixo do 8 😛

Sim, eu estou a par dos erros que o validador acusa, mas não é isso que está a causar o problema porque já testei sem template e sem mais nenhum html do que o proprio post. Quando acabar de corrigir os erros visiveis, passo para os bugs invisiveis.

PS: Quando adicionei aquele parametro na função, apesar de nada ter mudado, reparei que a informação já está correcta aqui: http://www.claudiop.com/includes/blog/?action=viewpost&post=1

Mas se reparar no codigo fonte, não está ai nada mais do que o post. Nem sequer declara ser utf-8.

Onde estou a errar agora?

Cumprimentos

Edited by brunoais
o link estava mal + geshi
Posted

HTML inválido + n é indicado que o charset é utf-8.

"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Posted (edited)

HTML inválido + n é indicado que o charset é utf-8.

Comentei temporariamente, todas as partes do documento que eram invalidas. Agora como podes ver o html está perfeitamente valido:

http://validator.w3.org/check?uri=http%3A%2F%2Fwww.claudiop.com%2F%3Faction%3Dviewpost%26post%3D1&charset=%28detect+automatically%29&doctype=Inline&group=0&user-agent=W3C_Validator%2F1.3

Está presente no documento o:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

A ligação á base de dados está a decorrer correctamente, e a função agora está assim:

public static function getList($numRows = 1000000) {
       $conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''));
       $sql = "SELECT SQL_CALC_FOUND_ROWS *, UNIX_TIMESTAMP(publicationDate) AS publicationDate FROM articles
           ORDER BY publicationDate DESC LIMIT :numRows";
       $st = $conn->prepare($sql);
       $st->bindValue(":numRows", $numRows, PDO::PARAM_INT);
       $st->execute();
       $list = array();
       while ($row = $st->fetch()) {
           $article = new Article($row);
           $list[] = $article;
       }
       // Now get the total number of articles that matched the criteria
       $sql = "SELECT FOUND_ROWS() AS totalRows";
       $totalRows = $conn->query($sql)->fetch();
       $conn = null;
       return ( array("results" => $list, "totalRows" => $totalRows[0]) );
   }

O que poderá estar a correr mal.

Desculpa o incomodo e a insistência, mas não estou mesmo a conseguir descubrir o problema.

Cumprimentos

Edited by brunoais
geshi!
Posted

Já rescreveste os dados depois de alterar o encoding da coluna para utf-8?

"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Posted
Em 09/06/2012 às 22:43, brunoais disse:

Já rescreveste os dados depois de alterar o encoding da coluna para utf-8?

Sim, acabei de fazer mais uma row só com acentos.

O resultado é este:

Citação
Quero testar os acentos: ������

O encoding é "utf8_unicode_ci"

Cumprimentos

Posted

Duas coisas (assumindo MySQL):

- Se estás a aceder como root, nunca vais receber dados UTF-8, nem se configurares a ligação para devolver os dados em UTF-8.

- O problema pode não ser o encoding da pase de dados, mas o encoding que é devolvido pela ligação (o MySQL recodifica os dados consoante o encoding pedido (ou o default).

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Posted
Em 09/06/2012 às 22:51, KTachyon disse:

Duas coisas (assumindo MySQL):

- Se estás a aceder como root, nunca vais receber dados UTF-8, nem se configurares a ligação para devolver os dados em UTF-8.

- O problema pode não ser o encoding da pase de dados, mas o encoding que é devolvido pela ligação (o MySQL recodifica os dados consoante o encoding pedido (ou o default).

Ás tantas, já nem sei qual é o problema.

A base de dados agora está toda definida para utf-8 general, quer as colunas quer o default.

Reparei num problema que pode indicar que não tem nada a ver com a base de dados.

Antes de ter movido o site para o alojamento, fiz a construção quase toda localmente, e reparei num problema que não tinha.

Tenho dois ficheiros que definem as traduções do menu/logo etc... en.php e pt.php.

Uma imagem de um deles:

http://www.claudiop.com/image/utf.png

Abri o notepad++ propositadamente para ter certeza absoluta do encoding que o ficheiro tem.

UTF-8 sem sombra de duvida.

Reparem no carácter que está marcado na linha 3(um simples ponto).

Quer defina UTF-8 no metadata, quer não, esse carácter assume um "?" em seguida ao titulo.

Poderão estes erros todos relacionados com encoding estar relacionados com a instalação do interpretador de php? Porque localmente esse carácter aparece bem.

Vou experimentar recriar a base de dados localmente para ver se o problema desaparece.

EDIT:

Consegui resolver o problema, se bem que ainda não entendi o como.

Fui reorganizar a classe que continha todas as funções que interagem com a BD. Depois de apagar 2/3 daquilo, acabei por dar por mais uma ligação á base de dados (no getbyid). Juntei a essa ligação o parâmetro para forçar UTF-8, e a BD passou a passar os dados correctamente.

Quanto aos dados estáticos que estavam a dar problema, alterei os scripts para que nunca chegassem a ser variaveis. Por exemplo o ponto, consegui coloca-lo em separado num require, de forma a que fosse parar ao mesmo sitio, mas nunca constando do script.

Cumprimentos

Cumprimentos

Posted (edited)

Atenção que o BOM pode estragar o teu código (se tentas alterar os headers) indicando que os headers já foram enviados.

Edited by brunoais

"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Posted

Atenção que o BOM pode estragar o teu código (se tentas alterar os headers) indicando que os headers já foram enviados.

Obrigado pela sugestão. Nem sabia o que era, agora que li isso é que fui pesquisar. 😉

Cumprimentos

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.