Czy PHP ma symbole takie jak Ruby? A może powinienem użyć ciągów jako kluczy w tablicy asocjacyjnej PHP?PHP odpowiada symbolowi Ruby
Zgaduję, że to ta sama odpowiedź jak w pytaniu Is there a Python equivalent to Ruby symbols?
Czy PHP ma symbole takie jak Ruby? A może powinienem użyć ciągów jako kluczy w tablicy asocjacyjnej PHP?PHP odpowiada symbolowi Ruby
Zgaduję, że to ta sama odpowiedź jak w pytaniu Is there a Python equivalent to Ruby symbols?
PHP definiowalne stałe, ale to naprawdę nie jest bardzo przydatne w tym kontekście.
Więc nie. Użyj ciągów jako kluczy.
Tablice asocjacyjne to Twoja jedyna opcja.
http://railsforphp.com/reference/array/array - Drugi nagłówek.
PHP nie ma nic podobnego do symboli, a nawet stałe działają w PHP znacznie inaczej niż w ruby. Klucze tablicowe muszą być ciągami lub numerycznymi. Możesz przypisać ciąg lub liczbę do stałej, a następnie "użyć" stałej jako klucza tablicy. Ale stałe w PHP są statyczne, więc może to nie być to, czego potrzebujesz, wymaga więcej "podstawowego kodu", a rzeczywisty klucz tablicy nadal będzie albo ciągiem lub liczbą (w oparciu o wartość stałej).
Jeśli twoim problemem jest przeciążenie używania łańcuchów jako kluczy tablicowych i fakt, że tablica jest kopiowana zamiast przekazywana jako referencja za każdym razem, mogę zasugerować, aby użyć stdClass
, czyli w zasadzie klasy obiektu, która może być modyfikowana dynamicznie, jak w tablicy, ale zachowuje się jak obiekt.
Nie, PHP nie ma czegoś takiego. Największym przybliżeniem w PHP byłoby użycie pojedynczych cudzysłowów dla twoich kluczy hashowych - tylko po to, aby upewnić się, że nie ma w nich "interpolacji".
kilka przykładów:
$arr[key]
- to będzie działać jak $arr['key']
w większości przypadków, ale ma kilka wad: a) jeżeli jest rzeczywiście zdefiniowanej stałej (np define('key', 'rubbish')
- będziesz dostępu . $arr['rubish']
Tak, to jest po prostu niebezpieczne b) spowodowałoby to wiadomości „Zawiadomienie” PHP (chyba że powiadomienia są tłumione)
$arr[@key]
. - podobnie jak wcześniej, ale bez powiadomienia. W rzeczywistości tłumienie błędów jest bardzo złe pod względem łatwości konserwacji.
$arr["key"]
- absolutnie prawidłowy sposób, chyba że masz jakieś specjalne symbole wewnątrz podwójnie cytowanego ciągu. Na przykład: "ab\ntc" != 'ab\ntc'
, "ab$c" != 'ab$c'
i tak dalej. Uważam jednak, że jest to trochę paranoiczne, jeśli chodzi o takie przypadki.
$arr['key']
- jest to, moim zdaniem, najbliższy Ruby z arr[:key]
, jak można uzyskać w PHP.
Możesz używać prostych obiektów, aby uzyskać podobny efekt, jak symbole w rubinach. Niektóre funkcje bazy danych mają opcję FETCH_OBJECT, aby emulować ten efekt.
class StoreMe {
public $A;
public $B;
public $C;
public $D;
}
Główną zaletą symboli jest użycie klawiszy skrótów do optymalizacji wydajności i wykorzystania pamięci. Ponieważ PHP używa "Kopiuj przy zapisie" do przechowywania zmiennych, łańcuchy mogą być równoważne jak symbole w ruby. Ale PHP używa pewnego rodzaju tabeli translacji, aby uzyskać indeks tablicy z klucza hash.Więc każda mała tablica ma pewien narzut.
Testscript
pisałem ten mały skrypt, aby przetestować zużycie pamięci z PHP.
error_log("Start: " . memory_get_usage());
$iterations = 10000;
$hash = [];
for ($i=0; $i<$iterations; $i++) {
$hash[] = [
"A" => "Test",
"B" => "Test",
"C" => "Test",
"D" => "Test",
];
}
error_log("String: " . memory_get_usage());
$hash = null;
error_log("Reset: " . memory_get_usage());
$hash = [];
for ($i=0; $i<$iterations; $i++) {
$hash[] = [
"Test",
"Test",
"Test",
"Test",
];
}
error_log("Raw: " . memory_get_usage());
$hash = null;
error_log("Reset: " . memory_get_usage());
$hash = [];
$copy = [
"Test",
"Test",
"Test",
"Test",
];
for ($i=0; $i<$iterations; $i++) {
$hash[] = $copy;
}
error_log("Copy: " . memory_get_usage());
$hash = null;
error_log("Reset: " . memory_get_usage());
$hash = [];
for ($i=0; $i<$iterations; $i++) {
$store = new StoreMe();
$store->A = "Test";
$store->B = "Test";
$store->C = "Test";
$store->D = "Test";
$hash[] = $store;
}
error_log("Object: " . memory_get_usage());
$hash = null;
$store = null;
error_log("Reset: " . memory_get_usage());
Oto wyniki z oficjalnymi obrazami Docker dla PHP. Właściwą wartością jest zużycie pamięci w bajtach.
PHP 5,6
Start: 225680
String: 8837400
Reset: 226088
Raw: 8837400
Reset: 226088
Object: 5580488
Reset: 1209264
PHP 7,0
Start: 355400
String: 4643840
Reset: 355400
Raw: 4643840
Reset: 355400
Copy: 884216
Reset: 355776
Object: 2127096
Reset: 478656
PHP 7,1
Start: 355336
String: 883776
Reset: 355336
Raw: 883776
Reset: 355336
Copy: 883776
Reset: 355336
Object: 2126656
Reset: 478216
Podsumowanie
Obiekty wymagają mniej pamięci, niż oczekiwano. Ale wydaje się, że PHP 5.6 ma problemy z usuwaniem śmieci przy użyciu obiektów. Wyniki PHP 7.1 wydają się być optymalizacją kompilatora, ponieważ nie ma różnicy w "Kopii przy zapisie" i tworzeniu tablic.
Jako że była to przyjęta odpowiedź, chciałbym wyjaśnić, że zdefiniowane przez PHP lub stałe nie są równoważne symbolom Ruby w bardzo wielu aspektach, z wyjątkiem tych, które muszą być wyrażeniami stałymi. – Matthew