$dictionary['<module singular>']['fields']['example_c']['dependency'] = '';
$dictionary['<module singular>']['fields']['example_c']['required'] = false;
$dictionary['<module singular>']['fields']['example_c']['massupdate'] = '0';
$dictionary['<module singular>']['fields']['example_c']['default'] = '';
$dictionary['<module singular>']['fields']['example_c']['no_default'] = false;
$dictionary['<module singular>']['fields']['example_c']['comments'] = 'Example Varchar Vardef';


$dictionary['<module singular>']['fields']['example_c']['help'] = '';
$dictionary['<module singular>']['fields']['example_c']['importable'] = 'true';
$dictionary['<module singular>']['fields']['example_c']['duplicate_merge'] = 'disabled';
$dictionary['<module singular>']['fields']['example_c']['duplicate_merge_dom_value'] = '0';
$dictionary['<module singular>']['fields']['example_c']['audited'] = false;
$dictionary['<module singular>']['fields']['example_c']['reportable'] = true;


$dictionary['<module singular>']['fields']['example_c']['unified_search'] = false;
$dictionary['<module singular>']['fields']['example_c']['merge_filter'] = 'disabled';
$dictionary['<module singular>']['fields']['example_c']['calculated'] = false;
$dictionary['<module singular>']['fields']['example_c']['len'] = '255';
$dictionary['<module singular>']['fields']['example_c']['size'] = '20';
$dictionary['<module singular>']['fields']['example_c']['id'] = 'example_c';


$dictionary['<module singular>']['fields']['example_c']['custom_module'] = '';
//required to create the field in the _cstm table
$dictionary['<module singular>']['fields']['example_c']['source'] = 'custom_fields';
Once the vardef is in place, determine whether the custom field's module already contains any other custom fields. If there are not any existing custom fields, create a corresponding record in fields_meta_data that will trigger the comparison process.


INSERT INTO fields_meta_data (id, name, vname, comments, custom_module, type, len, required, deleted, audited, massupdate, duplicate_merge, reportable, importable) VALUES ('<module>example_c', 'example_c', 'LBL_EXAMPLE_C', 'Example Varchar Vardef', '<module>', 'varchar', 255, 0, 0, 0, 0, 0, 1, 'true');
Finally, navigate to Admin > Repair > Quick Repair and Rebuild. The system will then rebuild the extensions. After the repair, you will notice a section at the bottom stating that there are differences between the database and vardefs. Execute the scripts generated to create theSaveÂ custom field:
Missing <module>_cstm Table:
/*Checking Custom Fields for module : <module>*/


/*Checking Custom Fields for module : <module>*/
CREATE TABLE <module>_cstm (id_c char(36)  NOT NULL  , PRIMARY KEY (id_c)) CHARACTER SET utf8 COLLATE utf8_general_ci;
Missing Columns:
/*MISSING IN DATABASE - example_c -  ROW*/
ALTER TABLE <module>_cstm add COLUMN example_c varchar(255)  NULL ;
Â
  	Last modified: 2023-02-03 21:04:03


Specifying Custom Indexes for Import Duplicate Checking
Overview
When importing records to Sugar via the Import Wizard, users can select which of the mapped fields theyÂ would like to use to perform a duplicate checkÂ and thereby avoid creating duplicate records. This article explains how to enable an additional field or set of fields for selection in this step.
Resolution
The import wizard's duplicate check operates based on indices defined for that module. You can create a non-database index to check for a field. It is important that it is non-database as single column indices on your database can hamper overall performance. The following is an example to add the home phone field to the Contact module's duplicate check.
First, create the following file from the root directory of your Sugar installation on theÂ web server:
./custom/Extension/modules/Contacts/Ext/Vardefs/custom_import_index.php


