Data Models (Eloquent)
Relevant source files
The following files were used as context for generating this wiki page:
The data layer of the PriceBuddy application is built upon Laravel's Eloquent ORM. These models represent the core entities of the system: products, stores, URLs, prices, and tags. They encapsulate the business logic, relationships, and data manipulation for each entity, providing a structured and maintainable way to interact with the database. The entire system is multi-tenant, with most data scoped to the authenticated user.
The core concept revolves around a Product, which can be tracked across multiple Stores via different Urls. Each Url has a history of Price records. Products can also be organized using Tags. All these entities are owned by a User.
Entity Relationship Diagram
This diagram illustrates the primary relationships between the core Eloquent models in the application.
Product
The Product model is the central entity in the application. It represents a specific item that a user wants to track. Each product can have multiple URLs from different stores.
Sources: app/Models/Product.php
Attributes and Properties
| Attribute | Type | Description |
|---|---|---|
title | ?string | The name of the product. |
image | ?string | The URL of the product's image. |
status | Statuses (Enum) | The status of the product (e.g., Published, Archived). |
favourite | boolean | Whether the product is marked as a favorite. |
notify_price | ?float | The price threshold for notifications. A notification is sent if the price is less than or equal to this value. |
notify_percent | ?float | The percentage drop from the initial price that triggers a notification. |
current_price | float | The latest lowest price found across all its URLs. |
price_cache | array | A JSON column storing cached price data, including history, for quick retrieval. |
ignored_urls | array | A list of URLs to ignore during searches. |
user_id | int | Foreign key linking to the users table. |
trend | string (Accessor) | Calculated price trend (Up, Down, Lowest, None). |
primary_image | string (Accessor) | Returns the image URL or a placeholder if empty. |
price_aggregates | Collection (Accessor) | A collection of formatted max, avg, and min prices from the cache. |
Sources: app/Models/Product.php:21-48, app/Models/Product.php:189-223
Relationships
urls(): A product has manyUrlrecords.user(): A product belongs to a singleUser.prices(): A product has manyPricerecords through itsUrls.stores(): A product has manyStores through itsUrls.tags(): A product can have manyTags (polymorphic many-to-many).
Sources: app/Models/Product.php:73-132
Key Methods and Logic
updatePriceCache(): This method rebuilds and updates theprice_cacheJSON column. It gathers price history from all associated URLs, calculates trends, and stores the aggregated data on theProductmodel. It also updates thecurrent_price.buildPriceCache(): Gathers price history from relatedUrlmodels, calculates trends for each URL, and formats the data into a collection of arrays ready to be stored in theprice_cache.getPriceHistory(): Queries the database to get a collection of all historical prices for the product, grouped byurl_id, for the last year.shouldNotifyOnPrice(Price $price): Determines if a notification should be sent based on thenotify_priceandnotify_percentthresholds.booted(): When aProductis deleted, this static method ensures that all its associatedUrlrecords are also deleted, which in turn cascades to deletePricerecords.
Sources: app/Models/Product.php:50-55, app/Models/Product.php:336-341, app/Models/Product.php:403-435
Price Cache Update Flow
This diagram shows the process of updating a product's price cache.
Url
The Url model links a Product to a specific page on a Store's website. It is the direct source for scraping price information.
Sources: app/Models/Url.php
Attributes and Properties
| Attribute | Type | Description |
|---|---|---|
url | ?string | The full URL of the product page. |
store_id | ?int | Foreign key linking to the stores table. |
product_id | ?int | Foreign key linking to the products table. |
buy_url | string (Accessor) | The product URL, potentially modified with an affiliate code. |
latest_price_formatted | string (Accessor) | The most recent price, formatted as a currency string. |
Sources: app/Models/Url.php:23-30, app/Models/Url.php:79-99
Relationships
store(): A URL belongs to oneStore.product(): A URL belongs to oneProduct.prices(): A URL has manyPricerecords.
Sources: app/Models/Url.php:45-61
Key Methods and Logic
createFromUrl(string $url, ...): A static factory method to create aUrland, if necessary, a newProductfrom a given URL string. It scrapes the URL for product details (title, price, image) and finds or creates the associatedStore.updatePrice(...): Scrapes the URL to get the current price and creates a newPricerecord. If no price is provided, it callsscrape().scrape(): Invokes theScrapeUrlservice to fetch data from the URL.
Sources: app/Models/Url.php:116-157, app/Models/Url.php:159-178
URL Creation and Initial Scrape Flow
This diagram shows how a new product and URL are created from a single URL string.
Sources: app/Models/Url.php:116-157
Store
The Store model represents an online retailer. It contains the domains associated with the store and the strategy for scraping product information from its pages.
Sources: app/Models/Store.php
Attributes and Properties
| Attribute | Type | Description |
|---|---|---|
name | string | The name of the store. |
slug | string | A URL-friendly version of the name. |
domains | array | A JSON array of domain names associated with the store. |
scrape_strategy | array | A JSON object defining the selectors/rules for scraping title, price, and image. |
settings | array | A JSON object for various settings, including scraper service and locale. |
user_id | int | Foreign key linking to the users table. |
scraper_service | string (Accessor) | The scraper service to use (e.g., http, api). Defaults to Http. |
scraper_options | array (Accessor) | Key-value options for the scraper service. |
locale | string (Accessor) | The locale for formatting currency (e.g., en_US). |
currency | string (Accessor) | The currency ISO code (e.g., USD). |
Sources: app/Models/Store.php:28-44, app/Models/Store.php:127-170
Relationships
user(): A store belongs to aUser.urls(): A store has manyUrls.products(): A store has manyProducts through itsUrls.
Sources: app/Models/Store.php:82-101
Price
The Price model is a simple model that records a product's price at a specific point in time for a given Url.
Sources: app/Models/Price.php
Attributes and Properties
| Attribute | Type | Description |
|---|---|---|
price | float | The price of the product. |
url_id | int | Foreign key linking to the urls table. |
store_id | int | Foreign key linking to the stores table. |
notified | boolean | Whether a notification has been sent for this price record. |
Sources: app/Models/Price.php:18-24
Relationships
url(): A price record belongs to a singleUrl.store(): A price record belongs to a singleStore.
Sources: app/Models/Price.php:33-44
Tag
The Tag model is used to categorize products. It has a polymorphic relationship with the Product model.
Sources: app/Models/Tag.php
Attributes and Properties
| Attribute | Type | Description |
|---|---|---|
name | string | The name of the tag. |
weight | int | A number used for sorting tags, affecting product group order. |
user_id | int | Foreign key linking to the users table. |
Sources: app/Filament/Resources/TagResource.php:31-40
Relationships
user(): A tag belongs to aUser.products(): A tag can be associated with manyProducts.
Sources: app/Models/Tag.php:38-42, app/Models/Product.php:127-130
Summary
The Eloquent models in PriceBuddy form a well-structured and interconnected system for managing product price tracking data. The Product model acts as the central hub, aggregating data from Urls and Prices. The Store model provides the necessary context and scraping logic, while Tags offer organizational capabilities. All data is user-specific, ensuring a secure, multi-tenant architecture. The extensive use of attribute accessors and custom methods within the models encapsulates complex logic, such as price trend calculation and cache management, keeping the application's controllers and services clean.