---
title: "Replace - snyggare sätt att lösa detta på?"
type: "forum-thread"
url: "https://www.webforum.nu/amne/php/183411-replace-snyggare-sätt-att-lösa-detta-på"
topic: "PHP"
topic_url: "https://www.webforum.nu/amne/php"
author: "bassebhu"
published: "2010-05-05T15:23:34.000Z"
updated: "2010-05-06T18:42:21.000Z"
replies: 4
views: 467
page: 1
pages: 1
language: "sv-SE"
site: "webForum — webforum.nu"
rights: "Upphovsrätten till varje inlägg tillhör dess författare."
attribution: "Citera som: webForum, https://www.webforum.nu/amne/php/183411-replace-snyggare-sätt-att-lösa-detta-på"
---

# Replace - snyggare sätt att lösa detta på?

## #1 — bassebhu, 2010-05-05T15:23Z

Har gjort ett litet script som hämtar rader från databasen. Min funktion getarchive() innehåller dels vilket parent-namn den ska hämta poster som tillhör och dels hur jag vill att det ska formateras. Jag vill kunna hämta önskade fält från databasen och kunna lägga på funktioner på dem i efterhand. Just nu har jag bara en replace på tre fördefinerade fält och kan inte göra nåt alls med dem i efterhand.

Så här ser min kod ut för att skriva ut poster:

```
$structure = '<dt>{$title}</dt>
<dd>{$datetime}</dd>
<dd>{$content}</dd>';
getarchive('nyheter', $structure);
```

Funktionen för databashämtet:

```
function getarchive ($parent, $structure) {

	$sql = "SELECT * FROM archive WHERE parent = '".$parent."'";
	$result = mysql_query($sql);

	$data = NULL;

	while($row = mysql_fetch_array($result)) {

		$datastr = str_replace('{$title}', $row['title'], $structure);
		$datastr = str_replace('{$datetime}', $row['datetime'], $datastr);
		$datastr = str_replace('{$content}', $row['content'], $datastr);
		$data .= $datastr;
	}

	return $data;

}
```

Jag hittar alltså på {$variabel} för att kunna ersätta dem, men jag tycker att det måste kunna göras på något smartare sätt. Förslag? Blanda in RegExp och lite sånt?

Stort tack!

Permalänk: https://www.webforum.nu/p/183411

## #2 — nitro2k01, 2010-05-05T16:16Z

Typ så här:

```php
$structure = '<dt>{$title}</dt>
<dd>{$datetime}</dd>
<dd>{$content}</dd>';
$structure_allowed_items=Array('title', 'datetime', 'content');
getarchive('nyheter', $structure, $structure_allowed_items);

function getarchive ($parent, $structure, $structure_allowed_items) {

	$sql = "SELECT * FROM archive WHERE parent = '".$parent."'";
	$result = mysql_query($sql);

	$replace_structure_element = create_function('$matches',
	'if (in_array($matches[1], $structure_allowed_items)){
		return $row[$matches[1]]
	}else{
		return $matches[0]
	} ');

	$data = NULL;

	while($row = mysql_fetch_array($result)) {
		$datastr = preg_replace_callback('/\{\$([a-z0-1_]+)\}/i', 
			$replace_structure_element,
			$structure);

		$data .= $datastr;
	}

	return $data;

}
```

Otestat, kan innehålla småfel. 
**preg_replace_callback** söker med ett regex. För varje natchning anropas en funktion. I detta fall skapar jag funktionen med **create_function**. Funktionen som skapas kollar om strängen som anropas är tillåten, för säkerhets skull. Är den det hämtas motsvarande rad i databasen. **$matches\[1\]** bör referera till **(\[a-z0-1\_\]+)** i uttrycket. Annars returneras matchningen oförändrad, vilket alltså gör att man varken får tillbaka lösenordet eller ett tomrum om man lägger in **{$password}** i strängen. ( ;) )

Permalänk: https://www.webforum.nu/p/2234445

## #3 — bassebhu, 2010-05-05T16:36Z

Tack!

Jag får:
Notice: Undefined variable: structure_allowed_items...
samt:
Warning: in_array() \[function.in-array\]: Wrong datatype for second argument...

Ska det in nån global till create_function?

Jag lade även till två semikolon efter return $row\[$matches\[1\]\] och return $matches\[0\] 

