FUDforum
Fast Uncompromising Discussions. FUDforum will get your users talking.

Home » Imported messages » comp.lang.php » Usage of class constants inside strings and heredocs
Show: Today's Messages :: Polls :: Message Navigator
Switch to threaded view of this topic Create a new topic Submit Reply
Usage of class constants inside strings and heredocs [message #170489] Tue, 02 November 2010 16:14 Go to next message
Giuseppe Sacco is currently offline  Giuseppe Sacco
Messages: 5
Registered: November 2010
Karma: 0
Junior Member
Hi all,
I created a class that encapsulates all methods for accessing a
database table. That class have class constants for defining all table
fields. I would like to create strings that include those constants,
but I fail to see how I might do it.

a simple (and not working) example:

class myTable {
const F_CODE = "code";
const F_DESCRIPTIOM = "description";
const TABLENAME = "lookup";
public function insert($record)
{
$sql = <<<SQLQ
INSERT INTO {self::TABLENAME}
VALUES ({$record[self::F_CODE]},{$record[self::F_DESCRIPTION]}
SQLQ;

// ....
} // end method insert
} // end class myTable

So, again, my question is: how do I put constants inside strings or
heredocs?

Thank you very much,
Giuseppe
Re: Usage of class constants inside strings and heredocs [message #170490 is a reply to message #170489] Tue, 02 November 2010 16:47 Go to previous messageGo to next message
alvaro.NOSPAMTHANX is currently offline  alvaro.NOSPAMTHANX
Messages: 277
Registered: September 2010
Karma: 0
Senior Member
El 02/11/2010 17:14, Giuseppe Sacco escribió/wrote:
> I created a class that encapsulates all methods for accessing a
> database table. That class have class constants for defining all table
> fields. I would like to create strings that include those constants,
> but I fail to see how I might do it.
>
> a simple (and not working) example:
>
> class myTable {
> const F_CODE = "code";
> const F_DESCRIPTIOM = "description";
> const TABLENAME = "lookup";
> public function insert($record)
> {
> $sql =<<<SQLQ
> INSERT INTO {self::TABLENAME}
> VALUES ({$record[self::F_CODE]},{$record[self::F_DESCRIPTION]}
> SQLQ;
>
> // ....
> } // end method insert
> } // end class myTable

"Not working" is a too simplistic description. Let's fix some syntax
errors and run your cod:

<?php

class myTable {
const F_CODE = "code";
const F_DESCRIPTION = "description";
const TABLENAME = "lookup";
public function insert($record)
{
$sql = <<<SQLQ
INSERT INTO {self::TABLENAME}
VALUES ({$record[self::F_CODE]},{$record[self::F_DESCRIPTION]})
SQLQ;

echo $sql;
} // end method insert
} // end class myTable

$record = array(
'code' => 'This is the code',
'description' => 'This is the description',
);
$foo = new myTable;
$foo->insert($record);

?>

INSERT INTO {self::TABLENAME}
VALUES (This is the code,This is the description)



> So, again, my question is: how do I put constants inside strings or
> heredocs?

Here's the documentation for the heredoc syntax:

http://es.php.net/manual/en/language.types.string.php#language.types.string .syntax.heredoc

Scroll down to "Variable parsing". As the title suggests, PHP only
parses variables, but there's a note to be taken into account:

"Functions, method calls, static class variables, and class constants
inside {$} work since PHP 5. However, the value accessed will be
interpreted as the name of a variable in the scope in which the string
is defined. Using single curly braces ({}) will not work for accessing
the return values of functions or methods or the values of class
constants or static class variables."

In simple words: it parses {self::TABLENAME} and then looks for a local
variable called $lookup. There is no replacement for two reasons:

- The syntax should be {${self::TABLENAME}}
- There is no such local variable

This does work as expected:

$tablename = self::TABLENAME;
$f_code = $record[self::F_CODE];
$f_description = $record[self::F_DESCRIPTION];

$sql = <<<SQLQ
INSERT INTO $tablename
VALUES ($f_code,$f_description)
SQLQ;

Make sure that heredoc is simplifying your code and not the opposite. To
build a simple templating system there're other alternatives like
sprintf() or strtr().


--
-- http://alvaro.es - Álvaro G. Vicario - Burgos, Spain
-- Mi sitio sobre programación web: http://borrame.com
-- Mi web de humor satinado: http://www.demogracia.com
--
Re: Usage of class constants inside strings and heredocs [message #170491 is a reply to message #170490] Tue, 02 November 2010 17:58 Go to previous messageGo to next message
Michael Fesser is currently offline  Michael Fesser
Messages: 215
Registered: September 2010
Karma: 0
Senior Member
.oO(Álvaro G. Vicario)

> Make sure that heredoc is simplifying your code and not the opposite. To
> build a simple templating system there're other alternatives like
> sprintf() or strtr().

sprintf() would be my favourite option in cases like this.

Micha
Re: Usage of class constants inside strings and heredocs [message #170498 is a reply to message #170490] Wed, 03 November 2010 09:40 Go to previous messageGo to next message
Giuseppe Sacco is currently offline  Giuseppe Sacco
Messages: 5
Registered: November 2010
Karma: 0
Junior Member
Álvaro,
thanks for your prompt answer. I understood what you say about class
constants and I understood that it is not possible to use class
constants in heredoc or string text. I just would like to write that
in my opinion this would really improve readability: I need class
constants in order to define strings that should never be changeable,
and I think heredoc are wonderful for creating long and indented text.
I mean, I just wrote a very simple query, but real queries use as much
as 20 table fields.
Using sprintf and such, add runtime complexity for dinamically create
a static string.

Is there any other *static* way?

Thanks a lot,
Giuseppe Sacco
Re: Usage of class constants inside strings and heredocs [message #170500 is a reply to message #170498] Wed, 03 November 2010 12:07 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 11/3/2010 5:40 AM, Giuseppe Sacco wrote:
> Álvaro,
> thanks for your prompt answer. I understood what you say about class
> constants and I understood that it is not possible to use class
> constants in heredoc or string text. I just would like to write that
> in my opinion this would really improve readability: I need class
> constants in order to define strings that should never be changeable,
> and I think heredoc are wonderful for creating long and indented text.
> I mean, I just wrote a very simple query, but real queries use as much
> as 20 table fields.
> Using sprintf and such, add runtime complexity for dinamically create
> a static string.
>
> Is there any other *static* way?
>
> Thanks a lot,
> Giuseppe Sacco

If you're trying to use class constants in heredoc or string text,
you're building the string dynamically anyway.

I agree with Micha - sprintf() is good for this; concatenation will also
work but is harder to read, imho.

And no, I don't think the complexity is that great at all, even for 20
fields.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: Usage of class constants inside strings and heredocs [message #170509 is a reply to message #170500] Thu, 04 November 2010 09:01 Go to previous messageGo to next message
Giuseppe Sacco is currently offline  Giuseppe Sacco
Messages: 5
Registered: November 2010
Karma: 0
Junior Member
Hi all,
just to be sure: when you suggest to use sprintf(), do you mean
something like this?

<?php

class myTable {
const F_CODE = "code";
const F_DESCRIPTION = "description";
const TABLENAME = "lookup";
public function insert($record)
{
// simplified: does not escape strings, does not use prepared
statemnts
$sql = sprintf("INSERT INTO %s (%s,%s) VALUES ('%s', '%s')",
self::TABLENAME, self::F_CODE, self::F_DESCRIPTION,
$record[self::F_CODE], $record[self::F_DESCRIPTION]);

echo $sql;
} // end method insert

} // end class myTable

$record = array(
'code' => 'This is the code',
'description' => 'This is the description',
);
$foo = new myTable;
$foo->insert($record);

?>
Re: Usage of class constants inside strings and heredocs [message #170510 is a reply to message #170509] Thu, 04 November 2010 09:16 Go to previous messageGo to next message
alvaro.NOSPAMTHANX is currently offline  alvaro.NOSPAMTHANX
Messages: 277
Registered: September 2010
Karma: 0
Senior Member
El 04/11/2010 10:01, Giuseppe Sacco escribió/wrote:
> Hi all,
> just to be sure: when you suggest to use sprintf(), do you mean
> something like this?
>
> <?php
>
> class myTable {
> const F_CODE = "code";
> const F_DESCRIPTION = "description";
> const TABLENAME = "lookup";
> public function insert($record)
> {
> // simplified: does not escape strings, does not use prepared
> statemnts
> $sql = sprintf("INSERT INTO %s (%s,%s) VALUES ('%s', '%s')",
> self::TABLENAME, self::F_CODE, self::F_DESCRIPTION,
> $record[self::F_CODE], $record[self::F_DESCRIPTION]);
>
> echo $sql;
> } // end method insert
>
> } // end class myTable
>
> $record = array(
> 'code' => 'This is the code',
> 'description' => 'This is the description',
> );
> $foo = new myTable;
> $foo->insert($record);
>
> ?>

IMHO this looks cleaner than your original approach but you can combine
all ideas to your liking, e.g.:

$sql = <<<SQLQ
INSERT
INTO %s (%s, %s)
VALUES ('%s', '%s')
SQLQ;

$sql = sprintf($sql,
self::TABLENAME, self::F_CODE, self::F_DESCRIPTION,
$record[self::F_CODE], record[self::F_DESCRIPTION]);

Or even:

$sql = sprintf(<<<SQLQ
INSERT
INTO %s (%s, %s)
VALUES ('%s', '%s')
SQLQ;
, self::TABLENAME, self::F_CODE, self::F_DESCRIPTION,
$record[self::F_CODE], $record[self::F_DESCRIPTION]);

I particularly love arrays and I tend to abuse them:

$sql = "INSERT
INTO {table} ({f_code}, {f_description})
VALUES ('{r_code}', '{r_description}')";

$replacements = array(
'{table}' => self::TABLENAME,
'{f_code}' => self::F_CODE,
'{f_description}' => self::F_DESCRIPTION,
'{r_code}' => $record[self::F_CODE],
'{r_description}' => $record[self::F_DESCRIPTION]
);

$sql = strtr($sql, $replacements);


You should not run out of ideas :)

--
-- http://alvaro.es - Álvaro G. Vicario - Burgos, Spain
-- Mi sitio sobre programación web: http://borrame.com
-- Mi web de humor satinado: http://www.demogracia.com
--
Re: Usage of class constants inside strings and heredocs [message #170513 is a reply to message #170510] Fri, 05 November 2010 08:41 Go to previous messageGo to next message
Giuseppe Sacco is currently offline  Giuseppe Sacco
Messages: 5
Registered: November 2010
Karma: 0
Junior Member
Hi all,
it seems none of these methods are really good (that's my opinion, of
course) when used in my scenario. I'll try to better depict what is my
source architecture in order to better explain the problem.

I have a few classes that should be used for accessing postgresql
database. The classes are a super class called Table and a few derived
classes, one for each table. The superclass provide methods for
creating insert and update statements. These statements are stored
into the database connection via pg_prepare(). Other Table method will
receive a record and actually call pg_execute() on the prepared
statement.
The super class will use reflection on $this for getting all field
names (declared as class constants) and prepare its statement.

Something similar to this:

class Table {
/*
* Create an SQL statement for pg_prepare()
*/
public function CreaInsertStatement() {
$fields = "";
$values = "";
$j = 1;
$c = new ReflectionClass(get_class($this));

foreach ($c->getConstants() as $key => $value) {
if ($j == 1) {
$fields = "$value";
$values = "\$1";
}
else {
$fields .= ",$value";
$values .= ",\$$j";
}
$j++;
}

$sql = "INSERT INTO {$this->nometabella} (${fields}) VALUES ($
{values})";
return $sql;
}
/*
* Take a record with only data and create a new array with
* all fields ordered as in CreaInsertStatement.
* The final array is to be used in pg_execute()
*/
public function ConvertiArrayPerInsert($assoc)
{
$v = array();
$j = 0;
$c = new ReflectionClass(get_class($this));
foreach ($c->getConstants() as $key => $value) {
$valore = $assoc[$value];
if (is_object($valore)) {
$classe = get_class($valore);
if ("DateTime" == $classe) {
// convert DateTime into string (TimeStamp) since pg_execute
// wouldn't convert it
/* @var $valore DateTime */
$valore = $valore->format('Y-m-d H:i:s');
}
}
$v[$j++] = $valore;
}

return $v;
}
} // end Table class

class Anagrafica extends Tabella {
// elenco dei campi nel database
const DB_ANAG_COD_ANAG = "cod_anag";
const DB_ANAG_COD_ORIGINALE = "cod_originale";
const DB_ANAG_COD_TIPOANAGRAFICA = "cod_tipoanagrafica";
const DB_ANAG_COD_FONTE = "cod_fonte";
const DB_ANAG_COD_TIPORAPPORTO = "cod_tiporapporto";
// more fields ....
protected $primarykey = array(
Anagrafica::DB_ANAG_COD_ANAG => Anagrafica::DB_ANAG_COD_ANAG,
Anagrafica::DB_ANAG_COD_ORIGINALE =>
Anagrafica::DB_ANAG_COD_ORIGINALE);
protected $nometabella = "anagrafica";
}

Thanks again,
Giuseppe
Re: Usage of class constants inside strings and heredocs [message #170514 is a reply to message #170513] Fri, 05 November 2010 12:11 Go to previous messageGo to next message
Giuseppe Sacco is currently offline  Giuseppe Sacco
Messages: 5
Registered: November 2010
Karma: 0
Junior Member
oops, I forgot to add the part about class constants in strings...
in all derived classes, I have special method for common operations on
specific tables. As an example, delete records:

class Comunicazioni extends Table {
// declare all field as class constants
// ...
public function CreaDeleteStatemnt() {
return "DELETE FROM {$this->nometabella}\nWHERE
".Comunicazioni::DB_COD_ANAG."=\$1 AND
".Comunicazioni::DB_COD_ORIGINALE."=\$2";
}
} // end class Comunicazioni

This is where I would like to use heredoc: I am in a derived class, so
I do not need reflection, and I need to create a prepared statement,
so I use placeholders instead of real values.

Bye,
Giuseppe
Re: Usage of class constants inside strings and heredocs [message #170515 is a reply to message #170514] Fri, 05 November 2010 13:01 Go to previous message
Matthew Leonhardt is currently offline  Matthew Leonhardt
Messages: 9
Registered: November 2010
Karma: 0
Junior Member
"Giuseppe Sacco" <eppesuig(at)gmail(dot)com> wrote in message
news:e35bdb56-6101-478c-891b-0facb4ebc0aa(at)g13g2000yqj(dot)googlegroups(dot)com...
> oops, I forgot to add the part about class constants in strings...
> in all derived classes, I have special method for common operations on
> specific tables. As an example, delete records:
>
> class Comunicazioni extends Table {
> // declare all field as class constants
> // ...
> public function CreaDeleteStatemnt() {
> return "DELETE FROM {$this->nometabella}\nWHERE
> ".Comunicazioni::DB_COD_ANAG."=\$1 AND
> ".Comunicazioni::DB_COD_ORIGINALE."=\$2";
> }
> } // end class Comunicazioni
>
> This is where I would like to use heredoc: I am in a derived class, so
> I do not need reflection, and I need to create a prepared statement,
> so I use placeholders instead of real values.

I don't see how any of this is relevant...

public function CreaDeleteStatemnt()
{
$delSql =<<<SQL
DELETE FROM %s
WHERE %s=\$1 AND %s=\$2

SQL;

return sprintf($delSql, $this->nometabella, Comunicazioni::DB_COD_ANAG,
Comunicazioni::DB_COD_ORIGINALE);
}

Does Alvero's (very elegant) suggestion of mixing heredoc with sprintf() not
fulfill your requirements for some reason?
  Switch to threaded view of this topic Create a new topic Submit Reply
Previous Topic: Free Web Space for our Experiments
Next Topic: There is some framework/tool to generate PHP code
Goto Forum:
  

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ]

Current Time: Tue Nov 26 10:38:25 GMT 2024

Total time taken to generate the page: 0.02732 seconds