Originally published on php2rust.dev — part of the PHP to Rust course. View this lesson on the original site.
Rust has two main string types: String (owned, growable) and &str (borrowed slice). PHP has a single string type that is copy-on-write.
From the previous lesson: On Slices we introduced borrowing and slice views, how &[T] lets you point at part of an array or Vec without owning or copying the whole thing. &str (“string slice”) is the same pattern for text: a borrowed view into UTF-8 bytes, usually inside a String or a string literal baked into the program. Keep that mental model: String owns the buffer; &str borrows a region of it (or borrows immortal literal text).
Rust
fn main() {
// &str: string slice (literal or borrowed)
let literal: &str = "Hello, world!";
println!("literal: {}", literal);
// String: owned, growable
let mut s = String::from("Hello");
s.push_str(", world!");
println!("{}", s);
// Convert
let from_str: String = "hi".to_string();
println!("from_str: {}", from_str);
let slice: &str = &s[0..5];
println!("slice: {}", slice);
}
&str: fixed view; often used in function parameters.String: heap-allocated, mutable.- Both are UTF-8.
Use case (PHP mindset): pass “some text”, not an owned String
In PHP you might write functions that accept a string or a substring (e.g. something like substr($s, 0, 5)), but Rust splits this into types:
&stris a borrowed view into text. Since it borrows, you can’t “delete”/drop the originalStringwhile the&stris still being used (Rust will refuse to compile).&mut stris a mutable borrow into a substring. Because it borrows the same underlying text, mutating that substring changes the originalString.
fn starts_with_hello(text: &str) -> bool {
text.starts_with("Hello")
}
fn main() {
let s = String::from("Hello, world!");
// Borrow the first 5 bytes as a `&str`
let first_five: &str = &s[0..5];
println!("first_five starts with Hello? {}", starts_with_hello(first_five));
// Mutable borrow: change a substring, and the original `String` changes too
let mut s2 = String::from("hello");
{
let sub: &mut str = &mut s2[0..5];
sub.make_ascii_uppercase(); // "HELLO"
}
println!("s2 is now: {}", s2);
}
PHP
<?php
$literal = "Hello, world!";
$s = "Hello";
$s .= ", world!";
echo "$s\n";
// Single type, copy-on-write
$from_str = "hi";
$sub = substr($s, 0, 5); // New string
PHP strings are mutable in place (with copy-on-write). They can be any byte sequence but are typically UTF-8 when handling text.
Comparison
- Rust:
String(owned) and&str(borrowed). Always UTF-8. No direct byte indexing. - PHP: Single
stringtype. Mutable. Usemb_*for proper character handling.
References
What's next
Next: Structs.
From PHP to Rust — Rust Syntax and Functions