3
votes

ColdFusion utilisant if conditionnel dans une fonction cfc basée sur un script

J'essaie de m'améliorer avec mon cfscript et je n'arrive pas à comprendre celui-ci. Dans un CFC basé sur des balises, je pourrais faire quelque chose comme ceci:

public query function querySd( numeric sd_id, string sd_code ){
  local.querySd = new Query(datasource = variables.dsn);
  if( isDefined('arguments.sd_id') ){
    local.querySd.addParam( name = 'sdid', value = arguments.sd_id, cfsqltype = 'cf_sql_int');
  };
  if( isDefined('arguments.sd_code') ){
    local.querySd.addParam( name = 'sdcode', value = arguments.sd_code, cfsqltype = 'cf_sql_varchar', maxlength = '20');
  };

 local.querySd.setSql('
            SELECT sd_id, sd_code, sd_active, sd_expires, sd_added, sd_dla
              FROM sd
             WHERE 0 = 0
             if( isDefined('arguments.sd_id') ){
                 AND sd_id = :sdid 
             };
             if( isDefined('arguments.sd_code') ){
                 AND sd_code = :sdcode 
             };
        ');
local.qrySd = local.querySd.execute().getResult();

Cependant, essayer une méthode similaire dans cfscript génère une erreur:

<cffunction name="querySd" access="public" returnType="query" output="false">
  <cfargument name="sd_id" type="numeric" required="No"/>
  <cfargument name="sd_code" type="string" required="No"/>
  <cfquery name="LOCAL.qrySd" datasource="#variables.dsn#">
    SELECT sd_id, sd_code, sd_active, sd_expires, sd_added, sd_dla
     FROM sd 
    WHERE 0=0
     <cfif isDefined("ARGUMENTS.sd_id")>
       AND sd_id = <cfqueryparam cfsqltype="CF_SQL_INTEGER" value="#ARGUMENTS.sd_id#"/>
     </cfif>
     <cfif isDefined("ARGUMENTS.sd_code")>
      AND sd_code = <cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="#ARGUMENTS.sd_code#" maxlength="20"/>
     </cfif>
    </cfquery>
  <cfreturn LOCAL.qrySd>
</cffunction>

Quelle est la manière correcte de travailler avec des arguments optionnels dans une requête basée sur cfscript à l'intérieur d'un cfc?


5 commentaires

Rien à voir avec la question, mais structKeyExist est généralement préféré à IsDefined, pour une meilleure précision.


Bon point - code mis à jour - merci!


Quelle version de CF?


OT: Si je convertissais, j'utiliserais queryexecute (). Il a une syntaxe plus simple.


Idem sur l'utilisation de queryExecute sur l'ancien Query.cfc


3 Réponses :


4
votes

Vous pouvez placer la partie de la requête dans une variable et l'utiliser dans la chaîne de requête.

local.queryPart = '';
if( isDefined('arguments.sd_id') ){
    local.queryPart &= ' AND sd_id = :sdid ';
};
if( isDefined('arguments.sd_code') ){
    local.queryPart &= ' AND sd_code = :sdcode ';
};
local.querySd.setSql('
    SELECT sd_id, sd_code, sd_active, sd_expires, sd_added, sd_dla
    FROM sd
    WHERE 0 = 0
    #local.queryPart#
');


1 commentaires

Merci - J'ai fini par créer une chaîne de requête et la construire en dehors de setSql ().



2
votes

Vous pouvez également utiliser des opérateurs ternaires:

local.querySd.setSql('
        SELECT sd_id, sd_code, sd_active, sd_expires, sd_added, sd_dla
          FROM sd
         WHERE 0 = 0
         # !isNull( arguments.sd_id ) ? ' AND sd_id = :sdid' : '' #
         # !isNull( arguments.sd_code ) ? ' AND sd_code = :sdcode' : '' #
    ');

Personnellement, je trouve cela beaucoup plus lisible.


2 commentaires

Je ne sais pas pourquoi quelqu'un a rejeté cette réponse. J'utilise tout le temps des opérateurs ternaires dans la construction de chaînes, et ils fonctionnent parfaitement bien dans la construction de requêtes. J'ai voté pour cela.


Je pense que c'est plus lisible, mais je n'aime pas cette logique de chaîne à l'intérieur d'une chaîne de requête. Pas de vote positif ou négatif pour moi.



4
votes

Comme d'autres l'ont dit, selon la version de CF que vous utilisez, j'utiliserais queryExecute () sur new Query () . Il y a de nombreuses raisons à cela, et c'est à peu près tout un autre sujet en soi.

Quoi qu'il en soit, maintenant que j'ai une minute, j'ai jeté ensemble un exemple de queryExecute () par souci d'exhaustivité. REMARQUE: J'utilise ici une requête de requête sur des données simulées. La vraie requête utiliserait une source de données réelle.

<cfscript>
public Query function querySd2 ( Numeric sd_id, String sd_code ) {
    // This is my fake query data, thanks to Mockaroo.
    local.sd = queryNew("sd_id,sd_code,sd_active,sd_expires,sd_added,sd_dla",
    "integer,varchar,bit,date,date,varchar",
    [ 
        { "sd_id":1,"sd_code":"DontPickMe","sd_active":true,"sd_expires":"2019-01-04","sd_added":"2018-05-07","sd_dla":"2M66CAf3" } ,
        { "sd_id":2,"sd_code":"PickMe","sd_active":true,"sd_expires":"2018-03-03","sd_added":"2018-08-18","sd_dla":"8FW4HRm8" } ,
        { "sd_id":3,"sd_code":"DontPickMe","sd_active":true,"sd_expires":"2019-01-01","sd_added":"2018-10-28","sd_dla":"4F6kBUm2" } ,
        { "sd_id":4,"sd_code":"PickMe","sd_active":false,"sd_expires":"2018-10-28","sd_added":"2018-08-22","sd_dla":"2NSlNLr8" } ,
        { "sd_id":5,"sd_code":"DontPickMe","sd_active":false,"sd_expires":"2018-03-07","sd_added":"2019-02-09","sd_dla":"8T0cWQc2" }
    ]);
    ////////////////

    local.sqlWhere = "1=1" ; // This is our default WHERE condition.
    local.qryParams  = {} ;  // queryExecute expects a struct of params. Or an array.

    // First, I check that the given args have a length, then create both 
    // the SQL and the param. Also "?." is the safe-navigation operator, added
    // in CF2016. https://helpx.adobe.com/coldfusion/using/language-enhancements.html
    if( len(trim(arguments?.sd_id)) ) {
        sqlWHERE &= " AND sd_id = :sdid" ;  // This is our SQL string. 
        qryParams.sdid = { value:arguments.sd_id, cfsqltype:"cf_sql_integer" } ;
    }

    if( len(trim(arguments?.sd_code)) ) {
        sqlWHERE &= " AND sd_code = :sdcode" ;
        qryParams.sdcode = { value:arguments.sd_code, cfsqltype:"cf_sql_varchar", maxlength:"20" }  ;
    }

    //writeDump(sqlWhere) ;

    // https://cfdocs.org/queryexecute
    local.qrySd = queryExecute( 
          "SELECT sd_id, sd_code, sd_active, sd_expires, sd_added, sd_dla FROM sd WHERE #sqlWhere#" 
        , qryParams 
        , { dbtype="query"} //datasource="dsn" } // Replace dbtype with datasource.
    ) ;
    return qrySd ;  // return our query object.
}

// TESTS
tests = [
    {qry:querySd2(2,"PickMe")         , label:"Results from query"                 , retval:querySd2(2,"PickMe").sd_expires } ,
    {qry:querySd2(1,"PickMe")         , label:"No Results from query"              , retval:querySd2(1,"PickMe").sd_expires } ,
    {qry:querySd2(1)                  , label:"No Param2"                          , retval:querySd2(1).sd_expires } ,
    {qry:querySd2(sd_code = "PickMe") , label:"No Param1 (CF2018+ (named params))" , retval:querySd2(sd_code = "PickMe").sd_expires } ,
    {qry:querySd2()                   , label:"No Params"                          , retval:querySd2().sd_expires } ,
    {qry:querySd2(1," ")              , label:"Edge. Empty string."                , retval:querySd2(1," ").sd_expires } 
] ;
//// Note that the above retval:querySd2().sd_expires only outputs one row. Loop
//// through the results themselves to output the multiple rows. 

writeDump(tests) ;
</cfscript>

https://cffiddle/fiddle.org 32c93137-adb1-4f58-8ed4-21bb9e5212b2 / ee3d9cac-e25e-46ca-8eec-f4ac8ddd4b41 / 4d295400-65fa-4b76-a889-a97a805409ea.cfm

REMARQUE: queryExecute () a été ajouté dans CF11. Safe-navigation (?. ) ajouté dans CF2016.

EDIT: J'ai changé mes données Mockaroo en données de requête statiques. Apparemment, vous pouvez parcourir les données Mockaroo assez rapidement. :-)


3 commentaires

Eh bien, cela n'a pas pris longtemps pour dépenser mon allocation Mockaroo pour la journée. Quand je rentre chez moi, je vais déplacer le .csv quelque part où je peux l'héberger à partir d'une connexion HTTPS.


C'est incroyablement utile! La documentation d'Adobe peut parfois manquer ou être peu conviviale. Il y a une page git d'exemples cfquery dans cfscript - votre exemple devrait y être ajouté.


@Steve Hit up CFDocs si vous recherchez des informations sur les fonctions. Il est un peu plus facile de naviguer que certains des documents Adobe. La meilleure source d'informations sur la mucoviscidose est Google. Il y a des tonnes de bons blogueurs qui ont écrit sur de bonnes choses. Vous devez juste faire attention aux informations datées. Malheureusement, il y en a beaucoup. Et, en tant que développeur Web, je recommande vivement de vous familiariser avec les éléments que vous pouvez trouver sur OWASP ( owasp.org ), en particulier leur top 10 des infos. Mais vraiment bravo pour regarder cfscript sur les balises. :-)