Är det möjligt att få det så att man skulle kunna skriva t.ex.:

```
$structure = '<dt>{strtoupper($title)}</dt>
<dd>{$datetime}</dd>
<dd>{$content}</dd>';
```

och den känner av om man har lagt något runt variablerna? t.ex. strtoupper eller en egen funktion eller nåt annat. Så att man kan behandla dem som vanliga variabler i princip.

Tack!

Permalänk: https://www.webforum.nu/p/2234446

## #4 — nitro2k01, 2010-05-06T01:02Z

> **[bassebhu skrev:](https://www.webforum.nu/p/1504412)**
>
> Ska det in nån global till create_function?

Så kan man göra, men det är inte *rätt*! Undvik **global**s som pesten, åtminstone för saker som inte ska vara globala egentligen. Föreställ dig t ex att du anropar funktionen rekursivt i en framtida version... 

> **[bassebhu skrev:](https://www.webforum.nu/p/1504412)**
>
> Är det möjligt att få det så att man skulle kunna skriva t.ex.:
>
>
> ```
> $structure = '<dt>{strtoupper($title)}</dt>
> <dd>{$datetime}</dd>
> <dd>{$content}</dd>';
> ```
>
> 
> och den känner av om man har lagt något runt variablerna? t.ex. strtoupper eller en egen funktion eller nåt annat. Så att man kan behandla dem som vanliga variabler i princip.

Så kan man göra, men det är inte *rätt*! En betydligt bättre metod är att sätta **text-transform: uppercase;** i CSS för elementen ifråga. 

Fast jag lade till en sådan funktion ändå. Du måste definiera alla tillåtna funktioner i förväg. Du kan självklart ange både egna och PHP's funktioner. Syntaxen i din mall blir lite annorlunda, **{strtoupper$title}** istället för **{strtoupper($title)}** men det får du stå ut med. (...eller skriva om regexen själv  §e )

```php
$structure = '<dt>{strtoupper$title}</dt>
<dd>{$datetime}</dd>
<dd>{$content}</dd>
<dd>{someinvalidtransform$content}</dd>
<dd>{$someothershit}</dd>';
// De två sista raderna i mönstret är ogiltiga data i testsyfte.

$structure_allowed_items=Array('title', 'datetime', 'content');

echo getarchive('nyheter', $structure, $structure_allowed_items);

function parse_structure_item($m0, $m1, $m2, $structure, $structure_allowed_items, $row) {
	$structure_allowed_transforms=Array('strtoupper' => strtoupper);

	if (in_array($m2, $structure_allowed_items)){
		if (in_array($m1, $structure_allowed_transforms)){
			// The item and transform are valid. Replace the variable, transform the item and return the result.
			$transform = $structure_allowed_transforms[$m1];
			return htmlspecialchars($transform($row[$m2]));
		}else if(!$m1){
			// The variable is valid. Replace the variable and return the result.
			return htmlspecialchars($row[$m2]);
		}
	}

	return $m0;		// The string and/or transformation function is invalid. Return the string unmodified	
}

function getarchive ($parent, $structure, $structure_allowed_items) {
//    $sql = "SELECT * FROM archive WHERE parent = '".$parent."'";
//    $result = mysql_query($sql);

	// Testdata
	$row = Array('title' => 'Jungel-Jim', 'datetime' => '06-07/96', 'content' => 'Parsuitel Orbitelum');
    $data = NULL;

//    while($row = mysql_fetch_array($result)) {
        $datastr = preg_replace('/\{([a-z0-1_]+)?\$([a-z0-1_]+)\}/ie', 
            'parse_structure_item(\'\0\', \'\1\', \'\2\', $structure, $structure_allowed_items, $row);',
            $structure);

        $data .= $datastr;
//    }

    return $data;

}
```

Permalänk: https://www.webforum.nu/p/2234470

## #5 — bassebhu, 2010-05-06T18:42Z

Nice! Tack!

Nu funkar det precis som jag vill ha det :D

Tänkte bygga på en optional kommentars-funktion till mitt arkiv, men om det dyker upp problem så kanske jag återkommer.

Tack för hjälpen igen!

Permalänk: https://www.webforum.nu/p/2234530

---

Tråden på webben: https://www.webforum.nu/amne/php/183411-replace-snyggare-sätt-att-lösa-detta-på
