maybe we can see to far and think in ORM https://en.wikipedia.org/wiki/Object-relational_mapping
an idea only
regards
Marcelo VÃa
No I wish See how Make the same sample of Jeff Bott ( made with tdata and trecord)
but with Tdatabase and tdataRow of Fivetech
#include "fivewin.ch"
REQUEST DBFCDX
#ifndef __XHARBOUR__
EXTERNAL TDOLPHINQRY
#endif
static oCn
//----------------------------------------------------------------------------//
function Main()
local aSrc := { "DBF", "TDATABASE", "FWMARIADB", "ADO" }
local nSrc
local oEmp
#ifndef __XHARBOUR__
AADD( aSrc, "DOLPHIN" )
#endif
SET DATE ITALIAN
SET CENTURY ON
RDDSETDEFAULT( "DBFCDX" )
nSrc := Alert( "Select Data Source Type", aSrc )
if nSrc == 0
return nil
endif
if aSrc[ nSrc ] == "FWMARIADB"
oCn := FW_DemoDB()
elseif aSrc[ nSrc ] == "ADO"
oCn := FW_OpenAdoConnection( "xbrtest.mdb", .t. )
elseif aSrc[ nSrc ] == "DOLPHIN"
oCn := FW_DemoDB( "DLP" )
endif
TEmployee():cDbType := Upper( aSrc[ nSrc ] )
oEmp := TEmployee():New( 101 )
? oEmp:cDbType
? oEmp:id, oEmp:FullName, oEmp:City
? oEmp:YearsWorked, oEmp:Gratuity
? oEmp:Salary
oEmp:PayIncrease( 2000 )
? oEmp:Salary
oEmp:Edit()
oEmp:Close()
if !Empty( oCn )
if aSrc[ nSrc ] $ "FWMARIADB,DOLPHIN"
oCn:End()
endif
endif
? "Done"
return nil
//----------------------------------------------------------------------------//
CLASS TEmployee FROM TDataRow
CLASSDATA cDbType AS CHARACTER INIT "DBF"
CLASSDATA employees
CLASSDATA nCount INIT 0
DATA oRs
METHOD New( nID ) CONSTRUCTOR
ACCESS FullName INLINE Trim( ::First ) + ", " + Trim( ::Last )
ACCESS YearsWorked INLINE YEAR( Date() ) - YEAR( ::HireDate ) - ;
If( SUBSTR( DTOS( DATE() ), 5 ) < SUBSTR( DTOS( ::HireDate ), 5 ), 1, 0 )
METHOD PayIncrease( n ) INLINE ( ::Salary += n, ::Save(), ::Salary )
ACCESS Gratuity INLINE ROUND( ::Salary * ::YearsWorked / 2, 0 )
METHOD OpenTable() //used only by DBF and TDatabase
METHOD Close()
ENDCLASS
//----------------------------------------------------------------------------//
METHOD New( nID ) CLASS TEmployee
local cSql
if ::cDbType $ "DBF,TDATABASE"
::OpenTable()
if ::cDbType == "DBF"
( ::employees )->( DBSEEK( nID ) )
else
::employees:Seek( nID )
endif
else
cSql := "SELECT * FROM customer WHERE ID = " + cValToChar( nID )
::oRs := If( ::cDbType == "ADO", FW_OpenRecordSet( oCn, cSql ), oCn:Query( cSql ) )
endif
::Super:New( IfNil( ::oRs, ::employees ) )
::lNavigate := .f.
return Self
//----------------------------------------------------------------------------//
METHOD OpenTable() CLASS TEmployee
if !File( "CUSTOMER.CDX" )
USE CUSTOMER EXCLUSIVE
FW_CdxCreate()
CLOSE DATA
endif
if ::employees == nil
if ::cDbType == "DBF"
USE CUSTOMER NEW SHARED ALIAS ( ::employees := cGetNewAlias( "CUST" ) )
SET ORDER TO TAG ID
GO TOP
elseif ::cDbType == "TDATABASE"
::employees := TDataBase():Open( nil, "CUSTOMER" )
WITH OBJECT ::employees
:SetOrder( "ID" )
:GoTop()
END
endif
::nCount := 0
endif
return nil
//----------------------------------------------------------------------------//
METHOD Close() CLASS TEmployee
if ::cDbType $ "DBF,TDATABASE" .and. !Empty( ::employees )
::nCount--
if ::nCount < 1
if ::cDbType == "DBF"
( ::employees )->( DBCLOSEAREA() )
else
::employees:End()
endif
::employees := nil
::nCount := 0
endif
elseif !Empty( ::oRs )
if ::cDbType $ "FWMARIADB,ADO"
::oRs:Close()
elseif ::cDbType == "DOLPHIN"
::oRs:End()
endif
::oRs := nil
endif
return nil
//----------------------------------------------------------------------------//Silvio.Falconi wrote:No I wish See how Make the same sample of Jeff Bott ( made with tdata and trecord)
but with Tdatabase and tdataRow of Fivetech
#include "fivewin.ch"
Function Main()
Local oCustomer, oCustomers
Local cCustNo
Field custno, company
REQUEST DBFCDX
rddsetdefault( "DBFCDX" )
set deleted on
ferase("arcust.cdx")
// Just for testing
// Must use TAG clause with CDXs
use arcust exclusive
index on CUSTNO tag "CUSTNO" to arcust
index on upper(COMPANY) tag "COMPANY" to arcust
use
// Instantiate the object
cCustNo:="10007"
oCustomer:= TCustomer():new(cCustNo)
oCustomer:display()
/* Testing
msgInfo( oCustomer:Company,"oCustomer:Company")
msgInfo( oCustomer:getBalance(), "Customer Balance" )
msgInfo( oCustomer:paymentStatus(), "Payment Status" )
msgInfo( oCustomer:PaymentTerms(), "Payment Terms" )
msgInfo( oCustomer:YearToDateSales(),"Year To Date Sales" )
*/
oCustomer:end()
Return nil
//--- Customer class
CLASS TCustomer from TDataRow
DATA oTable
METHOD New( cCustNo )
METHOD ApplyPayment( nAmount, dDate)
Method Display()
METHOD End()
Method GetBalance()
Method PaymentStatus()
Method PaymentTerms()
Method PastDueAmount()
Method PastDueDays()
Method PTDSales() inline ::ptdsls
Method YearToDateSales() inline ::ytdsls
Method SalesHistory()
ENDCLASS
METHOD New( cCustNo ) CLASS TCustomer
::oTable:= TCustomers():New()
::oTable:setOrder(1)
::oTable:seek( cCustNo )
// ::Load()
::Super:New( ::oTable )
RETURN Self
METHOD End() Class TCustomer
::oTable:End()
Return nil
METHOD ApplyPayment( nAmount, dDate ) CLASS TCustomer
default dDate:= date()
::balance:= ::balance - nAmount
::lastPay:= dDate
::lpymt := nAmount
::save()
RETURN nil
Method GetBalance() Class TCustomer
Return ::balance
Method PaymentStatus() Class TCustomer
Return "Paid Up"
Method PaymentTerms() Class TCustomer
Return "Net "+alltrim(str(::PDays))+" days"
Method PastDueAmount() Class TCustomer
Return 0
Method SalesHistory() Class TCustomer
//Local oSalesHistory:= TSalesHistory():New(::custNo)
//oSalesHistory:Display()
//oSalesHistory:end()
Return nil
Method PastDueDays() Class TCustomer
Return 0
Method Display() Class TCustomer
Local cString:=""
cString := cString + "Customer No: "+ ::custno + CRLF
cString := cString + "Payment Status: "+ ::paymentStatus + CRLF
cString := cString + "Payment Terms: "+ ::paymentTerms() + CRLF
cString := cString + "Balance: " + TRANSFORM(::GetBalance(), "$999,999.99") + CRLF
cString := cString + "Year-To-Date Sales: " + transform(::yeartodateSales(), "$999,999.99") + CRLF
msgInfo(cString, ::Company)
Return nil
//---------------------------------------------------------------------------//
// Customer table class
Class TCustomers From TDataBase
Method New()
Method End() inline ::close()
Endclass
Method New() Class TCustomers
::super:new(,"arcust")
::use()
::setOrder(1)
::gotop()
Return self
// EOFMr Rao,
To better understand how to create a management with Tdatabase and Tdatarow it is possible to make a small program from A to Z, inserting the management of an archive even simple with the following possibilities: insertion, modification, search, printing also with the possibility to insert data from other archives for example through a selection
For us beginners it could be very useful
Mr. Silvio
What you are asking is totally different from what Mr. James Bott was discussing. (i.e., the subject of this post)
A Customer object is for ONE customer only. The question of adding customer, deleting customer, etc. does not arise.
For that, you need a class to handle Tables. That is what TData or TDatabase does.
These classes already have methods to append, modify, seek and all those.
Marcelo Via Giglio wrote:Hola,
maybe we can see to far and think in ORM https://en.wikipedia.org/wiki/Object-relational_mapping
an idea only
regards
Marcelo VÃa
Marcelo Via Giglio wrote:
maybe we can see to far and think in ORM https://en.wikipedia.org/wiki/Object-relational_mapping
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Cliente extends Model
{
  protected $fillable = [
    'agrupacion_id',
    'nombre',
    'apellido1',
    'apellido2',
    'cif',
    'tipo_persona',
    'tipo_via',
    'nombre_via',
    'num_via',
    'otros_via',
    'poblacion',
    'codigo_postal',
    'telefono1',
    'telefono2',
    'email',
    'fax',
  ];
 Â
  static function rules(){
    return [
      'nombre' => 'required|max:64',
      'apellido1' => 'max:45',
      'apellido2' => 'max:45',
      'cif' => 'required|cif_nif_nie',
      'tipo_persona' => 'required|in:F,J',
      'tipo_via' => 'required',
      'nombre_via' => 'required',
      'num_via' => 'required',
      'otros_via' => '',
      'poblacion' => '',
      'codigo_postal' => 'required',
      'email' => 'email|required|max:64',
      ];
  }
  public function bancos(){
    return $this->hasMany('App\Models\BancoCliente', 'cliente_id', 'id');
  }
  public function solicitudes(){
    return $this->hasMany('App\Models\Solicitud', 'cliente_id', 'id');
  }
  public function agrupacion(){
    return $this->belongsTo('App\Models\Agrupacion', 'id', 'agrupacion_id');
  }
  /**
  * List of values for field Tipo de Persona
  *
  * @return array
  */
  static public function tipo_personaSelectData(){
    return [
      'J' => 'JurÃdica',
      'F' => 'FÃsica',
    ];
  }
}Dear José Luis,
sorry, I don't have any close to ORM
Dear Carlos,
good explanation about ORM, but will be a best sample a Java ORM like Hibernate, EclipseLink, etc. where with a simple line of code, you can persist entire sophisticates relation entities.
I think [x]Harbour is flexible, maybe can be possible to develop a basic ORM
Many thanks for your comments
Regards and sorry for my good English
Marcelo VÃa
As far as I know there is an ORM for Harbour at https://github.com/tfonrouge/oordb
You can know more about Teo Fonrouge at https://medium.com/harbour-magazine/int ... 9a1a167f7b
Regards,
According to Wikipedia, object oriented programming is a type of ORM. So we have had this capability since the Clipper days.
After you have defined an entity object, you can create an object in one line.
oCustomer := TCustomer:New( cCustNo )
Using TDatabase you can switch from DBFs to SQL without changing any other code.
James Bott wrote:According to Wikipedia, object oriented programming is a type of ORM.
After you have defined an entity object, you can create an object in one line.
oCustomer := TCustomer:New( cCustNo )
Using TDatabase you can switch from DBFs to SQL without changing any other code.
METHOD Invoices()
RETURN ::hasMany( TInvoices() )José Luis Sánchez wrote:As far as I know there is an ORM for Harbour at https://github.com/tfonrouge/oordb
This topic looks very atractive.
I feel very enthusiastic about it, I would like to see more information in this forum about how to use this model with FWH and Harbour.
Thanks a lot for all this knowledge you freely shear with us, this is what I love of this forum. ![]()
Carlos Mora wrote:
OOP is NOT an ORM. They are absolutely different concepts. An ORM is able to hide the persistence layer of an implementation and expose entities abstracting their attributes and relations. OOP is a much wider concept, applied to everything.
From Wikipedia:
Object-relational mapping https://en.wikipedia.org/wiki/Object-relational_mapping
Object-relational mapping (ORM, O/RM, and O/R mapping tool) in computer science is a programming technique for converting data between incompatible type systems using object-oriented programming languages.