When creating the file, keep in mind the following requirements:
The name of the file is not important, as long as it ends with a .php extension.
The rest of the directory path is case sensitive so be sure to create the directories as shown.
If you are creating the import index for a module other than Contacts, then substitute the corresponding directory name with that module.
Ensure that the entire directory path and file have the correct ownership and sufficient permissions for the web server to access the file.
The contents of the file should look similar to the following code:
<?php
$dictionary['Contact']['indices'][] = array(
     'name' => 'idx_home_phone_cstm',
     'type' => 'index',
     'fields' => array(
         0 => 'phone_home',
     ),
     'source' => 'non-db',
);


),
     'source' => 'non-db',
);
PleaseÂ note that the module name in line 2 of the code is singular (i.e. Contact, not Contacts). If you are unsure of what to enter for the module name, you can verify the name by opening the ./cache/modules/<module_name>/<module_name>vardefs.php file. The second line of that file will have text like the following:
$GLOBALS["dictionary"]["Contact"] = array (
The parameter following "dictionary" is the same parameter you should use in the file defining theÂ custom index. To verify duplicates against a combination of fields (i.e. duplicates will only be flagged if the values of multiple fields match those of an existing record), then simplyÂ add the desired fields to the 'fields' array in the code example.


Finally, navigateÂ to Admin > Repair > Quick Repair and Rebuild to enable the custom index for duplicate verification when importing records in theÂ module.
  	Last modified: 2023-02-03 21:04:03


Database
Overview
All Sugar products support the MySQL and Microsoft SQL Server databases. Sugar Enterprise and Sugar Ultimate also support the DB2 and Oracle databases. In general, Sugar uses only common database functionality, and the application logic is embedded in the PHP code. Sugar does not use or recommend database triggers or stored procedures. This design simplifies coding and testing across different database vendors. The only implementation difference across the various supported databases is column types.Â
Primary Keys, Foreign Keys, and GUIDs
By default, Sugar uses globally unique identification values (GUIDs) for primary keys for all database records. Sugar provides a Sugarcrm\Sugarcrm\Util\Uuid::uuid1() utility function for creating these GUIDs in the following format: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee. The primary key's column length is 36 characters.Â


The GUID format and value has no special meaning (relevance) in Sugar other than the ability to match records in the database. Sugar links two records (such as an Accounts record with a Contacts record) with a specified ID in the record type relationship table (e.g. accounts_contacts).
Primary keys in Sugar mayÂ contain any unique string such as a GUID algorithm, a key that has some meaning (e.g. bean type first, followed by info), an external key, or auto-incrementing numbers converted to strings. Sugar chose GUIDs over auto-incrementing keys to enable easier data synchronization across databases and avoid primary-key collisions.
You can also import data from a previous system with one primary key format and make all new records in Sugar use the GUID primary key format. All keys mustÂ be stored as globally unique strings with no more than 36 characters.


NoticeÂ If multiple records between modules contain matching ids, you may experience undesired behaviors within the system.
ToÂ implement a new primary key method or to import data with a different primary key format (based on the existing GUID mechanism for new records), keep in mindÂ the following rules of primary key behavior:
Quote characters : Sugar expects primary keys to be string types and will format the SQL with quotes. If you change the primary key types to an integer type, SQL errors may occur since Sugar stores all ID values in quotes in the generated SQL. The database may be able to ignore this issue. MySQL running in Safe mode experiences issues, for instance.


Case sensitivity : The ID values abc and ABC are treated the same in MySQL but represent different values in Oracle. When migrating data to Sugar, some CRM systems may use case-sensitive strings as their IDs on export. If this is the case, and you are running MySQL, you mustÂ run an algorithm on the data to make sure all of the IDs are unique. One simple algorithm is to MD5 the ID values that they provide. A quick check will let you know if there is a problem. If you imported 80,000 leads and there are only 60,000 in the system, some may have been lost due to non-unique primary keys caused by case insensitivity.


Key sizeÂ : Sugar only tracks the first 36 characters in the primary key. Any replacement primary key will either require changing all of the ID columns with one of an appropriate size or to make sure you do not run into any truncation or padding issues. MySQL in some versions has had issues with Sugar where the IDs were not matching because it was adding spaces to pad the row out to the full size. MySQL's handling of char and varchar padding has changed in laterÂ versions. To protect against this, make sure the GUIDs are not padded with blanks in the database by removing any leading or trailing space characters.
Indexes
Indexes can be defined in the main or custom vardefs.php for a module in an array under the key indices. See below for an example of defining several indices:
'indices' => array(
     array(
         'name' => 'idx_modulename_name',


array(
         'name' => 'idx_modulename_name',
         'type' => 'index',
         'fields' => array('name'),
     ),
     array(
         'name' => 'idx_modulename_assigned_deleted',
         'type' => 'index',
         'fields' => array('assigned_user_id', 'deleted'),
     ),
 ),
The name of the index must start with idx_ and must be unique across the database. Possible values for type include primary for a primary key or index for a normal index. The fields list matches the column names used in the database.
Doctrine


Doctrine
In order to provide robust support for Prepared Statements, which provide more security and better database access performance, Sugar 7.9 has adopted parts of Doctrine's Database Abstraction Layer, especially the QueryBuilder class, for working with prepared statements. The picture below shows how Sugar objects like DBManager and SugarQuery utilize Doctrine to provide this functionality, while still using the same toolset that has existed in Sugar.
Â
DBManager
The DBManager class will use Doctrine QueryBuilder for building INSERT and UPDATE queries.
SugarQuery
The SugarQuery class will use Doctrine QueryBuilder for building SELECT queries.
SugarBean
The SugarBean class will continue to use DBManager class for saving all fields.


The SugarBean class will continue to use DBManager class for saving all fields.
TopicsDBManagerThe DBManager Object provides an interface for working with the database.SugarQuerySugarQuery, located in ./include/SugarQuery/SugarQuery.php, provides an object-oriented approach to working with the database. This allows developers to generate the applicable SQL for a Sugar system without having to know which database backend the instance is using. SugarQuery supports all databases supported by Sugar.
  	Last modified: 2023-02-03 21:04:03


SugarQuery
Overview
SugarQuery, located in ./include/SugarQuery/SugarQuery.php, provides an object-oriented approachÂ to working with the database. This allows developers to generateÂ theÂ applicable SQL for a Sugar system without having to know which database backend the instance is using. SugarQuery supports all databases supported by Sugar.
Note: SugarQuery only supports reading data from the database at this time (i.e. SELECT statements).Â
Setup
To use SugarQuery, simply create a new SugarQuery object.
$sugarQuery = new SugarQuery();
Basic Usage


$sugarQuery = new SugarQuery();
Basic Usage
Using the SugarQuery objectÂ to retrieve records or generate SQL queries is very simple. At a minimum you need to set the ModuleÂ you are working with, using the from()Â method, however, there are helper methods for just about any operation you would need in a SQL query. The methods listed below will outline the major methodsÂ you should consider utilizing on the SugarQuery object in order to achieve your development goals.
from()
The from() method is used to set the primary module the SugarQuery object will be querying from. It is also used to set some crucial options for the query, such as whether Team Security should be used or if only non-deleted records should be queried. The following example will set the SugarQuery object to query from the Accounts module.
$sugarQuery->from(BeanFactory::newBean('Accounts'));


$sugarQuery->from(BeanFactory::newBean('Accounts'));
Arguments
Name
Type
Required
Description
$bean
SugarBean Object
true
The SugarBean object for aÂ specified module. The SugarBean object does not have to be a blank or new Bean as seen in the example above, but can be a previously instantiated SugarBean object.
$options
Array
false
An associative array that can specify anyÂ of the following options:
alias - string -Â The alias for the module table in the generated SQL query
team_security -Â boolean - Whether or not Team Security should be added to the generated SQLÂ queryÂ
add_deleted -Â boolean - Whether or not 'deleted' = 0 should be added to Where clause of generated SQL query
Returns
SugarQuery Object


Returns
SugarQuery Object
Allows for method chaining on the SugarQuery object.
select()
The example aboveÂ demonstrates the mostÂ basic example of retrieving records from a module. The select() method can be used on the SugarQuery object to specify the specific fields you wish to retrieve from the query.
//Alter the Selected Fields
$sugarQuery->select(array('id', 'name'));
Arguments
Name
Type
Required
Description
$fields
Array
false
Sets the fields that should be added to the SELECT portion of the SQL query
Returns
SugarQuery_Builder_Select Object


Returns
SugarQuery_Builder_Select Object
You cannot chain SugarQuery methods off of the select() method, however, you can use the returned Select object to modify the SELECT portion of the statement. Review theÂ SugarQuery_Builder_Select object in ./include/SugarQuery/Builder/Select.php for additional information on usage.
where()
To add a WHERE clause to the query, use the where() method to generate the Where object, and then use method chaining with the various helper methods to add conditions. To add aÂ WHERE clause for records with theÂ name field containingÂ the letter "I", you could addÂ the following code.Â
//add the where clause
$sugarQuery->where()->contains('name', 'I');
Arguments
None
Returns
SugarQuery_Builder_Where Object


Arguments
None
Returns
SugarQuery_Builder_Where Object
Allows for method chaining on the Where object as shown above.Â Review the SugarQuery Conditions documentation for aÂ full spectrum of where() method usage.
Relationships
join()
To add data from a related module to the SugarQuery, use the join() method. Adding to the same SugarQuery code example in this page, theÂ following code wouldÂ add the JOIN from Accounts module tables to Contacts table:
//add join
$sugarQuery->join('contacts');
Arguments
Name
Type
Required
Description
$link_name
String
true
The name of the relationship
$options
Array
false
Â
An associative array that can specify anyÂ of the following options:
alias - string -Â The alias for the module table in the generated SQL query


alias - string -Â The alias for the module table in the generated SQL query
relatedJoin -Â stringÂ - If joining to a secondary table (related to a related module), such as joining on Opportunities related to Contacts, when querying from Accounts, you can specify either the name of the relationship or the alias you specified for that relationship table.
Returns
SugarQuery_Builder_Join Object
Allows for method chaining on the SugarQuery_Builder_Join Object, to add additional conditions to the WHERE clause of the SQL condition.Â
joinTable()
If you were using the joinRaw() method in previous versions of Sugar, this is the replacement method which allows for joining to aÂ related table in SugarQuery. Adding to the same SugarQuery code example in this page, theÂ following code wouldÂ add the JOIN from Accounts module tables to theÂ accounts_contactsÂ table:


//add join
$sugarQuery->joinTable('accounts_contacts', array('alias' => 'ac'))->on()
    ->equalsField('accounts.id','ac.account_id')
    ->equals('ac.primary_account',1);
Arguments
Name
Type
Required
Description
$table_name
String
true
The name of the database table to join.Â
$options
Array
false
Â
An associative array that can specify anyÂ of the following options:
alias - string -Â The alias for the module table in the generated SQL query
Returns
SugarQuery_Builder_Join Object
Allows for method chaining on the SugarQuery_Builder_Join Object, to add additional conditions to the ONÂ clause using the on() method.Â
Altering Results


Altering Results
AlteringÂ the result set of a query can help the performance, as well as be crucial to finding the correct data. The following methods provide ways to limit the result set and change the order.
distinct()
To group the query on a field, you can use the corresponding distinct() method.
//add group by
$sugarQuery->distinct(true);
Arguments
Name
Type
Required
Description
$value
Boolean
true
Set whether or not the DISTINCT statement should be added to the query
Returns
Current SugarQuery Object
Allows for method chaining on the SugarQuery Object.
limit()
To limit the results of the query, you can use the limit() method.Â
//set the limit
$sugarQuery->limit(10);
Arguments
Name
Type
Required
Description
$number
Integer
true


Arguments
Name
Type
Required
Description
$number
Integer
true
The max amount of rows that should be returned by the query
Returns
Current SugarQuery Object
Allows for method chaining on the SugarQuery Object.
offset()
Adding a limit to the query limits the rows returned, however when doing so, you may need to alter the offset of the query to account for pagination or access other portions of the result set. To set an offset, you can use the offset() method.
//set the offset
$sugarQuery->offset(5);
Arguments
Name
Type
Required
Description
$number
Integer
true
TheÂ offset amount of rows, or starting point, of the result
Returns
Current SugarQuery Object
Allows for method chaining on the SugarQuery Object.
orderBy()


Allows for method chaining on the SugarQuery Object.
orderBy()
To orderÂ the query on a field, you can use the corresponding orderBy() method. This method can be called multiple times, to add multiple fields to the order by clauseÂ of the query.
//add group by
$sugarQuery->orderBy('account_type');
Arguments
Name
Type
Required
Description
$column
String
true
TheÂ field you want the query to be grouped on
$direction
String
false
Sets the direction of sorting. Must be 'ASC' or 'DESC'. The default is 'DESC'.
Returns
Current SugarQuery Object
Allows for method chaining on the SugarQuery Object.
Execution


Current SugarQuery Object
Allows for method chaining on the SugarQuery Object.
Execution
Once you have the SugarQuery object setup and configured for your statement, you will want to retrieve the results of the query, or simply get the generated query for the object. The following methods are used for executing the SugarQuery object.
execute()
To query the database for a result set, you will use the execute() method. The execute() method will retrieve the results and return them as a raw string, db object, json, or an array depending on the $type parameter. By default, results are returned as an array. An example of fetching records from an account is below:
//fetch the result
$result = $sugarQuery->execute();
The execute() function will return an array of results that you can iterate through as shown below:
Array
(
    [0] => Array
    (


Array
(
    [0] => Array
    (
        [id] => f39593da-3f88-3059-4f18-524b4d23d07b
        [name] => International Art Inc
    )
)
Note:Â An empty resultset will return an empty array.
Arguments
Name
Type
Required
Description
$type
String
false
How you want the results of the Query returned. Can be one of the following options:
dbÂ - Returns the result directly from the DatabaseManager resource
arrayÂ -Â DefaultÂ - Returns the results as a formatted array
json - Returns the results encoded as JSON
Returns
Default:Â Array.Â See above argument details for details on other Return options.
compile()


compile()
If you want to log the query being generated or want to output the query without running it during development, the compile() method is what should be used retrieve the Prepared Statement. You can then retrieve the Prepared Statement Object to retrieve the Parameterized SQL and the Parameters. For further information on Prepared Statement usage, see our Database documentation.
//get the compiled prepared statement
$preparedStmt = $sugarQuery->compile();
//Retrieve the Parameterized SQL
$sql = $preparedStmt->getSQL();
//Retrieve the parameters as an array
$parameters = $preparedStmt->getParameters();
Arguments
No arguments
Returns
Object
The compiled SQL Query built by the SugarQuery object.


No arguments
Returns
Object
The compiled SQL Query built by the SugarQuery object.
TopicsSugarQuery ConditionsLearn about the various methods that can be utilized with SugarQuery to add conditional statements to a query.Advanced TechniquesLearn about some of the advanced methods that SugarQuery has to offer, that are not as commonly used.
  	Last modified: 2023-02-03 21:04:03


SugarQuery Conditions
Overview
Learn about the various methods that can be utilized with SugarQuery to add conditional statements to a query.Â
Where Clause
Manipulating, the WHERE clause of a SugarQuery object is crucial for getting the correct results. To create a WHERE clause on the query, use the where() method on the SugarQuery object, as outlined in the SugarQuery documentation. Once you have the Where object, you can utilize the following methods on the Where object to add conditional statements.
equals() | notEquals()
Used to equate a field to a given value. Wildcards will not work with this function, as it is looking for an exact match.
//add equals
$SugarQuery->where()->equals('name','Test');
//add Not Equals
$SugarQuery->where()->notEquals('name','Tester');
Arguments
Name
Type
Required
Description
$field


Arguments
Name
Type
Required
Description
$field
String
true
TheÂ field you are checking againstÂ
$value
String
true
The value the field should be equal to
Returns
SugarQuery_Builder_Where Object
Allows for method chaining on the Where object to add additional conditions.
equalsField() | notEqualsField()
Used to equate a field to another field in the result set.
//add an Equals Field statement
$SugarQuery->where()->equalsField('industry','account_type');
//add a Not Equals Field statement
$SugarQuery->where()->notEqualsField('name','account_type');
Arguments
Name
Type
Required
Description
$field
String
true
TheÂ field you are checking againstÂ
$field
String
true


true
TheÂ field you are checking againstÂ
$field
String
true
The other field you want the first field to be equal to
Returns
SugarQuery_Builder_Where Object
Allows for method chaining on the Where object to add additional conditions.Â
isEmpty() | isNotEmpty()
Used to check if a field is or isn't empty.
//add an isEmpty statement
$SugarQuery->where()->isEmpty('industry');
//add an isNotEmpty statement
$SugarQuery->where()->isNotEmpty('name');
Arguments
Name
Type
Required
Description
$field
String
true
TheÂ field you are checking againstÂ
Returns
SugarQuery_Builder_Where Object
Allows for method chaining on the Where object to add additional conditions.Â
isNull() | notNull()


isNull() | notNull()
Used to check if a field is or isn't equal to NULL.
//add an isNull statement
$SugarQuery->where()->isNull('industry');

//add a notNull statement
$SugarQuery->where()->notNull('name');
Arguments
Name
Type
Required
Description
$field
String
true
TheÂ field you are checking againstÂ
Returns
SugarQuery_Builder_Where Object
Allows for method chaining on the Where object to add additional conditions.Â
contains() | notContains()
Used to check if a field has or doesn't have a specified string in its value. Utilizes the LIKE statement, and wildcards on both sides of the provided string.
//add an isNull statement
$SugarQuery->where()->contains('name','Test');


$SugarQuery->where()->contains('name','Test');
//add a notNull statement
$SugarQuery->where()->notContains('industry','Test');
Arguments
Name
Type
Required
Description
$field
String
true
TheÂ field you are checking againstÂ
$value
String
true
The stringÂ being searched for in the value of the field
Returns
SugarQuery_Builder_Where Object
Allows for method chaining on the WhereÂ Object to add additional conditions.Â
starts() | ends()


starts() | ends()
Similar to the above contains() method, theseÂ methods use the LIKE statement in the SQL query and wildcards for searching for a specified string in the field's value. However,Â the starts() and ends() methods only wildcard the right side and the left side, respectively. The following example demonstrates searching for records where the Name field starts with A, and ends with E.
//add an starts and ends statement
$SugarQuery->where()->starts('name','A')->ends('name','e');
Arguments
Name
Type
Required
Description
$field
String
true
TheÂ field you are checking againstÂ
$value
String
true
The stringÂ being searched for in the value of the field
Returns
SugarQuery_Builder_Where Object
Allows for method chaining on the Where object to add additional conditions.Â


Allows for method chaining on the Where object to add additional conditions.Â
in() | notIn()
Used to check if a field's value is or isn't one of a set of specified values. The following examples lookÂ for records where the industry fieldÂ is in a list of values, and not in a separate list of values.
$values = array(
    'Support',
    'Sales',
    'Engineering'
);
//add in statement
$SugarQuery->where()->in('industry',$values);
$values = array(
    'Marketing',
    'Accounting'
);
//add NotIn Statement
$SugarQuery->where()->notIn('industry',$values);
Arguments
Name
Type
Required
Description
$field
String
true
TheÂ field you are checkingÂ
$values
Array
true


true
TheÂ field you are checkingÂ
$values
Array
true
The array of values which the field is being checked against
Returns
SugarQuery_Builder_Where Object
Allows for method chaining on the Where object to add additional conditions.Â
between()
Used primarily for numeric type fields, to check if the value is greater than the minimum number specifiedÂ and less than the maximum number specified. The following code would check for records where the employees field is between 50 and 1000.
//add Between statement
$SugarQuery->where()->between('employees',50,1000);
Arguments
Name
Type
Required
Description
$field
String
true
TheÂ field you are checking againstÂ
$min
Number
true
The lowest number the field's value should be
$max
Number
true
The highest number the field's value should be
Returns


$max
Number
true
The highest number the field's value should be
Returns
SugarQuery_Builder_Where Object
Allows for method chaining on the Where object to add additional conditions.Â
lt() | lte() | gt() | gte()
These methodsÂ are primarily for numeric fields, to check if a field's value is less than (<), less than or equal (<=), greater than (>), or greater than or equal (>=) to a specified value.
//Add Less Than Statement
$SugarQuery->where()->lt('gross_revenue',1000000);
//Add Less Than or Equal to Statement
$SugarQuery->where()->lte('net_revenue','500000');
//Add Greater Than Statement
$SugarQuery->where()->gt('gross_revenue',500000);
//Add Greater Than or Equal to Statement


//Add Greater Than or Equal to Statement
$SugarQuery->where()->gte('net_revenue',100000);
Arguments
Name
Type
Required
Description
$field
String
true
TheÂ field you are checking againstÂ
$value
Number
true
The numeric value for comparisonÂ
Returns
SugarQuery_Builder_Where Object
Allows for method chaining on the Where object to add additional conditions.Â
dateRange()
Used to check if a field's value is betweenÂ a preset date range from the current time. See the TimeDate documentation on the available date range keys.
//add DateRange statement
$SugarQuery->where()->dateRange('date_modified','last_30_days');
Arguments
Name
Type
Required
Description
$field
String
true
TheÂ field you are checking againstÂ
$value


String
true
TheÂ field you are checking againstÂ
$value
String
true
The stringÂ specifying the date range key that will be used for comparison. ExampleÂ 'next_7_days'
Returns
SugarQuery_Builder_Where Object
Allows for method chaining on the Where object to add additional conditions.Â
dateBetween()
To group the query on a field, you can use the corresponding groupBy() method. This method can be called multiple times, to add multiple fields to the grouping of the query.
//add group by
$SugarQuery->where()->dateBetween('date_created',array('2016-01-01','2016-03-01'));
Arguments
Name
Type
Required
Description
$field
String
true
TheÂ field you are checking againstÂ
$value
Array
true


true
TheÂ field you are checking againstÂ
$value
Array
true
An array containing the minimum date in the first key, and the maximum date in the second.
Returns
SugarQuery_Builder_Where Object
Allows for method chaining on the WhereÂ Object to add additional conditions.Â
Combinations
Now that you have reviewed all of the available conditional statements for SugarQuery, you may want to combine them using AND and OR all within the same query. By default when the where() method is called, chained conditional methods will be added with AND to the where clause. You can specify an OR where clause on the main SugarQuery object by using the orWhere() method, which works the same as the where() method, just adds conditional statements with OR instead. The following methods allow for adding internal AND and OR logic to conditional statements on the Where object.
queryAnd()


queryAnd()
To start a group of conditional statements that should allÂ evaluate to True, use the queryAnd() method.Â For example, if you want to query for Accounts, where the name contains 'Test' AND description contains 'Test', you might use the following code:
$SugarQuery = new SugarQuery();
$SugarQuery->select(array('name'));
$SugarQuery->from(BeanFactory::newBean('Accounts'));
//Using queryAnd
$SugarQuery->where()->queryAnd()->contains('name','Test')->contains('description','Test');
The above use of queryAnd() method isn't entirely needed, as the main Where object would be using AND for all conditions anyway, but it does group the two conditions inside of their own parenthesis in the compiled query, as shown below, to demonstrate how it can be used for altering query logic.


SELECT  accounts.name name FROM accounts WHERE accounts.deleted = 0 AND (accounts.name LIKE '%Test%' AND accounts.description LIKE '%Test%')
queryOr()
To start a group of conditional statements that should evaluate to true, if any condition is true, you can use the queryOr() method. For example, if you want to query for Accounts, where the name contains 'Test' or where the description contains 'Test', you might use the following code:
$SugarQuery = new SugarQuery();
$SugarQuery->select(array('name'));
$SugarQuery->from(BeanFactory::newBean('Accounts'));
//Using queryOr
$SugarQuery->where()->queryOr()->contains('name','Test')->contains('description','Test');


This will group the two conditions inside of their own parenthesis in the compiled query.Â If eitherÂ of the conditions isÂ True, it will return a record. An example is shown below.
SELECT  accounts.name name FROM accounts WHERE accounts.deleted = 0 AND (accounts.name LIKE '%Test%' OR accounts.description LIKE '%Test%')
  	Last modified: 2023-02-03 21:04:03


Advanced Techniques
Overview
Learn about some of the advanced methods that SugarQuery has to offer, that are not as commonly used.
Get First Record
Getting the first record in a result set, can be accomplished by using the limit() method. The getOne() method is similar in that it gets the first record, but it also returns the first piece of data for that record.Â
getOne()
Get the first piece of data on the first record returned by the generated query. In this example, we want the 'name' from the Account with a given ID.
$SugarQuery = new SugarQuery();
$SugarQuery->select(array('name'));
$SugarQuery->from(BeanFactory::newBean('Accounts'));
$SugarQuery->where()->equals('id',$id);
//Get the Name of the account
$accountName = $SugarQuery->getOne();


$accountName = $SugarQuery->getOne();
Aggregates
setCountQuery()
Currently, the only method available for creating an aggregate column, is the setCountQuery() method on the SugarQuery_Builder_Select Object. You can add this method to your select() method chain, to add count(0) as record_count to the SQL SELECT statement.
$SugarQuery = new SugarQuery();
$SugarQuery->select(array('name'))->setCountQuery();
$SugarQuery->from(BeanFactory::newBean('Accounts'));
$SugarQuery->groupByRaw('accounts.name');
The above example will output the following prepared statement when using compile():
SELECT accounts.name, COUNT(0) AS record_count FROM accounts WHERE accounts.deleted = ? GROUP BY accounts.name, accounts.name
Parameters
array (


Parameters
array (
    [1] => 0
)
Arguments
No arguments
Returns
SugarQuery_Builder_Select Object
Allows for method chaining on the SelectÂ Object.
Joins
Joining to tables and joining via SugarBean relationships is outlined in the SugarQuery documentation, however the SugarQuery_Builder_Join Object has a few helpful methods not mentioned there.
joinName()
If you are not using a custom alias for the relationship or table, you may want to retrieve the generated name used by SugarQuery to add a conditions or join to.
$SugarQuery = new SugarQuery();
$SugarQuery->from(BeanFactory::getBean('Accounts'));
$contacts = $SugarQuery->join('contacts')->joinName();
$SugarQuery->select(array("$contacts.full_name"));


$SugarQuery->select(array("$contacts.full_name"));
$SugarQuery->where()->equals('industry', 'Media');
The above example will output the following prepared statement when using compile():


The above example will output the following prepared statement when using compile():
SELECT jt0_contacts.salutation rel_full_name_salutation, jt0_contacts.first_name rel_full_name_first_name, jt0_contacts.last_name rel_full_name_last_name FROM accounts INNER JOIN accounts_contacts jt1_accounts_contacts ON (accounts.id = jt1_accounts_contacts.account_id) AND (jt1_accounts_contacts.deleted = ?) INNER JOIN contacts jt0_contacts ON (jt0_contacts.id = jt1_accounts_contacts.contact_id) AND (jt0_contacts.deleted = ?) WHERE (accounts.industry = ?) AND (accounts.deleted = ?)
Parameters:


Parameters:
array (
    [1] => 0
    [2] => 0
    [3] => Media
    [4] => 0
)
Â
Arguments
No arguments
Returns
string
The name used in Query to identify the joined table
Unions
Unions allow joining multiple queries with the same selected fields to be combined during output. You can use Unions in SugarQuery by using the union() method.
union()
To add a union, you can use the corresponding union() method. The example below will join two SQL queries:
//Fetch the bean of the module to query
$bean = BeanFactory::newBean('Accounts');
//Specify fields to fetch
$fields = array(
    'id',
    'name'
);
//Create first query
$sq1 = new SugarQuery();
$sq1->select($fields);


$sq1 = new SugarQuery();
$sq1->select($fields);
$sq1->from($bean, array('team_security' => false));
$sq1->Where()->in('account_type', array('Customer'));
//Create second query
$sq2 = new SugarQuery();
$sq2->select($fields);
$sq2->from($bean, array('team_security' => false));
$sq2->Where()->in('account_type', array('Investor'));
//Create union
$sqUnion = new SugarQuery();
$sqUnion->union($sq1);
$sqUnion->union($sq2);
$sqUnion->limit(5);
The above example will output the following prepared statement when using compile():


The above example will output the following prepared statement when using compile():
SELECT accounts.id, accounts.name FROM accounts WHERE (accounts.account_type IN (?)) AND (accounts.deleted = ?) UNION ALL SELECT accounts.id, accounts.name FROM accounts WHERE (accounts.account_type IN (?)) AND (accounts.deleted = ?) LIMIT 5
Parameters:
array (
    [1] => Customer
    [2] => 0
    [3] => Investor
    [4] => 0
)
Arguments
Name
Type
Required
Description
$selectÂ
SugarQuery
true
The SugarQuery Object you wish to add to the UNION query
$all
Boolean
false
Whether to use UNION ALL or just UNION in the query. The default value is TRUE.
Returns
SugarQuery_Builder_Union Object


Returns
SugarQuery_Builder_Union Object
Allows for method chaining on the UnionÂ Object.
Having
When using aggregates in a query, you might want to filter out values based on a condition. SugarQuery provides the having() method for adding HAVING clause to the query.
having()
To use the having() method, you have to build a SugarQuery_Builder_Condition Object and set the field, operator, and value that condition is based on.
$SugarQuery = new SugarQuery();
$SugarQuery->from(BeanFactory::getBean('Accounts'));
$SugarQuery->join('contacts', array('alias' => 'industryContacts'));
$SugarQuery->join('opportunities', array('relatedJoin' => 'industryContacts', 'alias' => 'contactsOpportunities'));


$SugarQuery->select()->setCountQuery();
$SugarQuery->where()->equals('contactsOpportunities.sales_stage', 'closed');
$havingCondition = new SugarQuery_Builder_Condition($SugarQuery);
$havingCondition->setField('contactsOpportunities.amount')->setOperator('>')->setValues('1000');
$SugarQuery->having($havingCondition);
The above example will output the following prepared statement when using compile():


SELECT COUNT(0) AS record_count FROM accounts INNER JOIN accounts_contacts jt0_accounts_contacts ON (accounts.id = jt0_accounts_contacts.account_id) AND (jt0_accounts_contacts.deleted = ?) INNER JOIN contacts industryContacts ON (industryContacts.id = jt0_accounts_contacts.contact_id) AND (industryContacts.deleted = ?) INNER JOIN opportunities_contacts jt1_opportunities_contacts ON jt1_opportunities_contacts.deleted = ? INNER JOIN opportunities contactsOpportunities ON (contactsOpportunities.id = jt1_opportunities_contacts.opportunity_id) AND (contactsOpportunities.deleted = ?) WHERE


AND (contactsOpportunities.deleted = ?) WHERE (contactsOpportunities.sales_stage = ?) AND (accounts.deleted = ?) HAVING contactsOpportunities.amount > ?


Parameters:
array (
    [1] => 0
    [2] => 0
    [3] => 0
    [4] => 0
    [5] => closed
    [6] => 0
    [7] => 1000
)
Arguments
Name
Type
Required
Description
$conditionÂ
SugarQuery_Builder_Condition
true
The conditional object used to generate the HAVING clause
Returns
SugarQuery_Builder_Having Object
Allows for method chaining on the HavingÂ Object to add additional conditions.
Raw Methods
The SugarQuery Object has a few helper methods that allow raw SQL statement parts to be passed into. This allows for more complex statements or edge case scenarios where a helper function may not have met the requirements for the query.Â
whereRaw()


whereRaw()
To add to the WHERE clause of SugarQuery Object with raw SQL syntax, you can utilize the whereRaw() method. This method will append the specified statement, to the WHERE clause using an AND operator, and will wrap the entire statement in parenthesis. The following is an example use with the output:
$SugarQuery = new SugarQuery();
$SugarQuery->select(array('name'));
$SugarQuery->from(BeanFactory::newBean('Accounts'));
$SugarQuery->whereRaw("name LIKE '%T%'");
The above example will output the following prepared statement when using compile():
SELECT accounts.name FROM accounts WHERE (name LIKE '%T%') AND (accounts.deleted = ?)
Parameters:
array (
    [1] => 0
)
Arguments
Name
Type
Required
Description
$sql
String
true


)
Arguments
Name
Type
Required
Description
$sql
String
true
TheÂ WHERE clause SQLÂ to be appended to the where clause on the SugarQuery object. All conditions passed in are wrapped in parenthesis and appended using AND (if other conditions exist on where clause).
Returns
SugarQuery_Builder_Where Object
Allows for method chaining on the Where object.
groupByRaw()
To add multiple fields to the GROUP BY statement on the SugarQuery Object, it may be easiest to use the groupByRaw() method.
$SugarQuery = new SugarQuery();
$SugarQuery->select(array('account_type', 'industry'));
$SugarQuery->from(BeanFactory::newBean('Accounts'));
$SugarQuery->groupByRaw("accounts.account_type,accounts.industry");


The above example will output the following prepared statement when using compile():
SELECT accounts.account_type, accounts.industry FROM accounts WHERE accounts.deleted = ? GROUP BY accounts.account_type,accounts.industry
Parameters:
array (
    [1] => 0
)
Arguments
Name
Type
Required
Description
$sql
String
true
The GROUP BY statement, without the GROUP BY keyword.Â
Returns
SugarQuery Object
Allows for method chaining on the SugarQuery Object.
orderByRaw()
Using the oderBy() method only allows for adding a single field to the SugarQuery object at a time. In some cases, you might consider using the orderByRaw() method to add multiple fields or the entire ORDER BY statement to the SugarQuery object.Â
$SugarQuery = new SugarQuery();
$SugarQuery->select(array('name'));


$SugarQuery->select(array('name'));
$SugarQuery->from(BeanFactory::newBean('Accounts'));
$SugarQuery->orderByRaw("accounts.name DESC, accounts.date_modified");
The above example will output the following prepared statement when using compile():
SELECT accounts.name FROM accounts WHERE accounts.deleted = ? ORDER BY accounts.name DESC, accounts.date_modified DESC, accounts.id DESC
Parameters:
array (
    [1] => 0
)
Arguments
Name
Type
Required
Description
$sql
String
true
The ORDER BY statement, without the ORDER BY keyword.
Returns
SugarQuery Object
Allows for method chaining on the SugarQuery Object.
havingRaw()
Using the havingRaw() method allows for adding a having statementÂ to the SugarQuery object.Â


$SugarQuery = new SugarQuery();
$SugarQuery->from(BeanFactory::getBean('Accounts'));
$SugarQuery->join('contacts', array('alias' => 'industryContacts'));
$SugarQuery->join('opportunities', array('relatedJoin' => 'industryContacts', 'alias' => 'contactsOpportunities'));
$SugarQuery->select()->setCountQuery();
$SugarQuery->where()->equals('contactsOpportunities.sales_stage', 'closed');
$SugarQuery->havingRaw("contactsOpportunities.amount > 1000");
The above example will output the following prepared statement when using compile():


AND (contactsOpportunities.deleted = ?) WHERE (contactsOpportunities.sales_stage = ?) AND (accounts.deleted = ?) HAVING contactsOpportunities.amount > 1000


Parameters:
array (
    [1] => 0
    [2] => 0
    [3] => 0
    [4] => 0
    [5] => closed
    [6] => 0
)
Arguments
Name
Type
Required
Description
$sql
String
true
The HAVINGÂ statement, without the HAVINGÂ keyword.
Returns
SugarQuery Object
Allows for method chaining on the SugarQuery Object.Â
  	Last modified: 2023-02-03 21:04:03


DBManager
Overview
The DBManager Object provides an interface for working with the database.
Instantiating the DBManager Object
The DBManagerFactory class, located in ./include/database/DBManagerFactory.php,Â can help instantiate a DBManager object using the getInstance() method.
$db = \DBManagerFactory::getInstance();
For best practices, we recommend using the global DBManager Object:
$GLOBALS['db']
Querying The Database
Sugar supports prepared statements. The following sections outline the legacy usage and the newly prepared statement usage.
SELECT queries
For select queries that do not have a dynamic portion of the where clause, you can use the query()Â method on the DBManager object. For queries that are accepting data passed into the system in the where clause, the following examples demonstrate how best utilize the new Prepared Statement functionality.
Legacy:


Legacy:
$id = '1234-abcde-fgh45-6789';
$query = 'SELECT * FROM accounts WHERE id = ' . $GLOBALS['db']->quoted($id);
$results = $GLOBALS['db']->query($query);
Best Practice:
Use the getConnection() method to retrieve a Doctrine Connection Object which handles prepared statements.
$id = '1234-abcde-fgh45-6789';
$query = 'SELECT * FROM accounts WHERE id = ?';
$conn = $GLOBALS['db']->getConnection();
$result = $conn->executeQuery($query, [$id]);
In the case that query logic is variable or conditionally built then it makes sense to use Doctrine QueryBuilder directly.
Legacy:
$query = 'SELECT * FROM accounts';
if ($status !== null) {


$query = 'SELECT * FROM accounts';
if ($status !== null) {
	$query .= ' WHERE status = ' . $GLOBALS['db']->quoted($status);
}
$results = $GLOBALS['db']->query($query);
Best Practice:
Use the getConnection() method to retrieve the Doctrine Connection Object, and then use the createQueryBuilder() method on the Connection Object to retrieve the QueryBuilder Object.
$builder = $GLOBALS['db']->getConnection()->createQueryBuilder();
$builder->select('*')->from('accounts');
if ($status !== null) {
	$builder->where('status = ' . $builder->createPositionalParameter($status));
}
$result = $builder->executeQuery();
Retrieving Results
Legacy:


}
$result = $builder->executeQuery();
Retrieving Results
Legacy:
After using theÂ query()Â method, such as in the Legacy code examples above, you can use theÂ fetchByAssoc() method to retrieve results. The query() method will submit the query and retrieve the results while the fetchByAssoc() method will iterate through the results:
$sql = "SELECT id FROM accounts WHERE deleted = 0";
$result = $GLOBALS['db']->query($sql);
while($row = $GLOBALS['db']->fetchByAssoc($result) )
{
    //Use $row['id'] to grab the id fields value
    $id = $row['id'];
}
Best Practice:


$id = $row['id'];
}
Best Practice:
When using Prepared Statements, both the Doctrine Query Builder and the Doctrine Connection Object will return a Doctrine\DBAL\Result Object to allow iterating through the results of the query. You can use the fetchNumeric()Â ,Â fetchAssociative() or fetchAllNumeric()Â or fetchAllAssociative() methods to retrieve results.
fetchAllAssociative() Example
The fetchAllAssociative() method will return the entire result set as an associative array, with each index containing a row of data.
$conn = $GLOBALS['db']->getConnection();
$result = $conn->executeQuery("SELECT * FROM accounts");
foreach ($result->iterateAssociative() as $row) {
    $name = $row['name'];
    // do something
}


$name = $row['name'];
    // do something
}
iterateAssociativeIndexed() Example
The iterateAssociativeIndexed() method executes the query and iterate over the result with the key representing the first column and the value is an associative array of the rest of the columns and their values:
$query = 'SELECT id, name FROM accounts';
$conn = $GLOBALS['db']->getConnection();
foreach ($conn->iterateAssociativeIndexed($query) as $id => $data) {
    // ...
}
Retrieving a Single Result
To retrieve a single result from the database, such as a specific record field, you can use the getOne() method for Legacy query usage.
$sql = "SELECT name FROM accounts WHERE id = :id";
$conn = $GLOBALS['db']->getConnection();


$conn = $GLOBALS['db']->getConnection();
$row = $conn->fetchAssociative($sql, ['id' => $id]);
// alternative
$sql = "SELECT name FROM accounts WHERE id = '{$id}'";
$name = $GLOBALS['db']->getOne($sql);
Limiting Results
To limit the results of a query, you can add a limit to the SQL string or for legacy query usage you can use the limitQuery() method on the DBManager Object:
Legacy:
$sql = "SELECT id FROM accounts WHERE deleted = 0";
$offset = 0;
$limit = 1;
$result = $GLOBALS['db']->limitQuery($sql, $offset, $limit);
while($row = $GLOBALS['db']->fetchByAssoc($result) )
{


{
    //Use $row['id'] to grab the id fields value
    $id = $row['id'];
}
Prepared Statements:
When using the Doctrine Query Builder, you can limit the results of the query by using theÂ setMaxResults() method.
$builder = $GLOBALS['db']->getConnection()->createQueryBuilder();
$builder->select('*')->from('accounts');
if ($status !== null) {
	$builder->where('status = ' . $builder->createPositionalParameter($status));
}
$builder->setMaxResults(2);
$result = $builder->executeQuery();
INSERT queries
INSERT queriesÂ can be easily performed using DBManager class.
Legacy:
$query = 'INSERT INTO table (foo, bar) VALUES ("foo", "bar")';


$GLOBALS['db']->query($query);
Best Practice:
$fieldDefs = $GLOBALS['dictionary']['table']['fields'];
$GLOBALS['db']->insertParams('table', $fieldDefs, ['foo' => 'foo','bar' => 'bar']);
UPDATE queries
When updating records with known IDs or a set of records with simple filtering criteria, then DBManager can be used:
Legacy:
$query = 'UPDATE table SET foo = "bar" WHERE id = ' . $GLOBALS['db']->quoted($id);
$GLOBALS['db']->query($query);
Best Practice:
$fieldDefs = $GLOBALS['dictionary']['table']['fields'];


$GLOBALS['db']->updateParams('table', $fieldDefs, ['foo' => 'bar',], ['id' => $id]);
For more complex criteriaÂ or when column values contain expressions or references to other fields in the table then Doctrine QueryBuilder can be used.
Legacy:
$query = 'UPDATE table SET foo = "bar" WHERE foo = "foo" OR foo IS NULL';
$GLOBALS['db']->query($query);
Best Practice:
$query = 'UPDATE table SET foo = ? WHERE foo = ? OR foo IS NULL';
$conn = $GLOBALS['db']->getConnection();
$rowCount = $conn->executeStatement($query, ['bar', 'foo']);
Generating SQL Queries from SugarBean
To have Sugar automatically generate SQL queries, you can use the followingÂ methods from the bean class.


Select Queries
To create a select query you can use the create_new_list_query() method:
$bean = BeanFactory::newBean($module);
$order_by = '';
$where = '';
$fields = array(
    'id',
    'name',
);
$sql = $bean->create_new_list_query($order_by, $where, $fields);
Count Queries
You can also run the generated SQL through the create_list_count_query() method to generate a count query:
$bean = BeanFactory::newBean('Accounts');
$sql = "SELECT * FROM accounts WHERE deleted = 0";
$count_sql = $bean->create_list_count_query($sql);
  	Last modified: 2023-02-03 21:04:03


Subpanels
Overview
For Sidecar, Sugar's subpanel layouts have been modified to work as simplified metadata.Â This page is anÂ overview of the metadata framework for subpanels.Â
The reason for this change is that previous versions of Sugar generated the metadata from various sources such as the SubPanelLayout and MetaDataManager classes. This eliminates the need for generating and processing the layouts and allows the metadata to be easily loaded to Sidecar.
Note:Â Modules running in backward compatibility mode do not use the Sidecar subpanel layouts as they use the legacy MVC framework.
Hierarchy Diagram
When loading the Sidecar subpanel layouts, the system processes the layout in the following manner:
Note: The Sugar application's client type is "base". For more information on the various client types, please refer toÂ the User Interface page.
Subpanels and Subpanel Layouts


Subpanels and Subpanel Layouts
Sugar contains both a subpanels (plural) layout and a subpanel (singular) layout. The subpanels layout contains the collection of subpanels,Â whereasÂ the subpanel layout renders the actual subpanel widget.
An example of a stock module's subpanels layout is:
./modules/Bugs/clients/base/layouts/subpanels/subpanels.php
<?php
$viewdefs['Bugs']['base']['layout']['subpanels'] = array (
  'components' => array (
      array (
          'layout' => 'subpanel',
          'label' => 'LBL_DOCUMENTS_SUBPANEL_TITLE',
          'context' => array (
              'link' => 'documents',
          ),
      ),


'link' => 'documents',
          ),
      ),
      array (
          'layout' => 'subpanel',
          'label' => 'LBL_CONTACTS_SUBPANEL_TITLE',
          'context' => array (
              'link' => 'contacts',
          ),
      ),
      array (
          'layout' => 'subpanel',
          'label' => 'LBL_ACCOUNTS_SUBPANEL_TITLE',
          'context' => array (
              'link' => 'accounts',
          ),
      ),
      array (
          'layout' => 'subpanel',
          'label' => 'LBL_CASES_SUBPANEL_TITLE',
          'context' => array (
              'link' => 'cases',
          ),
      ),


'link' => 'cases',
          ),
      ),
  ),
  'type' => 'subpanels',
  'span' => 12,
);
You can see that the layout incorporates the use of the subpanel layout for each module. As most of the subpanel data is similar, this approach allows us to use less duplicate code. The subpanel layout, shown below, shows the three views that make up the subpanel widgets users see.
./clients/base/layouts/subpanel/subpanel.php
<?php
$viewdefs['base']['layout']['subpanel']  = array (
    'components' => array (
        array (
            'view' => 'panel-top',
        )
        array (
            'view' => 'subpanel-list',
        ),
        array (


'view' => 'subpanel-list',
        ),
        array (
            'view' => 'list-bottom',
        ),
    ),
    'span' => 12,
    'last_state' => array(
        'id' => 'subpanel'
    ),
);
Adding Subpanel Layouts
When a new relationship is deployed from Studio, the relationship creation process will generate the layouts using the extension framework. You should note that for stock relationships and custom deployed relationships, layouts are generated for both Sidecar and Legacy MVC Subpanel formats. This is done to ensure that any related modules, whether in Sidecar or Backward Compatibility mode, display a related subpanel as expected.
Sidecar Layouts


