bazaar

An e-commerce shop on a hand-rolled PHP microframework - no Laravel, no Symfony. Catalog, session cart, Stripe Checkout, customer accounts and a full admin back office, on hardened sessions and prepared statements only.

bazaar
TL;DR

An e-commerce shop on a hand-rolled PHP microframework, no Laravel, no Symfony. A product catalog, a session cart, Stripe Checkout, customer accounts and a full admin back office. With payments there is no room for shortcuts, so sessions are hardened and only prepared statements reach the database.

Overview

Big PHP frameworks handle a lot for you, security included. bazaar drops them on purpose: a microframework written from scratch means you guard sessions yourself, build queries yourself and are the one responsible for keeping customer data from leaking. There is no layer quietly patching your oversights.

It is a project about discipline, not features. The shop does exactly what you expect a shop to do, but all its value sits in the fact that every point of contact with the user and the database is a boundary you have to watch by hand and on purpose.

A deliberate descent to bare PHP

When you subtract the framework, the safety net that usually lives in the default config goes with it. Escaping, session protection, binding parameters in queries, none of it is free anymore. bazaar treats that as a lesson: to write a secure shop on bare PHP, you must understand every threat the framework normally shields you from.

The discipline here is bracing, because there is nowhere to hide a shortcut. If you stitched a query out of strings somewhere or trusted form data, it shows at once, and the responsibility is unambiguously yours.

From cart to payment

1
Catalog

products with prices, categories and a publication state.

2
Session cart

line items kept server-side, immune to form tampering.

3
Stripe Checkout

payment handed to a specialist provider, without touching card data.

4
Account and back office

order history for the customer, a full admin panel for the owner.

The key is in steps two and three. The cart lives server-side, so prices and quantities are not what came from the browser but what the shop itself decided. Payment goes to Stripe, so a card number never passes through our code, which removes the most dangerous slice of responsibility from the system.

The boundary you guard by hand

!
Warning

The shop takes payments, so mistakes are not cosmetic. Not a single query is stitched together from strings. Prepared statements only, always, because that is the one boundary that actually stops SQL injection.

repository.php · sql
SELECT id, name, price_cents
FROM products
WHERE slug = :slug AND published = 1
LIMIT 1;

Every input from outside is treated as hostile until it is bound to a parameter or escaped. That is not paranoia but the only way a shop without a framework's net can be safe.

The result is not a shop richer in features than the ones on Laravel, but a shop whose security you understand all the way down, because you built it yourself. Every boundary is explicit, every query parameterized, and the most sensitive element, the card data, does not live in our system at all.

Where the boundary is and what guards it

BoundaryGuarded by
Form inputvalidation and escaping
Database queryprepared statements only
Cartserver-side, a hardened session
Card datahanded to Stripe, never with us

More projects

More work from the same category - see how we tackle similar challenges.

Have a similar project?

Get in touch - a quote is free and comes back within an hour.