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.

9 min read • View on GitHub • More from veerpatel1304

A wide marketplace scene where several small shopfronts sit at different distances from a customer point in the center. Survey-like rings and measuring lines radiate outward, and the nearest shop is visually emphasized. The image explains that proximity is the organizing rule of the application, not just a cosmetic filter.
Nearby is not a filter here. It is the system’s main sorting rule, and everything else follows from that.
Key Takeaways

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 app does not just find nearby shops. It uses distance to decide which actions are allowed next.

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.

A close-up scene of a cart tray being checked by a gatekeeper mechanism. On one side, products from the same shop slide smoothly into the tray. On the other side, a product from a different shop is stopped by a mechanical latch. The image explains that the cart enforces vendor boundaries rather than acting as a neutral container.
The cart does not accept everything. It enforces a fulfillment rule that keeps each order inside one shop’s boundary.

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.

Aspectnearshop_de_Typical Laravel or Symfony marketplace
Speed of prototypingVery fast. The app logic sits close to the page and the query.Slower at first, because structure and conventions come with the framework.
Dependency footprintMinimal. Mostly PHP, MySQL, and browser APIs.Heavier. More packages, more indirection, more moving parts.
Geolocation logicDirectly embedded in SQL and request handling.Often wrapped in services, jobs, or helper layers.
Cart rulesHard constraint: one shop per cart.Usually modeled through cart grouping, vendor partitions, or checkout branching.
State managementMostly sessions and direct request flow.More formal session, service, and validation layers.
MaintainabilityReadable at small scale, brittle as complexity grows.More scalable for teams, but with more ceremony.
Security postureRiskier, especially where raw SQL and direct session checks are used.Typically stronger defaults and clearer escape hatches.
Best fitA 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);