Sidecar Layouts
Custom Sidecar layouts, located in ./custom/Extension/modules/<module>/Ext/clients/<client>/layouts/subpanels/, are compiled into ./custom/modules/<module>/Ext/clients/<client>/layouts/subpanels/subpanels.ext.php using the extension framework. When a relationship is saved, layout files are created for both the "base" and "mobile" client types.
For example, deploying a 1:M relationship from Bugs to Leads will generate the following Sidecar files:
./custom/Extension/modules/Bugs/Ext/clients/base/layouts/subpanels/bugs_leads_1_Bugs.php
<?php
$viewdefs['Bugs']['base']['layout']['subpanels']['components'][] = array (


'layout' => 'subpanel',
  'label' => 'LBL_BUGS_LEADS_1_FROM_LEADS_TITLE',
  'context' =>
  array (
    'link' => 'bugs_leads_1',
  ),
);
./custom/Extension/modules/Bugs/Ext/clients/mobile/layouts/subpanels/bugs_leads_1_Bugs.php
<?php
$viewdefs['Bugs']['mobile']['layout']['subpanels']['components'][] = array (
  'layout' => 'subpanel',
  'label' => 'LBL_BUGS_LEADS_1_FROM_LEADS_TITLE',
  'context' =>
  array (
    'link' => 'bugs_leads_1',


array (
    'link' => 'bugs_leads_1',
  ),
);
Note: The additional legacy MVC layouts generated by a relationships deployment are described below.
Legacy MVC Subpanel Layouts
Custom Legacy MVC Subpanel layouts, located in ./custom/Extension/modules/<module>/Ext/Layoutdefs/, are compiled into ./custom/modules/<module>/Ext/Layoutdefs/layoutdefs.ext.php using the extension framework. You should also note that when a relationship is saved, wireless layouts, located in ./custom/Extension/modules/<module>/Ext/WirelessLayoutdefs/, are created and compiled into ./custom/modules/<module>/Ext/Layoutdefs/layoutdefs.ext.php.
An example of this is when deploying a 1-M relationship from Bugs to Leads, the following layoutdef files are generated:


./custom/Extension/modules/Bugs/Ext/Layoutdefs/bugs_leads_1_Bugs.php
<?php
$layout_defs["Bugs"]["subpanel_setup"]['bugs_leads_1'] = array (
  'order' => 100,
  'module' => 'Leads',
  'subpanel_name' => 'default',
  'sort_order' => 'asc',
  'sort_by' => 'id',
  'title_key' => 'LBL_BUGS_LEADS_1_FROM_LEADS_TITLE',
  'get_subpanel_data' => 'bugs_leads_1',
  'top_buttons' =>
  array (
    0 =>
    array (
      'widget_class' => 'SubPanelTopButtonQuickCreate',


array (
      'widget_class' => 'SubPanelTopButtonQuickCreate',
    ),
    1 =>
    array (
      'widget_class' => 'SubPanelTopSelectButton',
      'mode' => 'MultiSelect',
    ),
  ),
);
./custom/Extension/modules/Bugs/Ext/WirelessLayoutdefs/bugs_leads_1_Bugs.php
<?php
$layout_defs["Bugs"]["subpanel_setup"]['bugs_leads_1'] = array (
  'order' => 100,
  'module' => 'Leads',
  'subpanel_name' => 'default',
  'title_key' => 'LBL_BUGS_LEADS_1_FROM_LEADS_TITLE',


'get_subpanel_data' => 'bugs_leads_1',
);
Fields Metadata
Sidecar's subpanel field layouts are initially defined by the subpanel list-view metadata.
Hierarchy Diagram
The subpanel list metadata is loaded in the following manner:
Note: The Sugar application's client type is "base". For more information on the various client types, please refer toÂ the User Interface page.
Subpanel List Views
By default, all modules come with a default set of subpanel fields for when they are rendered as a subpanel. An example of this is can be found in the Bugs module:
./modules/Bugs/clients/base/views/subpanel-list/subpanel-list.php
<?php
$subpanel_layout['list_fields'] = array (
  'full_name' =>
  array (


'full_name' =>
  array (
    'type' => 'fullname',
    'link' => true,
    'studio' =>
    array (
      'listview' => false,
    ),
    'vname' => 'LBL_NAME',
    'width' => '10%',
    'default' => true,
  ),
  'date_entered' =>
  array (
    'type' => 'datetime',
    'studio' =>
    array (
      'portaleditview' => false,
    ),
    'readonly' => true,
    'vname' => 'LBL_DATE_ENTERED',
    'width' => '10%',
    'default' => true,
  ),
  'refered_by' =>
  array (


),
  'refered_by' =>
  array (
    'vname' => 'LBL_LIST_REFERED_BY',
    'width' => '10%',
    'default' => true,
  ),
  'lead_source' =>
  array (
    'vname' => 'LBL_LIST_LEAD_SOURCE',
    'width' => '10%',
    'default' => true,
  ),
  'phone_work' =>
  array (
    'vname' => 'LBL_LIST_PHONE',
    'width' => '10%',
    'default' => true,
  ),
  'lead_source_description' =>
  array (
    'name' => 'lead_source_description',


array (
    'name' => 'lead_source_description',
    'vname' => 'LBL_LIST_LEAD_SOURCE_DESCRIPTION',
    'width' => '10%',
    'sortable' => false,
    'default' => true,
  ),
  'assigned_user_name' =>
  array (
    'name' => 'assigned_user_name',
    'vname' => 'LBL_LIST_ASSIGNED_TO_NAME',
    'widget_class' => 'SubPanelDetailViewLink',
    'target_record_key' => 'assigned_user_id',
    'target_module' => 'Employees',
    'width' => '10%',
    'default' => true,
  ),
  'first_name' =>
  array (


),
  'first_name' =>
  array (
    'usage' => 'query_only',
  ),
  'last_name' =>
  array (
    'usage' => 'query_only',
  ),
  'salutation' =>
  array (
    'name' => 'salutation',
    'usage' => 'query_only',
  ),
);
To modify this layout, navigate to Admin > Studio > {Parent Module} > Subpanels > Bugs and make your changes. Once saved, Sugar will generate ./custom/modules/Bugs/clients/<client>/views/subpanel-for-<link>/subpanel-for-<link>.php which will be used for rendering the fields you selected.


You should note that, just as Sugar mimics the Sidecar layouts in the legacy MVC framework for modules in backward compatibility, it also mimics the field list in ./modules/<module>/metadata/subpanels/default.php and ./custom/modules/<module>/metadata/subpanels/default.php. This is done to ensure that any related modules, whether in Sidecar or Backward Compatibility mode, display the same field list as expected.
  	Last modified: 2023-02-03 21:04:03


Modules
Overview
How modules are defined and used within the system
Module Definitions
The module definitions, defined in ./include/modules.php, determineÂ how modules are displayed and used throughout the application. Any custom metadata, whether from a plugin or a custom module, should be loaded through the IncludeÂ extension.Â Prior to 6.3.x, module definitions could be added by creating the file ./include/modules_override.php. This method of creating module definitions is still compatible but is not recommended from a best practices standpoint.Â
Hierarchy Diagram
The modules metadata are loaded in the following manner:
$moduleList
The $moduleList is an array containing a list of modules in the system. The format of the array is to have a numeric index and a value of the modules unique key.
$moduleList[] = 'Accounts';
$beanList


$moduleList[] = 'Accounts';
$beanList
The $beanList variable is an array that stores a list of all active beans (modules) in the application. The format of the array is array('<bean plural name>' => '<bean singular name>');. The $beanList key is used to lookup values in the $beanFiles variable.
$beanList['Accounts'] = 'Account';
$beanFiles
The $beanFiles variable is an array used to reference the class files for a bean. The format of the array is array('<bean singular name>' => '<relative class file>');. The bean name, stored in singular form, is a reference to the class name of the object, which is looked up from the $beanList 'key'.
$beanFiles['Account'] = 'modules/Accounts/Account.php';
$modInvisList


$modInvisList
The $modInvisList variableÂ removes a module from the navigation tab in the MegaMenu, reporting, and it's subpanels under related modules.To enable a hidden module for reporting, you can useÂ $report_include_modules.Â To enable a hidden modulesÂ subpanels on related modules, you can useÂ $modules_exempt_from_availability_check.Â TheÂ
$modInvisList[] = 'Prospects';
$modules_exempt_from_availability_check
TheÂ $modules_exempt_from_availability_check variable is used in conjunction withÂ $modInvisList. When a module has been removed from the MegaMenu view with $modInvisList,Â this will allow for the display of the modules subpanels under related modules.


$modules_exempt_from_availability_check['OAuthKeys'] = 'OAuthKeys';
$report_include_modules
Â TheÂ $report_include_modulesÂ variable is used in conjunction withÂ $modInvisList. When a module has been hidden with $modInvisList,Â this will allow for the module to be enabled for reporting.
$report_include_modules['Prospects'] = 'Prospect';
$adminOnlyList
The $adminOnlyList variable is an extra level of security for modules that are can be accessed only by administrators through the Admin page. Specifying all will restrict all actions to be admin only.
$adminOnlyList['PdfManager'] = array(
    'all' => 1
);
$bwcModules


'all' => 1
);
$bwcModules
The $bwcModules variable determines which modules are in backward compatibility mode. More information on backward compatibility can be found in the Backward Compatibility section.
  	Last modified: 2023-02-03 21:04:03


Relationships
Overview
Relationships are the basis for linking information within the system. This pageÂ explains the various aspects of relationships. For information on custom relationships, please refer to the Custom Relationships documentation.
Definitions
Relationships are initially defined in the module's vardefs file under the relationships array. For reference, you can find them using the vardef pathÂ ./modules/<module>/vardefs.php.
Database Structure


Database Structure
In Sugar, most relationships are stored using a joining table. This applies to both one-to-many (1:M) relationships as well as many-to-many (M:M) relationships. An example of this is the relationship between Accounts and Opportunities where there are three tables:Â accounts,Â accounts_opportunities,Â andÂ opportunities.Â You will find that the joining table,Â accounts_opportunities,Â will contain the fields needed in order to establish the relationship link.
The fields on the accounts_opportunitiesÂ table are listed below:
Fields
Description
id
A unique identifier for the relationship row (not typically used)
opportunity_id
The ID for the related opportunityÂ record. This isÂ named uniquely based on the relationship
account_id


account_id
The ID for the related accountÂ record. This is named uniquely based on the relationship
date_modified
The date the row was last modified
deleted
Whether or not the relationship still exists
Relationship Cache
All relationships in Sugar are compiled into the cache directory ./cache/Relationships/relationships.cache.php.Â If needed, the relationships cache can be rebuilt by navigating toÂ Admin > Repair > Rebuild Relationships.
TopicsCustom RelationshipsThis page needs an overview
  	Last modified: 2023-02-03 21:04:03


Custom Relationships
Overview
This page needs an overview
Creating Custom Relationships
Relationships are initially defined in the module's vardefs file under the relationships array. For reference, you can find them using the vardef path as follows:
./modules/<module>/vardefs.php
Custom relationships are created in a different way using the Extension Framework. The process requires two steps which are explained in the following sections:
Defining the Relationship MetaData
Defining the Relationship in the TableDictionary
Defining the Relationship MetaData
The definitions for custom relationships will be found in a path similar to:
./custom/metadata/<relatonship name>MetaData.php
This file will contain the $dictionary information needed for the system to generate the relationship. The $dictionary array will contain the following:
Index
Type
Description
true_relationship_type
String


Index
Type
Description
true_relationship_type
String
The relationship's structure (possible values: 'one-to-many' or 'many-to-many')
from_studio
Boolean
Whether the relationship was created in Studio
table
String
The name of the table that is created in the database to contain the link ids
fields
Array
An array of fields to be created on the relationship join table
indices
Array
The list of indexes to be created
relationships
Array
An array defining relationships
relationships.<rel>
Array
The array defining the relationship
relationships.<rel>.lhs_module
String
Left-hand module (should match $beanList index)
relationships.<rel>.lhs_table
String
Left-hand table name
relationships.<rel>.lhs_key
String
The key to use from the table on the left


String
The key to use from the table on the left
relationships.<rel>.rhs_module
String
Right-hand module (should match $beanList index)
relationships.<rel>.rhs_table
String
Right-hand table name
relationships.<rel>.rhs_key
String
The key to use from the table on the right
relationships.<rel>.relationship_type
String
The relationship type, typically stored as 'many-to-many'
relationships.<rel>.join_table
String
The join table
relationships.<rel>.join_key_lhs
String
Left table key, should exist in table field definitions above
relationships.<rel>.join_key_rhs
String
RightÂ table key, should exist in table field definitions above
MetaData Example
Creating a custom 1:M relationship between Accounts and Contacts will yield the following metadata file:


Creating a custom 1:M relationship between Accounts and Contacts will yield the following metadata file:
./custom/metadata/accounts_contacts_1MetaData.php
<?php
// created: 2013-09-20 15:15:47
$dictionary["accounts_contacts_1"] = array (
  'true_relationship_type' => 'one-to-many',
  'from_studio' => true,
  'relationships' =>
  array (
    'accounts_contacts_1' =>
    array (
      'lhs_module' => 'Accounts',
      'lhs_table' => 'accounts',
      'lhs_key' => 'id',
      'rhs_module' => 'Contacts',
      'rhs_table' => 'contacts',


'rhs_table' => 'contacts',
      'rhs_key' => 'id',
      'relationship_type' => 'many-to-many',
      'join_table' => 'accounts_contacts_1_c',
      'join_key_lhs' => 'accounts_contacts_1accounts_ida',
      'join_key_rhs' => 'accounts_contacts_1contacts_idb',
    ),
  ),
  'table' => 'accounts_contacts_1_c',
  'fields' =>
  array (
    0 =>
    array (
      'name' => 'id',
      'type' => 'varchar',
      'len' => 36,
    ),
    1 =>
    array (
      'name' => 'date_modified',


1 =>
    array (
      'name' => 'date_modified',
      'type' => 'datetime',
    ),
    2 =>
    array (
      'name' => 'deleted',
      'type' => 'bool',
      'len' => '1',
      'default' => '0',
      'required' => true,
    ),
    3 =>
    array (
      'name' => 'accounts_contacts_1accounts_ida',
      'type' => 'varchar',
      'len' => 36,
    ),
    4 =>
    array (
      'name' => 'accounts_contacts_1contacts_idb',
      'type' => 'varchar',
      'len' => 36,
    ),
  ),
  'indices' =>


),
  ),
  'indices' =>
  array (
    0 =>
    array (
      'name' => 'accounts_contacts_1spk',
      'type' => 'primary',
      'fields' =>
      array (
        0 => 'id',
      ),
    ),
    1 =>
    array (
      'name' => 'accounts_contacts_1_ida1',
      'type' => 'index',
      'fields' =>
      array (
        0 => 'accounts_contacts_1accounts_ida',
      ),
    ),
    2 =>
    array (
      'name' => 'accounts_contacts_1_alt',
      'type' => 'alternate_key',
      'fields' =>
      array (


'fields' =>
      array (
        0 => 'accounts_contacts_1contacts_idb',
      ),
    ),
  ),
);
Defining the Relationship in the TableDictionary
Once a relationship's metadata has been created, the metadata file will have a reference placed in the TableDictionary:
./custom/Extension/application/Ext/TableDictionary/<relationship name>.php
This file will contain an 'include' reference to the metadata file:
<?php
    include('custom/metadata/<relationship name>MetaData.php');
?>
TableDictionary Example
The custom 1:M relationship between Accounts and Contacts will yield the following TableDictionary file:
./custom/Extension/application/Ext/TableDictionary/accounts_contacts_1.php
<?php
    //WARNING: The contents of this file are auto-generated


<?php
    //WARNING: The contents of this file are auto-generated
    include('custom/metadata/accounts_contacts_1MetaData.php');
?>
If you have created theÂ relationship through Studio, the files above will be automatically created. If you are manually creating the files, run a Quick Repair and Rebuild and run any SQL scripts generated. The Quick Repair and Rebuild will rebuild the file map and relationship cache as well as populate the relationship in the relationships table.
  	Last modified: 2023-02-03 21:04:03


Integration
Overview
How to integrate with Sugar APIs
TopicsBest PracticesBest practices when integrating and migrating Sugar.Web ServicesDocumentation on Sugar Web Service APIs.ExternalResourceClientDocumentation on ExternalResourceClient, which replaces cURL.MigrationInformation on migrating data and Sugar instances.
  	Last modified: 2023-02-03 21:04:03


Web Services
Overview
Web Services allow for communication between different applications and platforms. Sugar currently supports REST and SOAP APIs. The following sections will outline how to interact with the APIs and what versions of the API we recommend for use.
Versioning
API versioning is the process of creating a new set of API endpoints for new functionality while leaving pre-existing endpoints available for third-party applications and integrations to continue using. This helps to extend the application in an upgrade-safe manner.
Quick Reference
When working with the Web Service API, you should be using the latest REST API specific to your release. A quick reference of this can be found below:
Release1
REST Version
REST URL
SOAP Version2
SOAP URL
13.0.x
v11.20
/rest/v11_20/
v4.1
/service/v4_1/soap.php


v4.1
/service/v4_1/soap.php
12.3.x
v11.19
/rest/v11_19/
v4.1
/service/v4_1/soap.php
12.2.x
v11.18
/rest/v11_18/
v4.1
/service/v4_1/soap.php
12.1.x
v11.17
/rest/v11_17/
v4.1
/service/v4_1/soap.php
12.0.x
v11.16
/rest/v11_16/
v4.1
/service/v4_1/soap.php
11.3.x
v11.15
/rest/v11_15/
v4.1


v11.15
/rest/v11_15/
v4.1
/service/v4_1/soap.php
11.2.x
v11.14
/rest/v11_14/
v4.1
/service/v4_1/soap.php
11.1.x
v11.13
/rest/v11_13/
v4.1
/service/v4_1/soap.php
11.0.x
v11.12
/rest/v11_12/
v4.1
/service/v4_1/soap.php
10.3.x
v11.11
/rest/v11_11/
v4.1
/service/v4_1/soap.php
10.2.x
v11.10


10.2.x
v11.10
/rest/v11_10/
v4.1
/service/v4_1/soap.php
10.1.x
v11.9
/rest/v11_9/
v4.1
/service/v4_1/soap.php
10.0.x
v11.8
/rest/v11_8/
v4.1
/service/v4_1/soap.php
9.3.x
v11.7
/rest/v11_7/
v4.1
/service/v4_1/soap.php
9.2.x
v11.6
/rest/v11_6/
v4.1
/service/v4_1/soap.php
9.1.x


/service/v4_1/soap.php
9.1.x
v11.5
/rest/v11_5/
v4.1
/service/v4_1/soap.php
9.0.x
v11.4
/rest/v11_4/
v4.1
/service/v4_1/soap.php
8.3.x
v11.4
/rest/v11_4/
v4.1
/service/v4_1/soap.php
8.2.x
v11.3
/rest/v11_3/
v4.1
/service/v4_1/soap.php
8.1.x
v11.2
/rest/v11_2/
v4.1


v11.2
/rest/v11_2/
v4.1
/service/v4_1/soap.php
8.0.x
v11.1
/rest/v11_1/
v4.1
/service/v4_1/soap.php
7.11.x
v11
/rest/v11/
v4.1
/service/v4_1/soap.php
7.10.x
v11
/rest/v11/
v4.1
/service/v4_1/soap.php
7.9.x
v10
/rest/v10/
v4.1
/service/v4_1/soap.php
7.8.x
v10
/rest/v10/
v4.1


v10
/rest/v10/
v4.1
/service/v4_1/soap.php
7.7.x
v10
/rest/v10/
v4.1
/service/v4_1/soap.php
6.5.x
v4.1
/service/v4_1/rest.php
v4.1
/service/v4_1/soap.php
1 Some of the releases in this table may no longer be officially-supported Sugar versions, but we have included them for archival purposes. For more information, please refer to the Supported Versions resource page. 2 As of Sugar 7.0, SOAP support is no longer offered with the new APIs. The legacy APIs will remain accessible in the product, however, any existing integrations should be updated to use the latest REST endpoints.


TopicsREST APIv10 - v11.20 API documentation.Legacy APIv1 - v4.1 API documentation.
  	Last modified: 2023-04-05 00:07:43


This API has been succeeded by a new version. It is recommended to upgrade to the latest API.
Legacy API
Overview
v1 - v4.1 APIÂ documentation.
SOAP VS REST
There are significant differences between how the legacy REST and SOAP protocols function on an implementation level (e.g. Performance, response size, etc). Deciding which protocol to use is up to the individual developer and is beyond the scope of this guide. Starting in SugarCRM version 6.2.0, there are some deviations between the protocols with the v4 API. There are additional core calls that are only made available through the REST protocol. They are listed below:
get_module_layout
get_module_layout_md5
get_quotes_pdf method
get_report_pdf method
snip_import_emails
snip_update_contacts
job_queue_cycle
job_queue_next


snip_update_contacts
job_queue_cycle
job_queue_next
job_queue_run
oauth_access method
oauth_access_token
oauth_request_token
REST
REST stands for 'Representational State Transfer'. This protocol is used by Sugar to exchange information both internally and externally.
How do I access the REST service?
The legacy REST services in SugarCRM and be found by navigating to:
http://{site url)/service/{version}/rest.php
Where 'site url' is the URL of your Sugar instance and 'version' is the latest version of the API specific to your release of Sugar. You can find out more about versioning in the Web Services documentation.
Input / Output Datatypes
The default input / output datatype for REST is JSON / PHP serialize.


The default input / output datatype for REST is JSON / PHP serialize.
These datatype files, SugarRestJSON.php and SugarRestSerialize.php, are in:
./service/core/REST/
Defining your own Datatypes
You can also define you own datatype. To do this, you need to create a new file such as:
./service/core/REST/SugarRest<CustomDataType>.php
Next, you will need to override generateResponse() and serve() functions. The Serve function decodes or unserializes the appropriate datatype based on the input type; the generateResponse function encodes or serializes it based on the output type.


See service/test.html for more examples on usage. In this file, the getRequestData function, which generates URL with json, is both the input_type and the response_type. That is, the request data from the JavaScript to the server is JSON and response data from server is also JSON. You can mix and match any datatype as input and output. For example, you can have JSON as the input_type and serialize as the response_type based on your application's requirements.
REST Failure Response
If a call failure should occur, the result will be as shown below:
Name
Type
Description
name
String
Error message.
number
Integer
Error number.
description
String
Description of error.
SOAP
SOAP stands for 'Simple Object Access Protocol'. SOAP is a simple XML-based protocol that is used to allow applications to exchange information.
How do I access the SOAP service?


How do I access the SOAP service?
The legacy SOAP service in SugarCRM and be found by navigating to:
http://{sugar_url)/service/{version}/soap.php
Where 'sugar_url' is the url of your Sugar instance and 'version' is the latest version of the API specific to your release of Sugar. You can find out more about versioning in the section titled 'API: Versioning'. The default WSDL is formatted as rpc/encoded.
WS-I 1.0 Compliancy
Sugar supports generating a URL that is WS-I compliant. When accessing the soap entry point, you can access the WSDL at:
http://{sugar_url)/service/{version}/soap.php?wsdl


By default, the WSDL is formatted as rpc/encoded, however, this can be changed by specifying a 'style' and 'use' url-paramater. An example of this is:
http://{sugar_url)/service/{version}/soap.php?wsdl&style=rpc&use=literal
URL Parameters
style
rpc
use
encoded
literal
Validation
This WSDL (rpc/literal) was successfully verified against Apache CXF 2.2.
SOAP Failure Response
If a call failure should occur, the result will be as shown below:
Name
Type
Description
faultcode
Integer
Fault ID.
faultactor
String
Provides information about what caused the fault to happen.
faultstring
String
Fault Message.
detail
String
Description of fault.


faultstring
String
Fault Message.
detail
String
Description of fault.
TopicsWhat is NuSOAP?NuSOAP is a SOAP Toolkit for PHP that doesn't require PHP extensions.MethodsWeb Service Method Calls.REST Release NotesLists changes between the different versions of the REST API.SOAP Release NotesLists changes between the different versions of the SOAP API.SugarHttpClientThe SugarHttpClient class is used to make REST calls.
  	Last modified: 2023-02-03 21:04:03


This API has been succeeded by a new version. It is recommended to upgrade to the latest API.
What is NuSOAP?
Overview
NuSOAP is a SOAP Toolkit for PHP that doesn't require PHP extensions.
Where Can I Get It?
NuSOAP can be downloaded fromÂ http://nusoap.sourceforge.net
How Do I Use It?
After you have downloaded NuSOAP, you will need to extract the zip file contents to a storage directory. Once extracted, you will reference "lib/nusoap.php" in your PHP SOAP application.
Example
<?php
//require NuSOAP
require_once("./lib/nusoap.php");
//retrieve WSDL


//retrieve WSDL
$client = new nusoap_client("http://{site_url}/service/v4/soap.php?wsdl", 'wsdl');
Â
Â
  	Last modified: 2023-02-03 21:04:03


This API has been succeeded by a new version. It is recommended to upgrade to the latest API.
REST Release Notes
Overview
Lists changes between the different versions of the REST API.
Release Notes
v4_1
get_modified_relationships method was added.
get_relationships had the parameter $limit added.
get_relationships had the parameter $offset added.
v4
get_entries had the parameter $track_view removed.
job_queue_cycle method was added.
job_queue_next method was added.
job_queue_run method was added.
oauth_access method was added.
oauth_access_token method was added.
oauth_request_token method was added.
search_by_module had the parameter $favorites added.
snip_import_emails method was added.
snip_update_contacts method was added.


snip_update_contacts method was added.
v3_1
get_entries had the parameter $track_view added.
get_entry had the parameter $track_view added.
get_entry_list had the parameter $favorites added.
get_language_definition method was added.
get_module_layout had the parameter $acl_check added.
get_module_layout_md5 had the parameter $acl_check added.
get_quotes_pdf method was added.
get_report_pdf method was added.
search_by_module had the parameter $unified_search_only added.
set_entry had the parameter $track_view added.
v3
get_available_modules had the parameter $filter added.
get_last_viewed method was added.
get_module_fields_md5 method was added.


get_module_fields_md5 method was added.
get_module_layout method was added.
get_module_layout_md5 method was added.
get_relationships had the parameter $order_by added.
get_upcoming_activities method was added.
search_by_module had the parameter $assigned_user_id added.
search_by_module had the parameter $select_fields added.
v2_1
get_entry_list method logic was modified.
get_report_entries method logic was modified.
md5 method was removed.
v2 (REST API was introduced into SugarCRM)
get_available_modules method was added.
get_document_revision method was added.
get_entries method was added.
get_entries_count method was added.
get_entry method was added.


get_entries_count method was added.
get_entry method was added.
get_entry_list method was added.
get_module_fields method was added.
get_note_attachment method was added.
get_relationships method was added.
get_report_entries method was added.
get_server_info method was added.
get_user_id method was added.
get_user_team_id method was added.
login method was added.
logout method was added.
md5 method was added.
seamless_login method was added.
search_by_module method was added.
set_campaign_merge method was added.
set_document_revision method was added.
set_entries method was added.
set_entry method was added.
set_note_attachment method was added.


set_entry method was added.
set_note_attachment method was added.
set_relationship method was added.
set_relationships method was added.SOAP Release Notes
  	Last modified: 2023-02-03 21:04:03


SugarHttpClient
Overview
The SugarHttpClient class is used to make REST calls.
The SugarHttpClient Class
The SugarHttpClient class is located in 'include/SugarHttpClient.php'. It contains a callRest() method that will allow you to post a request to a REST service via cURL without having to worry about the overhead or the restrictions on the file_get_contents() method when doing outbound webservice calls.
Making a Request
<?php
    // specify the REST web service to interact with
    $url = 'http://{sugar_url}/service/v4_1/rest.php';
    // Open a SugarHttpClient session for making the call
    require_once('include/SugarHttpClient.php');
    $client = new SugarHttpClient;
    // Set the POST arguments to pass to the Sugar server
    $parameters = array(


$parameters = array(
        'user_auth' => array(
            'user_name' => 'username',
            'password' => md5('password'),
        ),
    );
    $json = json_encode($parameters);
    $postArgs = array(
        'method' => 'login',
        'input_type' => 'JSON',
        'response_type' => 'JSON',
        'rest_data' => $json,
    );
    $postArgs = http_build_query($postArgs);
    // Make the REST call, returning the result
    $response = $client->callRest($url, $postArgs);
    if ( $response === false )
    {
        die("Request failed.\n");
    }
    // Convert the result from JSON format to a PHP array


}
    // Convert the result from JSON format to a PHP array
    $result = json_decode($response);
    if ( !is_object($result) )
    {
        die("Error handling result.\n");
    }
    if ( !isset($result->id) )
    {
        die("Error: {$result->name} - {$result->description}\n.");
    }
    // Get the session id
    $sessionId = $result->id;
?>
  	Last modified: 2023-02-03 21:04:03


This API has been succeeded by a new version. It is recommended to upgrade to the latest API.
Methods
Web Service Method Calls.


Topicsget_available_modulesRetrieves a list of available modules in the system.get_document_revisionRetrieves a specific document revision.get_entriesRetrieves a list of beans based on specified record IDs.get_entries_countRetrieves a list of beans based on query specifications.get_entryRetrieves a single bean based on record ID.get_entry_listRetrieves a list of beans based on query specifications.get_language_definitionRetrieves the language label strings for the specified modules.get_last_viewedRetrieves a list of recently viewed records by module for the current user.get_modified_relationshipsRetrieves a list of modified relationships between a specific date range. Helps facilitate sync operations for users.get_module_fieldsRetrieves the list of field vardefs for a specific module.get_module_fields_md5Retrieves the


for a specific module.get_module_fields_md5Retrieves the MD5 hash of the vardefs for the specified modules.get_module_layoutRetrieves the layout metadata for a given module given a specific type and view.get_module_layout_md5Retrieves the MD5 hash value for a layout given a specific module, type and view.get_note_attachmentRetrieves an attachment associated with a specific note record.get_quotes_pdfGenerates a quote PDF for a specific quote.get_relationshipsRetrieves a specific relationship link for a specified record.get_report_entriesRetrieves a list of report entries based on specified record IDs.get_report_pdfGenerates a PDF for a specific report.get_server_infoRetrieves info about the SugarCRM instance.get_upcoming_activitiesRetrieves a list of upcoming activities for the current


instance.get_upcoming_activitiesRetrieves a list of upcoming activities for the current user.get_user_idRetrieves the id of the user currently logged in.get_user_team_idRetrieves the ID of the default team of the user who is logged into the current session.job_queue_cycleRuns through the scheduler cleanup process and cycles the scheduler jobs.job_queue_nextRetrieves the next job from the job queue and marks it as 'In Progress'.job_queue_runRuns the specified job.loginLogs a user into the SugarCRM application.logoutLogs a user out of the SugarCRM application.oauth_accessRetrieves the OAuth access token.seamless_loginVerifies that a session is authenticated.search_by_moduleSearches modules for a string and returns matched records.set_campaign_mergeHandles campaign log entry


modules for a string and returns matched records.set_campaign_mergeHandles campaign log entry creation for mail-merge activity given a specified campaign.set_document_revisionCreates a new document revision for a specific document record.set_entriesCreate or update a list of records.set_entryCreates or updates a specific record.set_note_attachmentCreates an attachment and associated it to a specific note record.set_relationshipSets relationships between two records. You can relate multiple records to a single record using this.set_relationshipsSets multiple relationships between mulitiple record sets.snip_import_emailsUsed to imports an email record from the SNIP archiving service.snip_update_contactsRetrieves new contact emails since a timestamp for the current user.


Last modified: 2023-02-03 21:04:03


This API has been succeeded by a new version. It is recommended to upgrade to the latest API.
set_entry
Overview
Creates or updates a specific record.
Available APIs
SOAP
REST
Definition
set_entry(session, module_name, name_value_list)
Parameters
Name
Type
Description
session
String
Session ID returned by a previous login call.
module_name
String
The name of the module from which to retrieve records. Note: This is the modules key which may not be the same as the modules display name.
name_value_list
name_value_list | Array
The name/value list of the record attributes.
Result
Name
Type
Description
result
new_set_entry_result | Array
The call result.
result.id
String
The ID of the record that was created/updated.
Change Log
Version
Change
v2


Change Log
Version
Change
v2
Return type was changed from set_entry_result to new_set_entry_result.
Considerations
To update an existing record, you will need to specify 'id' in the name_value_list parameter.
To create a new record with a specific ID, you will need to set 'new_with_id' in the name_value_list parameter.
Examples
PHP
$set_entry_parameters = array(
    //session id
    "session" => $session_id,
    //The name of the module from which to retrieve records.
    "module_name" => "Accounts",
    //Record attributes
    "name_value_list" => array(
        //to update a record
        /*
        array(
            "name" => "id",


/*
        array(
            "name" => "id",
            "value" => "da0b107d-cfbc-cb08-4f90-50b7b9cb9ad7"
        ),
        */
        //to create a new record with a specific ID
        /*
        array(
            "name" => "new_with_id",
            "value" => true
        ),
        */
        array(
            "name" => "name",
            "value" => "Example Account"
        ),
    ),
);
  	Last modified: 2023-02-03 21:04:03


This API has been succeeded by a new version. It is recommended to upgrade to the latest API.
get_document_revision
Overview
Retrieves a specific document revision.
Available APIs
SOAP
REST
Definition
get_document_revision(session, i)
Parameters
Name
Type
Description
session
String
Session ID returned by a previous login call.
i
String
The ID of the document revision.
Result
Name
Type
Description
result
new_return_document_revision| Array
The call result.
result.document_revision
Array
The details of the document revision.
result.document_revision.id
String
The document ID.
result.document_revision.document_name
String
The document name.
result.document_revision.revision
String
The document revision number
result.document_revision.filename
String


String
The document revision number
result.document_revision.filename
String
The filename of the file.
result.document_revision.file
String
The binary contents of the file.
Change Log
Version
Change
v2
Return type was changed from return_document_revision to new_return_document_revision.
Examples
PHP
$get_document_revision_parameters = array(
    //Session id
    "session" => $session_id,
    //The attachment details
    "i" => '723b7dcb-27b3-e53d-b348-50bd283f8e48',
);
  	Last modified: 2023-02-03 21:04:03


This API has been succeeded by a new version. It is recommended to upgrade to the latest API.
get_note_attachment
Overview
Retrieves an attachment associated with a specific note record.
Available APIs
SOAP
REST
Definition
get_note_attachment(session, id)
Parameters
Name
Type
Description
session
String
Session ID returned by a previous login call.
id
String
The ID of the note record to associate the attachment to.
Result
Name
Type
Description
result
new_return_note_attachment | Array
The call result.
result.note_attachment
Array
The details of the file attachment.
result.note_attachment.id
String
The ID of the note record / attachment.
result.note_attachment.filename
String
The filename of the attachment.
result.note_attachment.file
String


String
The filename of the attachment.
result.note_attachment.file
String
The binary contents of the file.
result.note_attachment.related_module_id
String
The related parent ID.
result.note_attachment.related_module_name
String
The related parent module.
Change Log
Version
Change
v2
Return type was changed from return_note_attachment to new_return_note_attachment.
Examples
PHP
$get_note_attachment_parameters = array(
    //Session id
    "session" => $session_id,
    //The ID of the note containing the attachment.
    'id' => "9057784d-de17-4f28-c5f9-50bd0f260a43",
);
  	Last modified: 2023-02-03 21:04:03


This API has been succeeded by a new version. It is recommended to upgrade to the latest API.
get_entry
Overview
Retrieves a single bean based on record ID.
Available APIs
SOAP
REST
Definition
get_entry(session, module_name, id, select_fields, link_name_to_fields_array, track_view)
Parameters
Name
Type
Description
session
String
Session ID returned by a previous login call.
module_name
String
The name of the module from which to retrieve records. Note: This is the modules key which may not be the same as the modules display name.
id
String
The ID of the record to retrieve.
select_fields
select_fields | Array
The list of fields to be returned in the results. Specifying an empty array will return all fields.
link_name_to_fields_array


link_name_to_fields_array
link_names_to_fields_array | Array
A list of link names and the fields to be returned for each link.
track_view
Boolean
Flag the record as a recently viewed item.
Result
Name
Type
Description
result
get_entry_result_version2 | Array
The call result.
result.entry_list
Array
The record's name-value pair for the simple datatypes excluding the link field data. If you do not have access to the object, entry_list[].name_value_list will notify you.
result.relationship_list
Array
The records link field data.
Change Log
Version
Change
v3_1
Added track_view parameter.
v2
Added link_name_to_fields_array parameter.
v2


v2
Added link_name_to_fields_array parameter.
v2
Return type was changed from get_entry_result to get_entry_result_version2.
Examples
PHP
$get_entry_parameters = array(
    //session id
    'session' => $session_id,
    //The name of the module from which to retrieve records
    'module_name' => "Contacts",
    //The ID of the record to retrieve.
    'id' => "18df70e4-1422-8bff-6f5f-50aa571fe4e5",
    //The list of fields to be returned in the results
    'select_fields' => array(
        'id',
        'first_name',
        'last_name',
    ),


'first_name',
        'last_name',
    ),
    //A list of link names and the fields to be returned for each link name
    'link_name_to_fields_array' => array(
        array(
            'name' => 'email_addresses',
            'value' => array(
                'email_address',
                'opt_out',
                'primary_address'
            ),
        ),
    ),
    //Flag the record as a recently viewed item
    'track_view' => true,
);
  	Last modified: 2023-02-03 21:04:03


This API has been succeeded by a new version. It is recommended to upgrade to the latest API.
job_queue_run
Overview
Runs the specified job.
Available APIs
REST
Definition
job_queue_run(session, jobid, clientid)
Parameters
Name
Type
Description
session
String
Session ID returned by a previous login call.
jobid
String
The ID of the job to run.
clientid
String
The client id calling the application. This parameter is of your choosing for the calling application.
Result
Name
Type
Description
result
Array
The call result.
result.results
Boolean
The result of the job run.
result.message
String
This is only returned if a failure occurs.
Change Log
Version
Change
v4
Added job_queue_run method.
Examples
PHP


Change
v4
Added job_queue_run method.
Examples
PHP
$job_queue_run_parameters = array(
    //Session id
    'session' => $session_id,
    //The ID of the job to run.
    'jobid' => 'd141efd3-d2c7-8a9c-9c02-50c11b491f16',
    //The ID of the calling application.
    'clientid' => 'MyAppID',
);
  	Last modified: 2023-02-03 21:04:03


This API has been succeeded by a new version. It is recommended to upgrade to the latest API.
get_last_viewed
Overview
Retrieves a list of recently viewed records by module for the current user.
Available APIs
SOAP
REST
Definition
get_last_viewed(session, module_names)
Parameters
Name
Type
Description
session
String
Session ID returned by a previous login call.
module_names
module_names | Array
The list of modules to retrieve last viewed records for.
Result
Name
Type
Description
result
last_viewed_list | Array
The call result. Contains a list of reciently viewed records.
result[].id
Integer
The result ID.
result[].item_id
String
The reciently viewed record ID.
result[].item_summary
String
The name of the reciently viewed record.


result[].item_summary
String
The name of the reciently viewed record.
result[].module_name
String
The name of the module.
result[].monitor_id
String
The monitor ID from the tracker table.
result[].date_modified
String
The date the record was viewed.
Change Log
Version
Change
Examples
PHP
$get_last_viewed_parameters = array(
    //Session id
    "session" => $session_id,
    //The name of the modules to retrieve last viewed for
    'module_names' => array(
        'Contacts',
        'Accounts'
    ),
);
  	Last modified: 2023-02-03 21:04:03


This API has been succeeded by a new version. It is recommended to upgrade to the latest API.
get_modified_relationships
Overview
Retrieves a list of modified relationships between a specific date range. Helps facilitate sync operations for users.
Available APIs
SOAP
REST
Definition
get_modified_relationships(session, module_name, related_module, from_date, to_date, offset, max_results, deleted, module_user_id, select_fields, relationship_name, deletion_date)
Parameters
Name
Type
Description
session
String
Session ID returned by a previous login call.
module_name
String
The module key to retrieve relationships against.
related_module
String
The related module key to retrieve records off of. This parameter should always be 'Users'.
from_date
String


from_date
String
Start date in YYYY-MM-DD HH:MM:SS format for the date range.
to_date
String
End date in YYYY-MM-DD HH:MM:SS format for the date range.
offset
Integer
The offset to begin returning records from.
max_results
Integer
The max_results to return.
deleted
Integer
Whether or not to include deleted records. Set to 1 to find deleted records.
module_user_id
String
*This parameter is no longer used and is only present for backward compatibility purposes.
select_fields
select_fields
List of fields to select and return as name/value pairs.
relationship_name
String
The name of the relationship name to search on.
deletion_date
String


The name of the relationship name to search on.
deletion_date
String
Date value in YYYY-MM-DD HH:MM:SS format for filtering on deleted records whose date_modified falls within range.
Result
Name
Type
Description
result
modified_relationship_result | Array
The call result.
result.result_count
Integer
The result count.
result.next_offset
Integer
The next offset to retrieve from.
result.entry_list
Array
List of found records.
result.error
Array
Error Message.
result.error.number
Integer
The error number.
result.error.name
String
The name of the error.
result.error.description
String
The description of the error.
Change Log
Version
Change
v4_1
Added get_modified_relationships method.
Considerations


Change
v4_1
Added get_modified_relationships method.
Considerations
The module_name parameter should always be 'Users'.
Examples
PHP
$get_modified_relationships_parameters = array(
    //Session id
    'session' => $session_id,
    //The module key to retrieve relationships against.
    //This parameter should always be 'Users'.
    'module_name' => 'Users',
    //The related module key to retrieve records off of.
    'related_module' => 'Meetings',
    //Start date in YYYY-MM-DD HH:MM:SS format for the date range.
    'from_date' => '2000-01-01 01:01:01',
    //End date in YYYY-MM-DD HH:MM:SS format for the date range


'to_date' => '2013-01-01 01:01:01',
    //The offset to begin returning records from.
    'offset' => 0,
    //The max_results to return.
    'max_results' => 5,
    //Whether or not to include deleted records. Set to 1 to find deleted records.
    'deleted' => 0,
    //This parameter is not used.
    'module_user_id' => '',
    //List of fields to select and return as name/value pairs.
    'select_fields' => array(),
    //The name of the relationship name to search on.
    'relationhip_name' => 'meetings_users',
    //Date value in YYYY-MM-DD HH:MM:SS format for filtering on deleted records.


'deletion_date' => '2012-01-01 01:01:01'
);
  	Last modified: 2023-02-03 21:04:03