Ich muss in VBA ein Array in einen validen PHP-Serialize-String
umwandeln. Es handelt sich um ein assoziatives eindimensionales Array
mit Strings, Integern und Booleans. Nur ein einziges Item ist selbst
wieder ein Array (aus Strings). Ein rekursiver Algorithmus ist also
nicht nᅵtig - wenngleich natᅵrlich willkommen.
Hat jemand ein Stᅵck Code auf dem ich aufbauen kᅵnnte?
Muss natᅵrlich nicht in VBA sein. Wichtig ist nur, dass ausschlieᅵlich
einfache String-Manipulationen benutzt werden. Regulᅵre Ausdrᅵcke sind
aber mᅵglich.
Peter
> Ich muss in VBA ein Array in einen validen PHP-Serialize-String
> umwandeln.
Ich glaube nicht, dass das so ohne Weiteres mᅵglich ist. Der Ansatz
scheint mir auch nicht besonders sinnvoll zu sein.
Wie lautet denn das _eigentliche_ Problem, das Du damit zu lᅵsen versuchst?
Gruᅵ. Claus
Warum sollte das nicht mᅵglich sein? Wenn er nur Array, String, Integer
und Boolean hat, sind doch alle Typen, die er in VB hat, auch in PHP
vorhanden.
Und Werte serialisieren ist an sich ja nicht unsinnvoll, irgendwie muss
er die Sachen ja ᅵbertragen.
Ich habe heute die Welt noch nicht wirklich verbessert, also mal kurz
was gefrickelt (in PHP):
function recurse(array $structure ) {
$return = NULL;
$return .= "a:".count($structure).":{";
foreach($structure as $key => $value) {
$return .= serializeValue($key);
$return .= serializeValue($value);
}
$return .= "}";
return $return;
}
function serializeValue($value) {
if(is_string($value)) {
return "s:".strlen($value).":\"".$value."\";";
}
if(is_integer($value)) {
return "i:".$value.";";
}
if(is_float($value)) {
return "d:".$value.";";
}
if(is_bool($value)) {
if($value===TRUE) {
return "b:1;";
} else {
return "b:0;";
}
}
if(is_null($value)) {
return "N;";
}
if(is_array($value)) {
return recurse($value);
}
throw new Exception("type '".gettype($value)."' not implemented yet");
}
Damit werden string, int, float, bool, array und null behandelt. Vergiss
bitte die Exception in serializeValue nicht, damit sparst Du Dir eine
Menge Zeit bei der Fehlersuche, wenn mal jemand einen Typ reinbaut, der
nicht serialisiert werden kann.
Wenn man in VB andere Typen als in PHP als Schlᅵsselwert fᅵr einen
Assoziativen Array verwenden kann, solltest Du das berᅵcksichtigen (ich
geb Dir einen Rat - erlaube nur int und string).
Ich habe es gegen serialize mit folgendem Zeug getestet:
$array["int"] = 15;
$array["string"] = "Katzen sind niedlich";
$array["array"] = array("Hund", "Katze", "Maus");
$array["stuff"] = "\"";
$array[15] = 17.5;
$array["booleanf"] = FALSE;
$array["booleant"] = TRUE;
$array["empty"] = NULL;
$array[true] = NULL;
$array[null] = "18";
$array[17.8] = "float";
> Und Werte serialisieren ist an sich ja nicht unsinnvoll,
Solange er in einer PHP-Umgebung bleibt.
> irgendwie muss er die Sachen ja übertragen.
Und dafür gibt es genügend standardisierte Verfahren, wofür es schon 'zig
Lösungen gibt. PHPs AFAIK undokumentiertes serialize()-Format zu verwenden
ist äußerst ungeschickt.
--
<http://bav.malkusch.de/de/> - Mit PHP Kontonummern auf Gültigkeit prüfen
<http://php-autoloader.malkusch.de/de/> - PHP Autoload Implementierung
> Claus Reibenstein schrieb:
>
>> Peter Schleif schrieb:
>>
>>> Ich muss in VBA ein Array in einen validen PHP-Serialize-String
>>> umwandeln.
>>
>> Ich glaube nicht, dass das so ohne Weiteres mᅵglich ist. Der Ansatz
>> scheint mir auch nicht besonders sinnvoll zu sein.
>
> Warum sollte das nicht mᅵglich sein? Wenn er nur Array, String, Integer
> und Boolean hat, sind doch alle Typen, die er in VB hat, auch in PHP
> vorhanden.
Sicher ist das mᅵglich. Die Frage ist nur, wie groᅵ der Aufwand ist, ob
er sich lohnt und ob es sinnvoll ist.
> Und Werte serialisieren ist an sich ja nicht unsinnvoll, irgendwie muss
> er die Sachen ja ᅵbertragen.
Er will sie aber nicht "irgendwie ᅵbertragen", sondern ausgerechnet im
PHP-serialize-Format.
Gruᅵ. Claus
> Ich muss in VBA ein Array in einen validen PHP-Serialize-String
> umwandeln. Es handelt sich um ein assoziatives eindimensionales Array
> mit Strings, Integern und Booleans. Nur ein einziges Item ist selbst
> wieder ein Array (aus Strings). Ein rekursiver Algorithmus ist also
> nicht nötig - wenngleich natürlich willkommen.
>
> Hat jemand ein Stück Code auf dem ich aufbauen könnte?
Da ich kein VBA nutze kann ich dazu im Speziellen wenig sagen.
Eine Alternative wär evtl. Phalanger (wird auf codeplex.com gehostet und
ist OpenSource. Das ist eine PHP-Implementierung für das .NET-Framework,
geschrieben in C#- Wenn Du Dir dort die Datei PhpFormaterCLI.cs (o.ä.)
rauspickst und nach VB konvertierst (zum Konvertieren gibts Tools) dann
hast Du zumindest erst mal eine evtl. für Dich verständliche Codebasis
die sich dann eher nach VBA übersetzen läst.
MfG, Ulf
--
Es ist nicht einfach, perfekt zu sein, aber irgendeiner muß es sein
[Niki Lauda]
Naja, zunᅵchst hast Du geschrieben, dass Du nicht glaubst, dass das
"ohne Weiteres" mᅵglich ist.
Also es ist mᅵglich und der Aufwand, den ich getrieben habe, mit 30
Minuten recht ᅵberschaubar.
> Peter Schleif schrieb:
>
>> Ich muss in VBA ein Array in einen validen PHP-Serialize-String
ᅵᅵᅵᅵᅵᅵ
> Ich habe heute die Welt noch nicht wirklich verbessert, also mal kurz
> was gefrickelt (in PHP):
ᅵᅵᅵᅵᅵᅵ
Thema verfehlt.
> function recurse(array $structure ) {
> $return = NULL;
> $return .= "a:".count($structure).":{";
Aua!
> if(is_string($value)) {
> return "s:".strlen($value).":\"".$value."\";";
> }
> if(is_integer($value)) {
Schon mal was von elseif gehᅵrt?
Du hast die Welt leider immer noch nicht verbessert ...
Gruᅵ. Claus
Du mᅵkelst gerne rum, oder? Also, gehen wir das mal durch:
"Hat jemand ein Stᅵck Code auf dem ich aufbauen kᅵnnte?
Muss natᅵrlich nicht in VBA sein."
>> function recurse(array $structure ) {
>> $return = NULL;
>> $return .= "a:".count($structure).":{";
>
> Aua!
Persᅵnliche Prᅵferenz, muss man nicht mᅵgen.
>
>> if(is_string($value)) {
>> return "s:".strlen($value).":\"".$value."\";";
>> }
>> if(is_integer($value)) {
>
> Schon mal was von elseif gehᅵrt?
Ich bevorzuge Wᅵchter-if:
http://www.php-faq.de/q-stil-waechter.html
Das setze ich an vielen Stellen konsequent ein, auch das dient der
Lesbarkeit des Codes. Ich bevorzuge es, wenn einzelne Logikteile auch
als einzelner Block auftreten - ich kann hier eleganter einen Teil vor
den anderen schieben als mit elseif. elseif verwende ich - ungelogen - nie.
>
> Du hast die Welt leider immer noch nicht verbessert ...
Das kannst Du so sehen, ja.
> Claus Reibenstein schrieb:
>
>> Hadanite Marasek schrieb:
>>
>>> Peter Schleif schrieb:
>>>
>>>> Ich muss in VBA ein Array in einen validen PHP-Serialize-String
>> ᅵᅵᅵᅵᅵᅵ
>>
>>> Ich habe heute die Welt noch nicht wirklich verbessert, also mal kurz
>>> was gefrickelt (in PHP):
>> ᅵᅵᅵᅵᅵᅵ
>>
>> Thema verfehlt.
>
> Du mᅵkelst gerne rum, oder? Also, gehen wir das mal durch:
>
> "Hat jemand ein Stᅵck Code auf dem ich aufbauen kᅵnnte?
>
> Muss natᅵrlich nicht in VBA sein."
Das hatte ich nicht gesehen. Ok, ein Punkt fᅵr Dich.
>>> function recurse(array $structure ) {
>>> $return = NULL;
>>> $return .= "a:".count($structure).":{";
>>
>> Aua!
>
> Persᅵnliche Prᅵferenz, muss man nicht mᅵgen.
PHP mag das auch nicht, wie Du leicht feststellen kannst, indem Du Dein
Error Reporting mal vernᅵnftig einstellst. Momentan scheinen dort die
Warnings ausgeschaltet zu sein.
>>> if(is_string($value)) {
>>> return "s:".strlen($value).":\"".$value."\";";
>>> }
>>> if(is_integer($value)) {
>>
>> Schon mal was von elseif gehᅵrt?
>
> Ich bevorzuge Wᅵchter-if:
> http://www.php-faq.de/q-stil-waechter.html
Das ist eine vollkommen andere Baustelle. Dort geht es um Schachtelungen
wie diese:
if (...) {
if (...) {
if (...) {
...
} else {
...
}
} else {
...
}
} else {
...
}
Hier hingegen geht es um dieses:
if (...) {
...
} elseif (...) {
...
} elseif (...) {
...
} elseif (...) {
...
}
> elseif verwende ich - ungelogen - nie.
Dann programmierst Du reichlich ineffizient.
Gruᅵ. Claus
> Hier hingegen geht es um dieses:
>
> if (...) {
> ...
> } elseif (...) {
> ...
> } elseif (...) {
> ...
> } elseif (...) {
> ...
> }
Nein es ging um:
if (condition) return value;
if (othercondition) ...
was man natürlich nicht durch if-else ersetzen will.
MfG, Ulf
--
Die Lebensjahre sämtlicher deutscher Kleinkinder betragen
zusammengerechnet etwa 4 Mill. Jahre. Das ist einfach zu alt!
[Loriot]
>>>> function recurse(array $structure ) {
>>>> $return = NULL;
>>>> $return .= "a:".count($structure).":{";
>>> Aua!
>> Persᅵnliche Prᅵferenz, muss man nicht mᅵgen.
>
> PHP mag das auch nicht, wie Du leicht feststellen kannst, indem Du Dein
> Error Reporting mal vernᅵnftig einstellst. Momentan scheinen dort die
> Warnings ausgeschaltet zu sein.
Tja, die sind bei mir immer drin, und da kommt genau gar nichts. Worauf
beziehst Du Dich eigentlich genau?
>> Ich bevorzuge Wᅵchter-if:
>> http://www.php-faq.de/q-stil-waechter.html
>
> Das ist eine vollkommen andere Baustelle. Dort geht es um Schachtelungen
> wie diese:
Fᅵr mich ist das ein generelleres Konzept.
>> elseif verwende ich - ungelogen - nie.
>
> Dann programmierst Du reichlich ineffizient.
Ich habe ja schon gesagt, welche Vorteile ich in meinem Ansatz sehe, die
Nachteile nehme ich in Kauf.
Hallo.
Vielen Dank fᅵr den Code. Hab' ihn jetzt endlich umgesetzt. Funktioniert
bestens mit drei kleinen Anpassungen:
1. In VBA gibt es nicht fᅵr alle Datentypen eine is_XY()-Funktion. Darum
nehme ich stattdessen switch(gettype()). Ist irgendwie auch
ᅵbersichtlicher als die vielen if-return.
2. In VBA werden assoziative Arrays ᅵblicherweise mit Collections
realisiert; nur numerische Arrays sind echte Arrays. Bei der
for-each-Schleife musste ich darum eine Weiche einbauen. Hat aber
natᅵrlich nix mit deinem Code zu tun.
3. Der String soll php auf der Kommandozeile ᅵbergeben werden. Die
Shell-Anweisungen von VBA und Ooo-Basic erwarten die Parameter in
doublequotes und ohne Leerzeichen. Darum musste ich den String am Ende
noch maskieren.
<?php
$str =
"a:10:{s:3:\"int\";i:15;s:6:\"string\";s:20:\"Katzen%20sind%20niedlich\";s:5:\"array\";a:3:{i:0;s:4:\"Hund\";i:1;s:5:\"Katze\";i:2;s:4:\"Maus\";}s:5:\"stuff\";s:1:\"\"\";s:2:\"15\";d:17.5;s:8:\"booleanf\";b:0;s:8:\"booleant\";b:1;s:5:\"empty\";N;s:4:\"Wahr\";N;s:4:\"17.8\";s:5:\"float\";}";
echo "\n".$str."\n\n";
print_r(unserialize(urldecode(stripslashes($str))));
?>
Obwohl das alles nicht viel mit php zu tun, poste ich (fᅵrs Archiv)
unten mal den VBA-Code. Vielleicht sucht ja jemand mal ein ᅵhnliches
Problem.
Vielen Dank.
Peter
Sub test()
Dim oStructure As New KeyCollection
'KeyCollection stellt fᅵr die Eigenschaft .Key bereit,
'die den Items der normalen VBA-Collection fehlt.
oStructure.Add 15, "int"
oStructure.Add "Katzen sind niedlich", "string"
oStructure.Add Array("Hund", "Katze", "Maus"), "array"
oStructure.Add """", "stuff"
oStructure.Add 17.5, 15
oStructure.Add False, "booleanf"
oStructure.Add True, "booleant"
oStructure.Add Null, "empty"
oStructure.Add Null, True
'oStructure.Add "18", Null
oStructure.Add "float", 17.8
Debug.Print mask(recurse(oStructure))
End Sub
Function recurse(oStructure As Variant) As String
Dim i As Integer
Dim vItem As KeyCollectionItem
If IsArray(oStructure) Then
recurse = "a:" & UBound(oStructure) + 1 & ":{"
For i = 0 To UBound(oStructure)
recurse = recurse & serializeValue(i)
recurse = recurse & serializeValue(oStructure(i))
Next
recurse = recurse & "}"
Else
recurse = "a:" & oStructure.Count & ":{"
For Each vItem In oStructure.Items
recurse = recurse & serializeValue(vItem.Key)
recurse = recurse & serializeValue(vItem.Value)
Next
recurse = recurse & "}"
End If
End Function
Function serializeValue(ByVal vValue As Variant) As String
Select Case VarType(vValue)
Case 8, 7:
'/string, date/
serializeValue = "s:" & Len(vValue) & ":""" & vValue & """;"
Case 2, 3, 17:
'/int, long, byte/
serializeValue = "i:" & vValue & ";"
Case 4, 5, 6, 14:
'/single, double, currency, decimal/
serializeValue = "d:" & Trim(Str(vValue)) & ";"
Case 11:
'/boolean/
serializeValue = IIf(vValue, "b:1;", "b:0;")
Case 0, 1:
'/empty, null/
serializeValue = "N;"
Case 9, Is > 8000:
'/collection, array/
serializeValue = recurse(vValue)
Case Else:
'/ToDO: Fehlerbehandlung/
'/z.B. type VarType(vValue) not implemented yet/
MsgBox VarType(vValue) & " " & vValue
End Select
End Function
Function mask(ByVal sValue As String) As String
mask = sValue
mask = Replace(mask, """", "\""")
'mask = Replace(mask, "'", "\'")
mask = Replace(mask, " ", "%20")
End Function
>Claus Reibenstein schrieb:
>> Hadanite Marasek schrieb:
>
>>> function recurse(array $structure ) {
>>> $return = NULL;
>>> $return .= "a:".count($structure).":{";
>>
>> Aua!
>
>Pers�nliche Pr�ferenz, muss man nicht m�gen.
Semantisch sinnvoller w�re hier zumindest:
$return = '';
$return .= ...
Schlie�lich willst Du einen String zur�ckgeben. Dann ist es nur
konsequent, auch mit einem leeren String anzufangen.
Micha