I've just decided to venture off into PHP land for fun and to learn, reading that php is loosely typed and that $var's can be reused is this true that the code below will pose no problem?
$x = 996;
$x = mysql_query("SELECT aString FROM table1");
the variable x will stored as an int datatype with 996, then after the second line it will stored as a string datatype with the string from the query?
There wont be any casting errors?
You are correct; that's the definition of being "loosely typed". However, that may not be the best practice.
http://drupaler.co.uk/blog/baby-dont-you-loose-your-type-me/66 is a good read on your subject.
There will be no errors, except that the second line won't give you a string, mysql_query returns an internal PHP type called a resource (generally some kind of opaque handle/pointer for library functions)
There wont be any casting errors?
Correct!
jalf explained it well here
Related
I have made various functions such as "get_current_balance_from_my_bank_account()". It technically returns a string, but it's always a full integer number (as a string) which has never caused problems when its return variable is used directly in calculations.
However, it feels wrong.
Should I be doing something like this?
return (int)$amount_as_a_string;
Instead of the current:
return $amount_as_a_string;
? Or is (int) some archaic/legacy way of doing this? Should I be using some other, better method?
Example of the context:
$my_balance = get_current_balance_from_my_bank_account();
$previous_balance = load_last_balance();
echo 'I have ' . format_money_prettily($my_balance - $previous_balance) . '!' . PHP_EOL;
Again, I rarely if ever run into issues with this because it understands the "real" type. It does still feel wrong that I'm technically returning and sending around strings which in theory could be causing problems sooner or later -- perhaps catastrophic ones in production!
PHP will implicitly type cast in many situations, but not all. Take for example this:
echo json_encode(['balance' => get_current_balance_from_my_bank_account()]);
Now your type propagates to some other system via JSON, where it may cause actual issues if that system isn't so lenient about types. You're making somebody else deal with your incorrect type.
So, yes, your function should always return the type that it claims it returns. PHP implicitly "helping" you when you don't stick to your own type declarations is just sweeping the problem in the rug, but the problem is still there and may eventually cause actual issues.
I don't think that is something you have to worry to much, considering that php has automatic type conversion.
From the docs:
PHP does not require (or support) explicit type definition in variable declaration; a variable's type is determined by the context
in which the variable is used.
Just because the function returns the right data type does not mean that the value is correct or what you expect.
If you want to make sure that the function returns ok value, validating it before returning it much more helpful than simply typecasting it to correct type.
If you want to be more explicit about typing in PHP, have a look at the following from the manual:
default
By default, PHP will coerce values of the wrong type into the expected scalar type if possible.
For example, a function that is given an integer for a parameter that expects a string will get a variable of type string.
Strict mode
It is possible to enable strict mode on a per-file basis. In strict mode, only a variable of exact type of the type declaration will be accepted, or a TypeError will be thrown.
The only exception to this rule is that an integer may be given to a function expecting a float.
Function calls from within internal functions will not be affected by the strict_types declaration.
To enable strict mode, the declare statement is used with the strict_types declaration:
<?php
declare(strict_types=1); // strict type declaration MUST be the very first statement in your script
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1.5, 2.5));
?>
output
int(3)
Fatal error: Uncaught TypeError: Argument 1 passed to sum() must be of the type integer, float given
Note: Enabling strict mode will also affect return type declarations.
source: php.net
This will never be required in PHP, as it does the type conversion by itself. However you can do this if you want. This depends from project to project, but sometimes a decision is made for a certain project to use explicit types where possible. Also this is a good practice if you are working on a team where some of the people are comfortable with more strict languages.
In your case, depending on the number, there might be a good side in keeping it as a string, as if you convert it to int via casting and the number is bigger than the max_int_size, it will overflow.
As for the other question, casting as int (int) or (integer) is a perfectly good way to do it, even in newer versions. It is not a legacy way whatsoever. This does not mean there aren't other good ways to do that, though. You can also use something like intval() or settype(). In my opinion there isn't one right way to do it. You can decide for yourself on how to do that.
I have been doing some research online and it appears that the answer to my question is no, but I realize there are times when I might miss something or search for something incorrectly. I know in languages like C++, when a variable is declared it can be declared as int or string. Is it possible to force this in PHP?
For Example:
<?php
(int)$var = 5;
?>
will be validated and not cause an error in PHP, but:
<?php
$var = 5;
?>
will cause an error because it was not cast as a type string, int, object, etc...
I know PHP is loosely typed so this may not be an option, however I would like to use it that way I ensure that I sanitize data appropriately and improve readability by letting others know exactly what is going on with the code. I am hoping there is a way to enforce this in the php.ini file or to load it in a script that will always be executed by my program.
Thank you for any help you can offer!
PHP is loosely typed and does not require you to declare a variable type when declaring a variable. You can’t change that behavior with a magic php.ini directive.
The benefit of having “loose typing” is that it allows for flexibility. It allows you to create dynamic applications without having to worry about the type of the variable – PHP makes this possible by not enforcing variable types.
However, if you must convert a variable into a particular format, just cast it:
$int = (int) $foo;
$str = (string) $foo;
$bool = (bool) $foo;
$float = (float) $foo;
...
There are functions to do the same, e.g. intval(), strval(), boolval() – all of them do the same task, but a function is very useful when you want to use it as a callback to another function.
I was marvelled when I tested the following code today:
$star = "Aquarius";
$star = 11;
While debugging, I observed that $star simply changes from string type to integer type. I was amazed by this functionality. In C++ for instance, this is just impossible, but in c# I considered the var variable but it's not the same.
For instance you can't do:
var dynamic = "Hello";
dynamic = 3;
I began to wonder what exactly happens at the point when I basically say $star = 11. My guess is that $star is simply reinitialized since it's being directly assigned to (but this seems weird since the interpreter already knows that a variable $star has been declared earlier). Can anyone help with some clear or official source-backed explanation?
Thanks.
In C/C++ the type is defined at compile time because of the kinds of optimization that can occur based on it.
In C# the compiler infers the type based on the context and in the compilers brain it substitutes the var keyword for the type. This is why you can not change the type after the compiler made the initial inference.
In scripting languages like PHP a variable is an entry into a Hash Map (Associative Array, a Symbol Table). This defines the namespace (and scope). The actual value part is a generic object type that stores both the value and the type.
PHP is a dynamic language, similar in spirit to Perl, Ruby, Python, or many others. C++, on the other hand, is compiled and statically typed, requiring each variable to have a type defined at compile time.
Check the PHP docs for some great insight to PHP's dynamic typing implementation:
http://php.net/manual/en/language.types.type-juggling.php
PHP is a loosely typed language. PHP converts the variable to the correct data type, according to the value.
Check this out - http://php.net/manual/en/language.types.type-juggling.php
I haven't done much programing in many languages, but I know in C(++), you have to declare a variable type (int,char,etc).
In PHP you, of course, don't have to do that. You can start with $str = "something"; then later $str = array("something" => "smells"); and she is happy.
How does PHP compile? How does it know what the variable type is going to be? Does it even care?
This question has no relevance to anything I am doing. I am just curious.
EDIT.
I need to clarify this question a little bit.
In C, if I say:
int y;
It reserves x amount of bytes for y. If y overflows, bad news.
PHP doesn't have this nature (at least I don't think it does).
$i = "a number";
$i = 8;
$i = 1000000000000000000;
It's all the same to the language. How does it know how much to reserve? Or am I comparing Apples to Oranges? If I am going about this wrong, do you have any good topics that I can read to better understand?
Since you have C experience, consider a PHP variable to be like the following:
typedef struct {
int varType;
void* data;
} variable_t;
when you create a new variable, it will create a variable_t, give it a type tag (lets say 1 for int, 2 for string), and store it in a list somewhere (by scope, reference by name). The actual contents will be stored in *data. When the variable is again accessed, the type can be determined from int varType, and the appropiate action taken on void* data, such as using it as an int or string.
Imagine that the PHP snippet:
$data = 12;
$data2 = $data + 1;
$data = "Hello";
produces instructions like the following (pseudo-Cish):
Line 1:
variable_t* var = new_variable(TYPE_INT, data);
store_variable("data", var);
Line 2:
variable_t* var = get_variable("data2");
if (var->varType == TYPE_INT)
int value = 1 + *(int*)var->data);
else
error("Can't add non int");
var = new_variable(TYPE_INT, value);
store_variable("data2", var);
Line 3:
variable_t* var = get_variable("data");
if (var)
destroy_variable(var);
// Do like line 1, but for TYPE_STRING
This type of augmented data works in bytecoded, compiled, or direct interpreted languages.
There are more details in regards to different virtual machine implementations (local allocation, heap allocation, register VMs, etc). If you actually want to understand how virtual machines work, the best reference is Lua. Very clean language, very clean bytecode, and very clean virtual machine. PHP is probably the last implementation you should look at.
PHP doesn't really compile -- it is interpretted (into op-codes).
Pretty much if you try to do something on a certain data type that can't be done, it'll give you an error. There is no type checking.
It doesn't compile. It is an interpreted language, like Javascript.
I realize this is an old question but here is some more specific information on how PHP handles the questions asked by the OP.
This is the page from the PHP reference that you'd want to start with:
Introduction to Variables
I know linking isn't preferred but that link should be stable and I don't want to wholesale copy PHP reference documentation. Here are the highlights.
OP: How does PHP know what type of variables it uses (or does it)?
PHP is written in C and uses a C struct typedef which it calls a zval along with a C union typedef which is calls a zval_value to represent all variables.
typedef struct _zval_struct {
zvalue_value value; /* variable value */
zend_uint refcount__gc; /* reference counter */
zend_uchar type; /* value type */
zend_uchar is_ref__gc; /* reference flag */
} zval;
"The engine attempts to cover up the complexity of the concept of a variable that can be any type by providing a uniform and intuitive set of macros for accessing the structures various fields."
"PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting." Reference Counting and Copy-on-write (COW) are two powerful concepts PHP uses which I won't go into here but are worth reading about.
"Weak typing is implicit of the engine's preference to convert, or coerce variables into the required type at execution time. Reference counting is the means by which the engine can deduce when a variable no longer has any references in the users code, and so is able to free the structures associated with the variable."
"The zval_value is a union which can represent all types a variable may hold."
" ... a variable can be of one type, the variable data is represented by the appropriate field in the zval_value union. The zval itself holds the type, reference count and a flag to indicate if a variable is a reference."
How does PHP compile?
"Compile" is a broad word that can have different meanings and PHP doesn't compile in the traditional sense. It does do a sort of pre-compilation which converts the source code into opcodes which are instructions that can be executed by the processor. These opcodes are cached which prevents PHP from have to parse frequently called scripts.
How does it know what the variable type is going to be? Does it even care?
As already quoted above it is the PHP engine's "preference to convert, or coerce variables into the required type at execution time." Baiscally PHP does always store what it determines a variable's type to be when it's created but when a variable is referenced PHP makes another determination of what the type is based on the context in which it is being used.
"PHP is weakly typed, as such the engine provides API functions for converting variables from one type to another."
The engine has a set of macros it uses for working with the zvals to convert a variable's type so that you usually don't have to deal with that.
If you want to see what zvals look like in action they can be dumped with:
debug_zval_dump($variableName);
"How does PHP compile? How does it know what the variable type is going to be? Does it even care?
This question has no relevance to anything I am doing. I am just curious."
PHP is an interpreted language and it doesn't compile.
PHP doesn't know what type the variable is going to be, because the type of the variable is determined by the type of the value which was assigned last time to that variable.
You can do this:
$foo = 5;
var_dump($foo);
$foo = "5";
var_dump($foo);
$foo = array();
$foo[] = 0;
$foo[] = 1;
$foo[] = 2;
var_dump($foo);
As you can see, whenever a value is assigned to foo, the type might be changed.
PHP doesn't care about the type of your variable, because it's a programming language and it doesn't have feelings.
EDIT:
"Or am I comparing Apples to Oranges?"
Yes, you are. Here you can learn more about the language.
EDIT2:
PHP is a scripting language with an interpreter and without a compiler. This means that in PHP you can only get runtime errors. It's a liberal language if we consider types, because you have the right to do anything with your variables and their types will be modified according to the usage of them.
These links might be useful for you:
http://www.gidforums.com/t-11866.html
http://www.webmaster-talk.com/coding-forum/186350-fundamental-differences-between-php-c-c.html
Variable scope difference between PHP and C: block scope is not exactly the same?
Note, that PHP is executed on the server, if you want to create client events, Javascript is my suggestion.
PHP now supports type hinting, you can include things like 'string' or 'array' in function definitions that are caught as the scripts are parsed to indicate there is a type mismatch.
I am currently using SQL Server 2000 Stored Procedures with PHP. Following the PHP doc, I use mssql_bind to assign value of parameters and then execute the Stored Procedure.
The problem is that I got this bug which prevents me to bind empty strings to parameters (they are converted to NULL when the Stored Proc gets called)
I dont't want to have to convert every parameter inside the Stored Procedures to check if its NULL then convert back to an empty string. I want to be able to use empty strings as well as NULL which both have their own meaning.
Does anyone know a workaround for this in PHP ? PHP bugs website isn't very clear if that bug is fixed or when it will be fixed, I use PHP 5.2.11 (the lastest version from the 5.2 branch)
Assuming you do not want to do what you suggested, options left to you are
Download a cvs snapshot of php and install it if viable, see if it is fixed. If not viable or fixed via cvs then...
Use system() or exec() calls to use the stored procedures. If too much a hassle then...
Don't use stored procedures, do your functionality in php or other scripting code.
Alter the stored procedure to accept another value for '' strings and convert THAT to a '' string.
Do what you didn't want to do. Harsh :P But I do not see another way.
The bug #44325 proposed a patch to solve the problem, but it was not a correct solution, as it seems the problem is in ntwdblib.dll, and not in the code of the php_mssql extension.
See the comment from alexr at oplot dot com :
I'm sorry. This bug is not fixed. This
is a bug of the ntwdblib.dll. And
after latest updates the bug is
return.
When I bind a empty string, the stored
procedure received a chr(0) char
instead a empty string.
Please roll back last fixes. This bug
is irrecoverable.
Considering this, I'm not sure there's much that could be done on the PHP side :-(
Last time I worked with PHP+MSSQL on Windows, I had quite a lot of problems, like some quite similar to this one, actually ;-(
Maybe a possible solution, for you, might be to switch to the newer SQL Server Driver for PHP driver ? Note that is only works on Windows, though...
I personally don't have a MSSQL server available to test but have you tried using PDO instead of mssql directly?
PDOStatement->bindValue( mixed $parameter , mixed $value [, int $data_type ] )
bindValue()
Yes, I realize that PDO is only a wrapper but who knows, could work! :)
I have a solution that will work.
I am using ADODB (but that doesnt matter) and I have hacked the mssql driver (adodb-mssql.inc.php in the adodb5 drivers folder).
here is the code
if($var === ''){
//stupid hack to prevent mssql driver from converting empty strings to null. now they arent empty strings but they will get trimmed down to legth 0 ;-)
$var = ' ';
$type = SQLVARCHAR;
$isNull = false;
$maxLen = 0;
}
simply check if you are trying to bind an empty string and if you are change it to be non empty. it doesn't matter what value you use I just use a space.
make the type a sqlvarchar isnull should be false and now the trick is to make maxlen 0 so that the mssql driver will trim your string to an empty string.
those variables should get passsed to the mssql_bind function if that wasn't obvious.