I am developing a web app that interfaces with an ERP production database and the data is being retrieved by a complex SQL query with many joins and aliases before being passed to my controllers and views which modify them in different ways.
The result might be, for example, an array of products that contains all relevant information for each purchase such as model, serial number, customer, etc., and in a smaller scale app these would certainly all be stored in the same table.
However because I am pulling from a very complex ERP solution these details are taken from many different tables, but I'd like to treat it as a single table in my model.
Is there any way to accomplish this so that I can use Eloquent as usual? Things like Product::all()
do not work, though I can call custom methods like Product::getWhere($serial)
but I'd rather do this the Eloquent way since it is easier and makes pagination much nicer to work with.
Here is an idea of what my queries looks like:
SELECT
[PSerials].[ElementID] AS [ProductElementID],
[PSerials].[SerialNumber] AS [SerialNumber],
[PSerials].[SNStatus] as [ProductStatus],
[PSerials].[JobID] AS [JobID],
[Element].[Desc] AS [Description],
[PSerials_UD].[Prog] AS [ProgramNum],
[PSerials_UD].[Elec] AS [ElecPrint],
[PSerials_UD].[SinglePHVolt_c] AS [SinglePHVolt],
[PSerials_UD].[SinglePHAmp_c] AS [SinglePHAmp],
[PSerials_UD].[ThreePHVolt_c] AS [ThreePHVolt],
[PSerials_UD].[ThreePHAmp_c] AS [ThreePHAmp],
[PSerials_UD].[Notes_c] AS [Notes],
[PSerials_UD].[WarrantyExpDate_c] AS [WarrantyExpDate],
[QuoteDtl].[QuoteNum] AS [QuoteNum],
[QuoteDtl].[QuoteComment] AS [QuoteComment],
[OrderDtl].[RequestDate] AS [ShipDate],
[Customer].[CustID] AS [CustomerID],
[Customer].[Name] AS [CustomerName],
[Customer1].[CustID] AS [ShipToCustomerID],
[Customer1].[Name] AS [ShipToCustomerName]
FROM Erp.PSerials AS PSerials
INNER JOIN Erp.Element AS Element ON
PSerials.Company = Element.Company AND PSerials.ElementID = Element.ElementID
AND (Element.ProdCode = 'MACH' AND Element.ClassID = 'MAC')
INNER JOIN Erp.PSerials_UD AS PSerials_UD ON
PSerials_UD.ForeignSysRowID = PSerials.SysRowID
LEFT OUTER JOIN Erp.PProd AS PProd ON PProd.JobID = PSerials.JobID
LEFT OUTER JOIN Erp.OrderDtl AS OrderDtl ON PProd.Company = OrderDtl.Company
AND PProd.OrderNum = OrderDtl.OrderNum AND PProd.OrderLine = OrderDtl.OrderLine
LEFT OUTER JOIN Erp.QuoteDtl AS QuoteDtl ON OrderDtl.QuoteNum = QuoteDtl.QuoteNum
AND OrderDtl.QuoteLine = QuoteDtl.QuoteLine
LEFT OUTER JOIN Erp.Customer AS Customer ON OrderDtl.Company = Customer.Company
AND OrderDtl.CustNum = Customer.CustNum
LEFT OUTER JOIN Erp.Customer AS Customer1 ON PSerials.Company = Customer1.Company
AND PSerials.ShipToCustNum = Customer1.CustNum
I have it sitting in a static variable on my Product
model and then have custom functions that simple tack on SQL queries to the end as needed, but this isn't elegant and it isn't fun to work with, here's an example of how I use these queries:
public static function getWhere($serial)
{
$query = DB::select(DB::raw(Self::$baseQuery));
$collection = new \Illuminate\Support\Collection($query);
$product = $collection->where("SerialNumber", $serial)->first();
return $product;
}
Does anyone how I can have my model simply treat queries like that as if they were a simple table, or is there perhaps another way to go about doing this?
Update
Thanks to Zamrony P. Juhara's advice below I was able to successfully create an SQL view and tell my Products model to reference is like a table:
class Product extends Model
{
protected $table = 'dbo.ProductInfo';
}
Now Product::all()
works as expected.
Regarding the limitations pointed out by Peh this app is purely for viewing the data that exists in the ERP software and won't need to update or delete any records, so in this case the SQL view is absolutely perfect.
You can turn SQL command into VIEW (CREATE VIEW) then use it just like ordinary table in your model.