Call function on string literal - php

I am wondering whether it is possible to call functions on string literals (Like in Python) in PHP (Tried googling, but 90% sure my terminology is off).
Example python:
"test,1,2,3".split()
I want to achieve something like (In php psuedo code):
$result = "SELECT `db`.`table`.`field` FROM `db`.`table` WHERE 1"->query();
Currently I am doing this:
$result = MySql::query("SELECT `db`.`table`.`field` FROM `db`.`table` WHERE 1");
But I really like the simplicity of the middle example and was wondering if anything like that is possible in PHP, maybe by overriding the PHP string class?

The difference is that everything in Python (and similar OO languages) is an object, that's why even strings have "methods" and "properties". PHP isn't a full top-to-bottom OO language, strings are just primitive strings. Even if they were objects, a string probably wouldn't have methods pertaining to database queries, because that'd be quite weird OO design with terribly mixed responsibilities.

There's no real way to do what you're talking about
$result = "SELECT `db`.`table`.`field` FROM `db`.`table` WHERE 1"->query();
In this example, your string is just a string. You then try to reference it like an object. In this case, you would get a Fatal error because you're telling PHP to use an object where none exists.
The closest thing to what you describe is direct chaining, where you create an instance of the class and reference it in the same statement (available in PHP >= 5.4)
$class = (new Class())->function();

Related

What is a dereferencable scalar in PHP?

Recently, I was following this PHP talk See it on YouTube. There is a part about new features in PHP7 that is a really strange stuff for me (in "Uniform variable syntax" part of the talk), which wrote:
// support all operations on dereferencable scalars
// (not very useful)
"string"->toLower()
What is a dereferencable scalar? I know when I call a method on a non-object, for example:
echo "string"->toLower();
I'll get the following Error in PHP7:
Fatal Error: Uncaught Error: Call to a member function toLower() on string
Also, I cannot find a way to declare methods on strings (like something we see in JavaScript); as I know, there is no way to do it.
So, what is the code above saying? How can we do the stuff above? What is the use case for it? Saying it generally, what is "string"->toLower()?
(Editted) Note: While the PHP talks says it exists as of PHP 7.0, it seems to be a mistake by Mr. Lerdorf (it could be a rejected patch, for example).
Thanks in advance.
Short answer: this would be a syntax sugar.
Longer answer: This is a way to call functions with the syntax which aligns with the object syntax.
For example, an object (i.e. a class instance) could have a method called "length()". The invocation of this method would be expressed with the following "arrow" syntax:
$length = $myObject->length();
But, for example, to get a length of a string, you can't currently use the same syntax, because strings are not objects. Instead, you must put the variable name within the parentheses, as a parameter to the strlen function , i.e.:
$length = strlen($myString);
What you have mentioned is an idea to unify the syntax, i.e.
$length = $myString->strlen();
would be another possible syntax to call the strlen function. This would make operations on scalars (and arrays) syntactically closer to the objects' method calls.
Note that PHP doesn't support this syntax yet, as of 2018-09-14.

Javascript (Node.js) in PHP

Is there any project like PHP.js but in vice direction to provide PHP implementation of JS classes and functions? In particular Date, RegEx, String classes?
I found this class for String but I am looking for a more complete collection.
My consern is not about using or not using such thing, I just need such thing.
Today I found jsphp. It seems promising.
JavaScript for PHP (jsphp) is a pseudo-implementation of the ECMA 262
standard (JavaScript 8.5.1) for PHP 5.3+. It allows you to write code
in PHP as if it were JavaScript, using the standard API and the
dynamic attributes available in the language, such as prototype
inheritence and chaining, first-class functions, and other
object-orientated features. It includes JSBoolean, JSNumber, JSString,
JSObject, JSArray, JSFunction, JSRegExp, JSDate, JSError and JSMath,
as well as the global helper functions, such as parseInt or isNaN.
The syntax in jsphp is very similar to a native implementation, although adapted to the syntax of PHP. For example, the variables are
prepended by a "$", the Object access opertaor is "->", and Strings
are concatenated using a ".".
$myString = new JSString( 'Hello World' );
$myString = $myString->split( '' )->reverse()->join( '' );
print( 'Reversed: ' . $myString ); // dlroW olleH
There is not - and there can not be - somehting like you ask for.
Javascript has a special syntax for regular expressions, something PHP could not take.
Similar how "object" methods in javascript are invoked. And the scope of variables is different. So this would not work.
Instead use the PHP functions. If they are not complete or useable enough for you, wrap them into objects so you can create an interface you like. Or use one of the many libraries that are available.

What is the purpose of the printf() function in PHP?

