Sign in

Kevin Bond

@zenstruck.com
434 followers 45 following 28 posts

Open Source, #PHP, #Symfony Developer. Writer @SymfonyCasts.com, @Symfony.com Core Member. Author of github.com/zenstruck packages.

PostsRepliesMedia
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 25/09/2026
🔐 Symfony Security: Going Further #4 Wrong password, unknown email, disabled account... your login form answers all three with "Invalid credentials." That's deliberate. Let's decide how much we actually want to give away. symfonycasts.com/screencast/s...
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 24/09/2026
Symfony Cache Contracts have a sneaky little trick 👀 Use `beta: INF` to force-refresh a cached value without deleting the old one first - so other requests can keep using it while the fresh value is computed. See how it works 👇 symfonycasts.com/blog/symfony...
symfonycasts.com
Force Refresh a Symfony Cache Item with beta: INF
Symfony's Cache Contracts have a mysterious third argument: "$beta". Here's where its name comes from, how it prevents cache stampedes, and how "beta: INF" lets you force a cache item to refresh…
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 23/09/2026
🔐 Symfony Security: Going Further #3 Disabling an account blocks the next login... but a user already browsing doesn't even notice. Let's show them the door mid-click. 👋 symfonycasts.com/screencast/s...
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 22/09/2026
🔐 Symfony Security: Going Further #2 Deleting a user is forever. Sometimes you just want to switch them off. Let's teach our login to check more than the password. symfonycasts.com/screencast/s...
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 17/09/2026
🚀 New on the blog: our ideal GitHub Actions setup for Symfony apps! Tests, linting, PHPStan, code style, database/schema checks, Symfony-aware diagnostics, asset compilation, plus a scheduled Composer security audit. A solid CI baseline you can actually build from: symfonycasts.com/blog/ideal-g...
symfonycasts.com
Ideal GitHub Actions for Symfony Apps
A practical, modern GitHub Actions setup for Symfony apps, covering tests, linting, static analysis, database checks, Symfony-aware diagnostics, and scheduled dependency security audits.
063
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 16/09/2026
🚨 New Course 🚨 🔐 Symfony Security: Going Further #1 A 403 status code tells us we don't have access... but it also tells us the thing exists. Let's borrow the trick GitHub uses on private repositories 🖖 symfonycasts.com/screencast/s...
021
Reposted by Kevin Bond
Simon André @smnandre.dev · 15/09/2026
I'm excited to be heading to SymfonyCon Warsaw this November! I'll be talking about PlaywrightPHP, and some of the new things it brings to testing Symfony apps... smnandre.dev/blog/see-you... #playwright @symfony.com @ux.symfony.com
062
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 03/09/2026
🔐 Symfony Security Basics #19 Let's finish by building a complete user registration flow! We'll generate the registration form, add validation, save our new user, log them in automatically, and finish with a discussion about user enumeration. symfonycasts.com/screencast/s...
021
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 01/09/2026
🔐 Symfony Security Basics #18 Symfony dispatches events throughout the security process. Let's explore some of the most useful ones, then put one to work tracking each user's last login! symfonycasts.com/screencast/s...
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 27/08/2026
🔐 Symfony Security Basics #17 Let's protect our login form from brute-force attacks! We'll enable Symfony's login throttling, see what happens when we trip the limiter, then dig into its configuration and how it works. Delightful nerdery!
symfonycasts.com
Limiting Login Attempts
Enables Symfony login throttling to limit failed login attempts, explains the required RateLimiter dependency and cache-backed storage, and shows how the default per-IP/per-username and global IP limits...
011
Reposted by Kevin Bond
nikophil.bsky.social @nikophil.bsky.social · 07/09/2026
Few weeks ago, I finally released "zenstruck/foundry-behat" don't hesitate to try it and give some feedback! symfony.com/bundles/Zens... @zenstruck.com #PHP #symfony
symfony.com
ZenstruckFoundryBundle Documentation
Official documentation of ZenstruckFoundryBundle, a bundle for Symfony applications
032
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 25/08/2026
🔐 Symfony Security Basics #16 User impersonation is super useful... until you forget you're impersonating someone! Let's make it painfully obvious when we're switched to another user and add an easy way to exit.
symfonycasts.com
Exiting Impersonation & IS_IMPERSONATOR
Adds a visible production indicator for Symfony user impersonation and provides a dedicated way to exit impersonation, including redirecting back to the admin user list afterward.
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 20/08/2026
🔐 Symfony Security Basics #15 Need to debug a problem from a user's perspective? Let's enable Symfony's user impersonation feature so admins can temporarily switch to another user without ever knowing their password.
symfonycasts.com
Impersonating Users with switch_user
Impersonation with switch_user lets an admin temporarily log in as another user, and this chapter shows how to enable it in Symfony security, expose switch links in a user admin CRUD, and route the impersonated...
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 18/08/2026
🔐 Symfony Security Basics #14 Hiding an action a user can't access is good UX, but it's not security! Let's enforce our voter permissions in the controller, then give admins the power to bypass them.
symfonycasts.com
Denying Access with a Voter
Introduces Symfony voters as the mechanism for denying or allowing access based on custom authorization logic beyond simple roles.
011
Kevin Bond @zenstruck.com · 28/08/2026
I’m really proud to be part of this one. @smnandre.dev had the brilliant idea to connect Playwright’s request interception directly to Symfony’s kernel - and I’m incredibly excited about what we’re building on top of it. Real browser. Real JS. Symfony kernel. 🤯
121
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 17/08/2026
Doctrine lazy objects used to rely on generated proxy classes that extended your entities. PHP 8.4 makes them native. Same lazy-loading magic - fewer workarounds - and your entities can finally be "final". 🎉 See how lazy objects work 👉 youtu.be/X0HhrOnkGlc
youtu.be
Doctrine Native Lazy Objects Explained
Doctrine uses lazy objects to avoid loading related entities until you actually need their data. Previously, Doctrine generated special proxy classes that extended your entities. With PHP 8.4 and DoctrineBundle 3, PHP can handle lazy objects natively - no generated proxy classes required. The practical payoff? Your relationships still load only when accessed, but your entities can finally be marked as final. Watch the full SymfonyCasts course 👉 https://symfonycasts.com/screencast/symfony8-upgrade/doctrine
021
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 14/08/2026
🔐 Symfony Security Basics #13 Roles are great, but sometimes permissions need to be more precise. Let's create a custom voter to decide whether the current user can edit or delete a specific object.
symfonycasts.com
Creating a Custom Voter
Introduces the idea of creating a custom Symfony security voter to make authorization decisions beyond the built-in roles system.
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 11/08/2026
One of Symfony's * coolest * security features: 1) Users log in 2) Symfony checks their password hash. 3) Old algorithm? Rehash and save automatically 🔐 Automatic security upgrades over time! youtu.be/Bu8ZDbXAsq8
youtu.be
Symfony Password Upgrading Explained
Symfony can automatically upgrade old password hashes as users log in 🔐 When a user successfully authenticates, Symfony checks whether their stored password hash uses an outdated algorithm. If it does, Symfony rehashes the submitted plain text password with the current hasher and saves the new hash. No password reset needed. No user interruption. Just stronger hashes over time. Check out the full course 👉 https://symfonycasts.com/screencast/symfony8-security
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 05/08/2026
"Remember Me" is convenient. It's also the reason many websites ask you to re-enter your password before changing your email address, password, or other sensitive settings. There's a good security reason for that 🔐 youtu.be/j2s_xZgYNss
youtu.be
Why "Remember Me" Isn't Fully Authenticated
Checking "Remember Me" keeps users logged in, but that doesn't mean they're fully authenticated. A remembered user is less trustworthy than someone who just entered their password. That's why sensitive actions - like changing an email address or password - often require you to authenticate again. It's a small distinction that makes a big difference for your application's security. Watch the full SymfonyCasts lesson 👉 https://symfonycasts.com/screencast/symfony8-security/authentication-attributes
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 04/08/2026
🔐 Symfony Security Basics #12 Fetching the current user is easy. Fetching it elegantly is even better. Let's compare a few approaches and finish with the expressive #[CurrentUser] attribute.
symfonycasts.com
Fetching the User in Services/Controllers
Shows three ways to fetch the currently logged-in user in Symfony—via AbstractController::getUser(), the Security service, and controller argument resolvers—and how to make the result type-safe so...
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 30/07/2026
A cautionary tale for web developers: If a request changes state, it should never be a GET. Browsers, crawlers, and link previewers are allowed to make GET requests automatically. The garage door story is worth hearing... 😅 youtu.be/A4ujMeiG_v8
youtu.be
A Cautionary Tale About GET Requests
A cautionary tale for every web developer. Someone built a smart garage door controller with a GET endpoint that toggled the door. Sounds convenient... until a browser, crawler, or link preview decided to "help" by making the request automatically. If a request changes state, it should never be a GET. Watch the full SymfonyCasts lesson 👉 https://symfonycasts.com/screencast/symfony8-security/logout-csrf
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 29/07/2026
🔐 Symfony Security Basics #11 Our User class is a Doctrine entity, which means it can have normal Doctrine relationships. Let's add one and use it to personalize our application.
symfonycasts.com
User Doctrine Relationship
On our app's homepage, we have the concept of "MyShip". It's intended to be the current user's starship
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 28/07/2026
TailwindBundle 1.0 is here! :tada: Add Tailwind CSS to your Symfony + AssetMapper app, with no Node required. A huge thank you to everyone who contributed, reported issues, and helped us reach 1.0! Check out the release: github.com/SymfonyCasts...
github.com
Release v1.0.0 · SymfonyCasts/tailwind-bundle
What's Changed Remove deprecation layer by @kbond in #130 Remind users to clear the cache after config changes by @kbond in #136 Authenticate the GitHub API call to avoid rate limiting by @Amoifr ...
061
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 27/07/2026
🔐 Symfony Security Basics #10 Why assign users five roles when one will do? Let's use Symfony's role hierarchy to inherit permissions, then secure an entire admin section with `access_control`.
symfonycasts.com
Role Hierarchy & Access Control
Did you know roles can have children? Yep! And a parent role inherits all the child roles. This is called role hierarchy
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 23/07/2026
🔐 Symfony Security Basics #9 Let's compare a few different ways to protect a page with a custom user role. Then we'll follow the login flow to access it and fix a sneaky Turbo gotcha along the way!
symfonycasts.com
User Roles
Let's dive deeper into user roles and how they can be used to control access to different parts of your application. We have this link to our "/parts" page, which lists a bunch of Starship parts
021
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 21/07/2026
🔐 Symfony Security Basics #8 A remembered login isn't the same as a fresh login. Let's explore Symfony's authentication attributes and see how they can help protect sensitive actions.
symfonycasts.com
Authentication Attributes
Symfony’s special authentication attributes let you distinguish between public, remembered, and fully authenticated users, so you can protect sensitive actions more precisely than with roles alone.
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 20/07/2026
Let's take a tour through the internals of Brontie, our AI assistant, we'll take a peek into how it actually works inside SymfonyCasts! 🦕 🤖 symfonycasts.com/blog/brontie...
symfonycasts.com
How We Built Brontie your AI Assistant
Brontie is a new AI assistant for SymfonyCasts. Learn how we built it, how it works, and how you can get involved
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 15/07/2026
Me: "Which password hashing algorithm should I choose?" Symfony: "Don't worry, I've got this." 🔐 ✨ youtu.be/dizl8aIqhCo
youtu.be
Symfony's Smart Password Hasher
Symfony has a password hasher setting called auto and it's kind of magical ✨. Instead of choosing a specific hashing algorithm yourself, Symfony automatically uses the strongest supported option available. Even better, it can still verify passwords created with older algorithms, so existing users keep logging in normally while new passwords get the latest protection. One more reason to keep your Symfony version up to date 🚀 Watch the full course 👉 https://symfonycasts.com/screencast/symfony8-security
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 13/07/2026
🔐 Symfony Security Basics #7 We're using session-based authentication, so let's take a peek behind the curtain to see how it works. Then we'll enable Symfony's "Remember Me" feature so users don't need to log in every time they reopen their browser.
symfonycasts.com
Enabling "Remember Me" Feature
Enables Symfony’s “remember me” login persistence so users stay authenticated across browser sessions instead of being logged out when the session ends.
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 08/07/2026
Encryption is a locked box 🔐 Hashing is a fingerprint 👆 One is designed to be opened later. The other is designed to never reveal the original value. -- A poem from the SymfonyCasts team youtu.be/XqFviPUn3UY
youtu.be
Hashing vs Encryption: What's the Difference?
Hashing and encryption are both used in security, but they solve different problems. 🔐 Encryption is reversible. With the right key, you can get the original data back. 👆Hashing is one-way. You can verify a match, but you can't realistically reconstruct the original value. That's why passwords should be hashed, not encrypted. Watch the full course 👉 https://symfonycasts.com/screencast/symfony8-security
021
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 07/07/2026
🔐 Symfony Security Basics #6 Let’s see why using a simple link for logout is a bad idea. We’ll look at the reason GET requests should never change application state, then secure our logout flow with POST and CSRF protection.
symfonycasts.com
Protecting Logout with CSRF
Protecting logout from CSRF by changing it from a GET link to a POST form and enabling Symfony’s logout CSRF protection in the security firewall.
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 01/07/2026
Upgrading to Symfony 8 #6 (Bonus) AI is changing security research, and that means more vulnerabilities are being found and fixed than ever before. Let's explore "composer audit", CVEs, and how to automate dependency security checks.
symfonycasts.com
Composer Audit and Security Updates
Uses composer audit to find dependency vulnerabilities, interpret advisories/CVEs, temporarily ignore known risks in composer.json, apply fixed updates, and automate recurring security checks with GitHub...
022
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 29/06/2026
🔐 Symfony Security Basics #5 Time to improve our user experience! We'll detect whether someone is logged in, show the appropriate login/logout links, and learn a handy trick for generating logout URLs. symfonycasts.com/screencast/s...
symfonycasts.com
app.user and Login/Logout Links
Uses Symfony’s app.user variable and route-based login/logout links to show the current authentication state in templates and let users sign in or sign out cleanly
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 22/06/2026
🔐 Symfony Security Basics #4 Hashing and encryption are very different things. We'll compare them, & see how Symfony automatically chooses the best password hashing algorithm and transparently upgrades your users as better algorithms become available.
symfonycasts.com
Understanding Password Hashing
Ok, we left off trying to login with a valid username and password, but it didn't work... Let's take a moment to understand why. Over in the terminal, dump our user table with: """terminal symfony console...
011
Kevin Bond @zenstruck.com · 17/06/2026
I've been thinking about this for years. Most Symfony best practices encourage code that's explicit and hard to misuse. Doctrine entities have always felt like a strange exception. There are reasons we do it this way... but I think ObjectMapper changes the equation.
211
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 16/06/2026
🔐 Symfony Security Basics #3 Time to log in! We'll generate a login form with MakerBundle, see how Symfony's built-in form authenticator works, explore the generated code, and take a peek at the CSRF protection that's keeping us safe.
symfonycasts.com
Creating a Login Form
We have our user provider configured and a user in our database. Now we need a way to log them in! There are several different ways to do this, but we'll focus on *session-based* authentication with an...
031
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 15/06/2026
Need clarification on a SymfonyCasts lesson without waiting for a reply? Meet Brontie 🦕, our new AI companion that understands the course and chapter you're currently watching. Read more about Brontie and why we built it: symfonycasts.com/blog/brontie...
symfonycasts.com
Meet Brontie, your AI Companion
Meet Brontie - your new SymfonyCasts companion. Part dinosaur, part AI, fully obsessed with Symfony
021
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 10/06/2026
🔐 Symfony Security Basics #2 In order for users to log in, we need a user object and a user provider. Let’s build the most common implementation: a database-backed user/provider + a user factory to quickly spin them up in our dev & test environments.
symfonycasts.com
Creating the User Class
The first thing we need to actually authenticate someone is a special *user* class. This is a class that must implement "UserInterface" provided by Symfony
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 08/06/2026
🚨 New course 🚨 🔐 Symfony Security Basics #1 Symfony Security is the gatekeeper of your application. We'll install the Security component, explore the default configuration, talk firewalls, & learn the difference between authentication & authorization.
symfonycasts.com
Installing the Security Bundle
Hey Friends! Welcome to the Symfony Security course! In this tutorial, we're going to explore one of the most important parts of any web application: controlling who can access your site and what they're...
021
Kevin Bond @zenstruck.com · 05/06/2026
Thanks, #SymfonyDay Montreal! We had a great time at the @SymfonyCasts.com booth meeting members of the community and talking #Symfony. Also pictured: future #Symfony developers?! Maybe someday they'll finally get my 10-year-old Doctrine ORM PR merged. 🙃🤪🤞
SymfonyCasts booth
060
Kevin Bond @zenstruck.com · 03/06/2026
Talking to AI is a strange mix of being a tyrant-king "excellent idea, sir" and arguing with my 8-year-old "you're not listening to me!"
010
Kevin Bond @zenstruck.com · 02/06/2026
🇨🇦🚆🇨🇦 En route to Montreal for #SymfonyDay with our two newest @symfonycasts.com interns! #Symfony
151
Kevin Bond @zenstruck.com · 28/05/2026
I'm so happy "named autowiring aliases without the Target attribute" in #Symfony is being deprecated! I recently did a quick video on the dangers: www.youtube.com/watch?v=t2Cd...
youtube.com
The Hidden Danger of Named Autowiring
YouTube video by SymfonyCasts
021
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 26/05/2026
Symfony upgrades do not have to be scary 😌 Deprecations are your roadmap: Fix warnings in 7.4 → upgrade safely to Symfony 8 🚀 0 deprecations = no surprises. symfonycasts.com/blog/depreca...
symfonycasts.com
Symfony Deprecations Explained (Upgrade Without Breaking Things)
Symfony upgrades do not have to be stressful. Thanks to Symfony's deprecation system, you can fix future breaking changes before upgrading
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 25/05/2026
Symfony form tip 💡 `form_row()` renders everything. `form_widget()` renders just the field itself. Need full control? Render the label, widget, errors, and help text separately 🎨 youtu.be/uRykFN4fk-s
youtu.be
Symfony Forms: form_row() vs form_widget()
In Symfony Forms, the actual HTML input, select, and button elements are called widgets. Need more control over your form layout? Use `form_widget()` to render just the field element instead of the entire `form_row()`. You can also render each part separately: - `form_label()` - `form_widget()` - `form_errors()` - `form_help()` Perfect for custom form layouts 🎨 Check out the full course 👉 https://symfonycasts.com/screencast/symfony-forms
131
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 19/05/2026
Upgrading to Symfony 8 #5 With the "hard" work behind us, the actual jump from Symfony 7.4 to 8.0 should be pretty easy. Plus, we'll check out a nifty Composer command afterward to confirm we have no outdated 😉 packages.
symfonycasts.com
Upgrading to Symfony 8.0!
Symfony 7.4? Check
031
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 13/05/2026
Upgrading to Symfony 8 #4 Fixing all deprecations in Symfony 7.4 is required before upgrading to Symfony 8. Let's look at how to find them and some tricks to make life easier! symfonycasts.com/screencast/s...
symfonycasts.com
Tracking & Fixing Deprecations
Let's revisit deprecations as these are important to fix. As mentioned earlier, before you can safely jump to Symfony 8
011
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 08/05/2026
Upgrading to Symfony 8 #3 Now that we’re on PHP 8.4, let's upgrade DoctrineBundle to v3. This unlocks native lazy objects in Doctrine, my favorite PHP 8.4 feature! Let’s see how they change Doctrine and your entities.
symfonycasts.com
Upgrading Doctrine & Native Lazy Objects
We need to upgrade the doctrine-bundle... but before we do, I want to give a refresher on a really cool Doctrine feature: lazy objects. Open up "src/Entity/StarshipPart
021
Reposted by Kevin Bond
Symfony @symfony.com · 08/05/2026
🚀 New in Symfony 8.1: Console Argument Resolvers ➡️ symfony.com/blog/new-in-symfony-8-1…
0104
Reposted by Kevin Bond
SymfonyCasts @symfonycasts.com · 07/05/2026
Join us next month on June 4 in Montreal, Canada for SymfonyDay! There is an awesome lineup of speakers and I can't wait to see you there! 🎟️ Get your ticket: live.symfony.com/2026-montreal/
011