nearshop_de_: The PHP Marketplace That Treats Distance Like a Database Rule
A deep dive into a flat PHP e-commerce stack that turns geolocation, vendor boundaries, and delivery logic into first-class application behavior.
- nearshop_de_ makes distance a business rule, not a display choice, by pushing proximity into the query layer and the shopping flow.
- The cart is a policy engine, because the app refuses to mix products from different shops and turns fulfillment into a single-path system.
- The schema history reads like product pressure made visible, with each phase adding logistics logic that the database itself has to carry.
- The codebase is intentionally simple, but that simplicity also exposes the classic tradeoff of raw PHP: fast to build, easier to understand, and much easier to outgrow.
The marketplace starts with distance
Most marketplaces treat location as a filter. This repo treats it as structure. Nearby shops are not just listed first. They are ranked through a geospatial query that makes distance part of the application’s core logic, which is why the product feels more like a local routing system than a generic catalog.
That matters because it changes the business model. If proximity is the first rule, then search, cart behavior, and delivery planning all have to bend around it. The user does not merely browse inventory. They enter a bounded neighborhood of options.
The implementation is direct. The repo’s nearby-shop query uses the Haversine formula inside SQL, so latitude and longitude are not decorative data fields. They are the inputs to ranking. That is the cleanest possible expression of the project’s thesis: physical closeness becomes an application primitive.
One cart, one shop, one delivery path
The cart rule is the most revealing product decision in the codebase. If a user tries to mix items from two shops, the add-to-cart path blocks it. That simplifies logistics, but it also declares the real shape of the marketplace. Each order belongs to one vendor, one preparation process, and one delivery path.
| Aspect | nearshop_de_ | Typical Laravel or Symfony marketplace |
|---|---|---|
| Speed of prototyping | Very fast. The app logic sits close to the page and the query. | Slower at first, because structure and conventions come with the framework. |
| Dependency footprint | Minimal. Mostly PHP, MySQL, and browser APIs. | Heavier. More packages, more indirection, more moving parts. |
| Geolocation logic | Directly embedded in SQL and request handling. | Often wrapped in services, jobs, or helper layers. |
| Cart rules | Hard constraint: one shop per cart. | Usually modeled through cart grouping, vendor partitions, or checkout branching. |
| State management | Mostly sessions and direct request flow. | More formal session, service, and validation layers. |
| Maintainability | Readable at small scale, brittle as complexity grows. | More scalable for teams, but with more ceremony. |
| Security posture | Riskier, especially where raw SQL and direct session checks are used. | Typically stronger defaults and clearer escape hatches. |
| Best fit | A focused prototype or a tightly scoped local-commerce app. | A team-built product expected to grow into many features. |
That table is the key tradeoff. The project is not trying to be a universal commerce engine. It is encoding one operational model with as little friction as possible. In that sense, the repo is less a marketplace framework than a business rule engine with a storefront attached.
The repo reads like a timeline of product maturity
The phase-based SQL files tell a story without needing prose. Early schema work establishes the basic store and user flow. Later changes add vendor structure and delivery-related fields. You can see the database absorbing new requirements as the product moves from simple commerce toward multi-vendor logistics.
That is a useful pattern to study because it shows where complexity really lands. In a system like this, product evolution does not just add pages. It adds invariants. A shop boundary becomes a database concern, not a frontend convention. Delivery becomes a schema concern, not a post-order note.
<?php
// Simplified pattern from the cart gate logic
$existingShopId = get_existing_cart_shop_id($conn, $userId);
$newShopId = get_product_shop_id($conn, $productId);
if ($existingShopId !== null && $existingShopId !== $newShopId) {
echo json_encode([
'success' => false,
'message' => 'You can only add items from one shop at a time.'
]);
exit;
}
add_item_to_cart($conn, $userId, $productId, $qty);