This may seem like a really daft question, but what is the reason for the existence of the printf() function in PHP?
It seems to me that that using echo will achieve the exact same results, with the added bonus that you don't get confused if you have several variables being output on one line (true, you can use %1$s as opposed to just %s, but it can still get messey with a few variables all being declared).
I know you can also define the type of the variable, without the need to amend it before outputting the string, but to me that doesn't seem like enough to warrent creating a function.
Maybe I'm wrong, maybe I'm missing something obvious, but if someone can help me to understand why it exists (so that I know whether or not I should really be using it!) I'd appriciate it. Thanks.
echo is language construct, printf is a function. It means that so you won't be able to use echo in the same way as printf.
IT'S NOT JUST PERSONAL TASTE
Take a look to the manual pages for both functions:
echo: http://php.net/manual/en/function.echo.php
printf: http://php.net/manual/en/function.printf.php
This topic is discussed there, for example, you cannot call echo with variable functions. Moreover the way they get and manage the input is different. If you do not need the parameters FORMATTING provided by printf you should use echo (it's slightly faster).
Examples
I insist again on some keywords: formatting and function.
The use of printf isn't to concatenate strings or to build a string from placeholders but to do it with custom formatting (possibly from configuration, user inputs or whatever else).
I write some code to explain what I mean (original source in the links I posted).
This code is not valid, echo is not a function so it won't return the printed value (you may use print or sprintf for this but print does not provide string concatenation).
($some_var) ? echo 'true' : echo 'false';
Following code prints a formatted string, in this case the format comes from a literal variable but it may comes from (for example) a GET request or whatever else. Can you rewrite it with echo and the formatting string taken from the configuration?
%format = "%'.-15.15s%'.6.6s\n";
printf($format, $heading1, $value1);
printf() is a port of C's printf() function, so people who got a background writing C code are more familiar with the syntax and will prefer it.
However, most people who start with PHP find it rather confusing.
For comparison:
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
mysql_real_escape_string($user),
mysql_real_escape_string($password));
(I used sprintf(), which is the same as printf but it won't actually print the string, it just returns it)
$query = "SELECT * FROM users WHERE user='" . mysql_real_escape_string($user) . "' AND password='" . mysql_real_escape_string($password) . "'";
It's just a matter of preference!
This is about separating static string and formatting, and data.
This separation is encouraged in every programming language that I know of because:
intent of programmer is clearer and enforced
intent is clear: When you read this you know what type is awaited for each field:
printf("a: %.2f, b: %s, c: %d", $a, $b, $c)
intent is enforced: silly type errors are limited (as for the security concerns).
it's more secure
Because it limits silly injection of unexpected meta-strings:
$avg = 3.1415;
// $avg = '3</td>pawned!';
printf("average: %.2f", $avg);
It's much worse in SQL...
usually much easier to read
Appart than you have more clues to the intent of the writer, the string
is clearly in one unique clear block. Data are cleanly listed one by one
after. You don't overuse things like ", . all over the place.
it's very powerfull
I'm curious to see how you would do the following without printf:
printf("%.2f %5d", $v1, $v2);
it's some sort of standard of programming
A lot of other programming languages (C, C++, Java, Python, Bash...) will have
similar printf format and way to treat strings.
So its good for you to know it, and for those who already know, it's easier.
And as a consequence there are plenty of docs and tutorials everywhere on the
subject, and a wikipedia page for it: print format string
The strings can be separated from your data automatically
And this means it's available for translation or syntax correction.
You'll find similar concerns with:
prepared statements in mysql that are now enforced with mysql_query being
deprecated in php 5.5 in favor for prepared statements.
All templating language: where you have the template usually in a different langage,
and the data the other side to render the template.
The more general topic is covered on wikipedia: string interpolation
A last precision:
echo does nothing more than outputing a string. And printf does string interpolation, and outputs a string.
So to be fair, we are here comparing building string via string concatenation vs string interpolation. As there's nothing wrong to output a string with echo. So this is not about echo but how you make your string. You are doing string interpolation even when using echo like this:
echo sprintf("avg: %.3f", $avg);
But then, well there are no more difference between this last form and:
printf("avg: %.3f", $avg);
printf probably exists because PHP was created in C, and printf is traditionally used to output formatted strings in C. printf can actually do a lot more than echo because it can output variables in a variety of formats including decimals to certain places and probably a lot more.
That being said, you can do anything that printf can do with some combination of PHP functions, and it may make more sense depending upon your background.
I'll just explain what I did so you get a clear difference, I'm not a PHP Pro, so maybe I'm wrong and there is a better or easier approach, and also my example may be not so useful to you as well.
I pass each string I want to translate to a function, and it returns the translated string, based on source string and current language, this way it would translate:
"The cat has %d kittens." (english) <=> "Katua %d kume ditu." (euskera)
The fact is that the splitted string for the echo couldn't be translated, as the part previous to the number is not the same for every language, so it must be translated as a "single entity".
It's legacy from C inherited by the PHP language
function http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/
printf takes input differently: you can provide a format string and then list all the required input (just like in C/C++).
'echo' and 'print' only take strings and are easier to use.
Your wish, Your style :)
NOT THAT:
as Others have said echo is a language construct and printf is a real function,
You can do lot with printf.
People coming from C/C++ background know a lot of format strings like %f, %d, %.2f and what not !!!!!
They would prefer printf to echo for this scenario as these floating point precison format and others will be at their finger-tips.
They wd prefer these over PHP's inbuilt format functions.

Database class in PHP; only has one function - question about practices and whether it's a good idea

So I have this database class in PHP and I only have 1 function in it (other than __construct and __destruct. Let me explain further...
I had originally written it so when I connected to a database I would just call my function connect_to_db() which returned a mysqli object. I then used this objects functions (->query(), ->prepare(), ->bind_param(), et cetera..) to do whatever. This cluttered (and still is as I haven't switched my code over to my new class yet) with a lot of functions that just do specific things, for example:
function get_country_info($db, $usrid) {
$statement = "select `name`, `population`, `money`, `food` from `countries` where `usr_id` = ?";
$qry = $db->prepare($statement) or
trigger_error("get_country_info():statement failed...");
$qry->bind_param("i", $usrid);
$qry->execute();
$qry->bind_result($name, $population, $money, $food);
$qry->fetch();
$res = array("name" => $name,
"pop" => $population,
"money" => $money,
"food" => $food);
return $res;
}
And what I originally planned to do was just to throw these into a class for clarity, but what I actually ended up doing was creating a class that when created creates a mysqli object for a specific database (supplied via an argument) and when destroyed closes off this link. I very much like not having to worry about typing $db->close(); as when the script finishes executing the connection is closed.
It only has 1 other function; query(). This function can handle any query put forth and outputs it as a multidimensional array. It uses eval(). From what I understand this is generally frowned upon - but eval() is so useful; so why is it frowned upon?
I guess the function may be slow, but seen as I'm just using it for a pet project (browser based country management game) and I haven't noticed anything I'm not worried about that at all. What I am worried about is whether people would generally do this in the 'real world' or whether there is some sort of standard by which people do this, or perhaps something included (or add-on-able) in PHP which is usually used?
I'm self taught, so sometimes I don't really know the best way to go about doing things. Perhaps somebody could advise me here?
The function in question can be seen here: http://pastebin.org/353721, as its ~60 lines and I don't want to clutter the page. I also haven't extensively tested it (I don't even know what unit tests are, so I test by using the function in a lot of different ways) so it may have problems I'm not aware of that you guys can point out.
Thanks.
Doesn't seem to me too bad. You have basically done a really basic wrapper around the database, and you performed the very first step in database independence, which is good.
This can be good for small and well organized projects, but once you will start going more complicated, you will soon notice that your approach has one large disadvantage: you still have your SQL queries split around the site. The day you will change anything in the database, you'll need to go through all your site and look for all the SQL statements: this is bad (I had to do it once...).
You should now move all the SQL code to one place. So there are various options. In a similar context, I made the query() method protected, then made the Db class "abstract" and subclassed it. Each subclass is a class which contains several methods relative to a specific set of tables, and this is the only place where you find SQL. All the rest of the project can only call these methods.
Or, even better, you could use an ORM (oblect relational mapper) which would map each table to an object.
For what concerns the evils of evals: I never used them. But I thought I wasn't going to use a "goto" because it's evil, and then I found the magic place where that was the perfect fit. So, if you have investigated all the possibilities, and you think that's the optimal solution... use it.
Instead of eval, you can use call_user_func() or call_user_func_array().
You should check the return value of execute().
Your function does not support subselects which contain multiple comma's, but only return one value.
You can use trim() instead of ltrim(rtrim()).
I would still use a function like get_country_info() on top of this db class. Often, you want to do something with the data before your application can use it. More importantly, you want to abstract the data storage from your application. That is, the method which uses the country info does not need to know that it came from the database.
As Techpriester wrote: brake it down into smaller parts.
I recommend at least:
the argument to bind converter
the single and multi param bind if-else branch
the sql statement parser (find out about returned fields)
One other approach to your problem would be to build the sql statement inside your query class (arguments would be field names, the table, the where constraints,... ) and to develop subclasses for different query types. This would elimiate the need to parse the statement.
Above this layer you would put a bunch of DAO classes to do the actual work.
But wait: others have done this... (maybe a lot of others to be specific). So using PDO, Doctrine, Propel or even a bigger library like ZendFramework (active record pattern there...) would be the most valuable and stable option.
If you, however, want to learn something about software architecture and OO Systems. Go ahead and build your own, if you do it well you can switch to another DB Layer as soon as your system grows (Version 2.x :-) ).
First: The eval() in your function doesn't serve any purpose as I see it. Why don't you call the $qry->... things directly?
Second, your function is way to complex. Brake it down into smaller parts that call each other.
Third: Manipulating SQL Statements is generally a very bad idea. It's error prone as soon as you feed your function with something like nested statements or other more complicated SQL code. So just don't do it.
Fourth: I wouldn't recommend using mysqli anymore. You should switch to PDO.
As I understand it, your function tries to find out, what fields were in the SELECT clause of the query to build the result array. That is only necessary if you want to allow your database layer it to execute arbitrary queries which is also not a good idea.
When I have to use classic SQL in an application, I predefine every query that I need in some method or function. That function then will know exactly what field it has to read from the result set. So there's no need to parse the SQL code. However, mostly I try to avoid SQL by using things like Doctrine ORM. SQL is just too prone to errors...
About eval(): It is entirely and absolutely evil for several reasons:
It may open the door to code injection.
It makes code unreadable to humans and unparsable to an IDE
It's nearly impossible to debug code that uses eval()
Not really a problem of eval() itself, but when you have to use it, that's a sign of a flawed design.
To your question - you need some experience to learn why there are "best practices", why eval() is deprecated, why people use prepared statements etc.
I'd recommend you to have a look at http://dibiphp.com/cs/ for a nice and concise DB layer for PHP.
You could also try Java when you get some clue about web technologies.
Then you can use cool things like iBatis, which almost got it to PHP
I personally once had a lib for DB, which was used like this:
$aasAreas = Array();
$sSQL = "SELECT id, x, y, x2 AS r, popis FROM ".$oFW->GetOption('tables.areas')
." WHERE id_ad=".asq((int)$_GET['id']);
$oRes = $oFW->GetDB()->Select($sSQL);
if(!$oRes || !$oRes->IsOk()){ $sError = $oRes->GetError(); break; }
else while( $a = $oRes->FetchRow() ){
$aasAreas[] = $a;
}
[OT] And some ORM for PHP attempt, used like this:
// Load by ID
echo "<h3>Load by ID</h3>";
$iID = 1;
echo "<pre>\$oObject = \$oOP->LoadObjectById(".$oClass->GetName().", $iID);</pre>";
$oUser = $oOP->LoadObjectById($oClass, $iID);
echo "<pre>oUser: [".gettype($oUser)."]".AdjustedPrintR($oUser)."</pre>";
echo "<div>GetPoolCount(): ".$oOP->GetPoolCount()."</div>";
// Save
echo "<h3>Save</h3>";
$oUser = new cObjectPersistenceTestClass_User();
$oUser->SetId(1);
$oUser->SetProperty('user', 'as'.rand());
$oUser->SetProperty('pass', 'as');
$oUser->SetProperty('fname', 'Astar');
$oUser->SetProperty('lname', 'Seran');
echo "<pre>oUser: [".gettype($oUser)."]".AdjustedPrintR($oUser)."</pre>";
$bSucc = $oOP->SaveObject($oUser);
echo "<div>".($bSucc ? 'saved' : 'error')."</div>";
// Load by value - load object created above -> Object Pool hit
$xVal = $oUser->GetProperty('user');
$aoUsers = $oOP->LoadObjectsByValue($oClass, 'user', $xVal);
echo "<pre>\$aoUsers: [".gettype($aoUsers)."]".AdjustedPrintR($aoUsers)."</pre>";
etc.

Problem with PHP Array

Why is it not possible to do something equivalent to this in PHP:
(Array(0))[0];
This is just for sake of argument, but it seems strange it does not allow access of anonymous objects. I would have to do something like the following:
$array = Array(0);
$array[0];
Any ideas why this is the behavior of PHP?
I read something somewhat detailed about this once and I regret not bookmarking it because it was quite insightful. However, it's something along the lines of
"Because the array does not exist in memory until the current statement (line) executes in full (a semicolon is reached)"
So, basically, you're only defining the array - it's not actually created and readable/accessible until the next line.
I hope this somewhat accurately sums up what I only vaguely remember reading many months ago.
This language feature hasn’t been inplemented yet but will come in PHP 6.
I guess the short answer is: nobody has coded it yet. I've used (and loved) that syntax in both Python and Javascript, but still we wait for PHP.
The main reason is because unlike some languages like Python and JavaScript, Array() (or in fact array()) is not an object, but an language construct which creates an inbuilt data type.
Inbuilt datatypes themselves aren't objects either, and the array() construct doesn't return a reference to the "object" but the actual value itself when can then be assigned to a variable.

Categories