Singleton is one of the most popular design patterns. Its purpose is to
ensure the existence of only one instance of a certain class while also
providing global access to it. Here is a brief example for completeness:
class Database
{
private static $instance;
private function __construct()
{}
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new self;
}
return self::$instance;
}
...
}
// singleton is globally accessible
$result = Database::getInstance()->query('...');
Typical features include:
- A private constructor, preventing the creation of an instance outside
the class
- A static property
$instance
where the unique instance
is stored
- A static method
getInstance()
, which provides access to the
instance and creates it on the first call (lazy loading)
Simple and easy to understand code that solves two problems of
object-oriented programming. Yet, in dibi or
Nette Framework, you won’t find any
singletons. Why?
Apparent Uniqueness
Let's look closely at the code – does it really ensure only one instance
exists? I’m afraid not:
$dolly = clone Database::getInstance();
// or
$dolly = unserialize(serialize(Database::getInstance()));
// or
class Dolly extends Database {}
$dolly = Dolly::getInstance();
There is a defense against this:
final public static function getInstance()
{
// final getInstance
}
final public function __clone()
{
throw new Exception('Clone is not allowed');
}
final public function __wakeup()
{
throw new Exception('Unserialization is not allowed');
}
The simplicity of implementing a singleton is gone. Worse – with every
additional singleton, we repeat the same piece of code. Moreover, the class
suddenly fulfills two completely different tasks: besides its original purpose,
it takes care of being quite single. Both are warning signals that something is
not right and the code deserves refactoring. Bear with me, I’ll get back to
this soon.
Global = Ugly?
Singletons provide a global access point to objects. There is no need to
constantly pass the reference around. However, critics argue that such a
technique is no different from using global variables, and those are
pure evil.
(If a method works with an object that was explicitly passed to it,
either as a parameter or as an object variable, I call it “wired
connection”. If it works with an object obtained through a global point (e.g.,
through a singleton), I call it “wireless connection”. Quite a nice
analogy, right?)
Critics are wrong in one respect – there is nothing inherently bad about
“global”. It’s important to realize that the name of each class and
method is nothing more than a global identifier. There is no fundamental
difference between the trouble-free construction $obj = new MyClass
and the criticized $obj = MyClass::getInstance()
. This is even less
significant in dynamic languages like PHP, where you can “write in PHP 5.3”
$obj = $class::getInstance()
.
However, what can cause headaches are:
- Hidden dependencies on global variables
- Unexpected use of “wireless connections”, which are not apparent from
the API of classes (see Singletons are
Pathological Liars)
The first issue can be eliminated if singletons do not act like global
variables, but rather as global functions or services. Consider google.com –
a nice example of a singleton as a global service. There is one instance (a
physical server farm somewhere in the USA) globally accessible through the
identifier www.google.com
. (Even clone www.google.com
does not work, as Microsoft discovered, they have it figured out.) Importantly,
this service does not have hidden dependencies typical for global variables –
it returns responses without unexpected connections to what someone else
searched for moments ago. On the other hand, the seemingly inconspicuous
function strtok suffers from a serious
dependency on a global variable, and its use can lead to very hard-to-detect
errors. In other words – the problem is not “globality”, but design.
The second point is purely a matter of code design. It is not wrong to use a
“wireless connection” and access a global service, the mistake is doing it
unexpectedly. A programmer should know exactly which object uses which class.
A relatively clean solution is to have a variable in the object referring to
the service object, which initializes to the global service unless the
programmer decides otherwise (the convention over configuration technique).
Uniqueness May Be Harmful
Singletons come with a problem that we encounter no later than when testing
code. And that is the need to substitute a different, test object. Let's return
to Google as an exemplary singleton. We want to test an application that uses
it, but after a few hundred tests, Google starts protesting We're
sorry… and where are we? We are somewhere. The solution is to substitute
a fictitious (mock) service under the identifier www.google.com
. We
need to modify the hosts
file – but (back from the analogy to
the world of OOP) how to achieve this with singletons?
One option is to implement a static method
setInstance($mockObj)
. But oops! What exactly do you want to pass
to that method when no other instance, other than that one and only,
exists?
Any attempt to answer this question inevitably leads to the breakdown of
everything that makes a singleton a singleton.
If we remove the restrictions on the existence of only one instance, the
singleton stops being single and we are only addressing the need for a global
repository. Then the question arises, why repeat the same method
getInstance()
in the code and not move it to an extra class, into
some global registry?
Or we maintain the restrictions, only replacing the class identifier with an
interface (Database
→ IDatabase
), which raises the
problem of the impossibility to implement IDatabase::getInstance()
and the solution again is a global registry.
A few paragraphs above, I promised to return to the issue of repetitive
code in all singletons and possible refactoring. As you can see, the problem has
resolved itself. The singleton has died.
Twitter for PHP is a very small and easy-to-use library for
sending messages to Twitter and receiving status updates with OAuth support.
Download Twitter for PHP 3.5
It requires PHP (version 5 or newer) with CURL extension and is licensed
under the New BSD License. You can obtain the latest version from our GitHub repository or install it via
Composer:
php composer.phar require dg/twitter-php
Twitter requires SSL/TLS as of January 14th, 2014. Update to
the last version.
Getting started
Sign in to the http://twitter.com and
register an application from the http://dev.twitter.com/apps page.
Remember
to never reveal your consumer secrets. Click on My Access Token link from the
sidebar and retrieve your own access
token. Now you have consumer key, consumer secret, access token and access token
secret.
Create object using application and request/access keys:
$twitter = new Twitter($consumerKey, $consumerSecret,
$accessToken, $accessTokenSecret);
Posting
The send() method posts your status. The message must be encoded
in UTF-8:
$twitter->send('I am fine today.');
You can append picture:
$twitter->send('This is my photo', $imageFile);
Displaying
The load() method returns the 20 most recent status updates posted in the
last 24 hours by you:
$statuses = $twitter->load(Twitter::ME);
or posted by you and your friends:
$statuses = $twitter->load(Twitter::ME_AND_FRIENDS);
or most recent mentions for you:
$statuses = $twitter->load(Twitter::REPLIES);
Extracting the information from the channel is easy:
<ul>
<?php foreach ($statuses as $status): ?>
<li><a href="http://twitter.com/<?= $status->user->screen_name ?>">
<?= htmlspecialchars($status->user->name) ?></a>:
<?= Twitter::clickable($status) ?>
<small>at <?= date("j.n.Y H:m", strtotime($status->created_at)) ?></small>
</li>
<?php endforeach ?>
</ul>
The static method Twitter::clickable()
makes links in status
clickable. In addition to regular links, it links @username
to the
user’s Twitter profile page and links hashtags to a Twitter search on that
hashtag.
Searching
The search()
method provides searching in twitter statuses:
$results = $twitter->search('#nette');
The returned result is a again array of statuses.
Error handling
All methods throw a TwitterException on error:
try {
$statuses = $twitter->load(Twitter::ME);
} catch (TwitterException $e) {
echo "Error: ", $e->getMessage();
}
Additional features
The authenticate()
method tests if user credentials
are valid:
if (!$twitter->authenticate()) {
die('Invalid name or password');
}
Other commands
You can use all commands defined by Twitter API 1.1. For example GET
statuses/retweets_of_me returns the array of most recent tweets authored by
the authenticating user:
$statuses = $twitter->request('statuses/retweets_of_me', 'GET', array('count' => 20));
I recently participated in a discussion that reminded me
(again) of the deeply entrenched myths regarding the differences between HTML
and XHTML. The campaign for the formats with the letter “X” was accompanied
by great emotions, which usually do not go hand in hand with a clear head.
Although the enthusiasm has long since faded, a significant part of the
professional community and authors still believe a number of misconceptions.
In this article, I will attempt to bury the biggest of these myths in the
following way. This article will contain only facts. I will save my
opinions and your comments for a second article.
In the text below, by HTML I mean the version HTML 4.01, and by XHTML I mean the
version XHTML 1.0 Second Edition.
For completeness, I add that HTML is an application of the SGML
language, while XHTML is an application of the XML language.
Myth: HTML allows tag crossing
Not at all. Tag crossing is directly prohibited in SGML, and consequently in
HTML. This fact is mentioned, for example, in the W3C recommendation:
“…overlapping is illegal in SGML…”. All these markup languages
perceive the document as a tree structure, and therefore it is not possible to
cross tags.
I am also responding to a reformulation of the myth: “The advantage of
XHTML is the prohibition of crossing tags.” This is not the case; tags cannot
be crossed in any existing version of HTML or XHTML.
Myth:
XHTML banned presentation elements and introduced CSS
Not at all. XHTML contains the same sort of elements as HTML 4.01. This is
mentioned right in the first
paragraph of the XHTML specification: “The meaning of elements and
their attributes is defined in the W3C recommendation for HTML 4.” From
this perspective, there is no difference between XHTML and HTML.
Some elements and attributes were deprecated already in HTML
4.01. Presentation elements are forbidden in favor of CSS, which also
answers the second part of the myth: the arrival of cascading styles with XHTML
is unrelated, having occurred earlier.
Myth: HTML parser must
guess tag endings
Not at all. In HTML, for a defined group of
elements, the ending or starting tag can optionally be omitted. This is for
elements where omitting the tag cannot cause ambiguity. As an example,
take the ending tag for the p
element. Since the standard states
that a paragraph cannot be inside another paragraph, it is clear by
writing…
<p>....
<p>....
…that by opening the second paragraph, the first must close. Therefore,
stating the ending tag is redundant. However, for example, the div
element can be nested within itself, so both the starting and ending tags are
required.
Myth: HTML attribute
notation is ambiguous
Not at all. XHTML always requires enclosing attribute values in quotes or
apostrophes. HTML also requires
this, except if the value consists of an alphanumeric string. For
completeness, I add that even in these cases, the specification recommends
using quotes.
Thus, in HTML it is permissible to write
<textarea cols=20 rows=30>
, which is formally as unambiguous
as <textarea cols="20" rows="30">
. If the value contained
multiple words, HTML insists on using quotes.
Myth: HTML document is
ambiguous
Not at all. The reasons given for ambiguity are either the possibility of
crossing tags, ambiguity in writing attributes without quotes, which are already
debunked myths, or also the possibility of omitting some tags. Here I repeat
that the group of elements where tags can be omitted is chosen so as to omit
only redundant information.
Thus, an HTML document is always unambiguously determined.
Myth: Only in XHTML
is the ‘&’ character written as ‘&’
Not at all – it must also be written that way in HTML. For both languages,
the characters <
and &
have a specific meaning.
The first opens a tag and the second an entity. To prevent them from being
understood in their meta-meaning, they must be written as an entity. Thus also
in HTML, as stated by the specification.
Myth: HTML
allows ‘messes’ that would not pass in XHTML
Not at all. This view is rooted in a series of myths that I have already
refuted above. I haven't yet mentioned that XHTML, unlike HTML, is case
sensitive for element and attribute names. However, this is a completely
legitimate feature of the language. In this way, Visual Basic differs from C#,
and it cannot objectively be said that one or the other approach is worse. HTML
code can be made confusing by inappropriately mixing upper and lower case
(<tAbLe>
), XML code can also be confusing by using strings
like id
, ID
, Id
for different
attributes.
The clarity of the notation in no way relates to the choice of one language
over the other.
Myth: Parsing XHTML is much
easier
Not at all. Comparing them would be subjective and therefore has no place in
this article, but objectively, there is no reason why one parser should have a
significantly easier time. Each has its own set of challenges.
Parsing HTML is conditioned by the fact that the parser must know the
document type definition. The first reason is the existence of optional tags.
Although their addition is unambiguous (see above) and algorithmically easy to
handle, the parser must know the respective definition. The second reason
concerns empty elements. That an element is empty is known to the parser only
from the definition.
Parsing XHTML is complicated by the fact that the document can (unlike HTML)
contain an internal subset DTD with the definition of its own entities (see example). I add that
an “entity” does not have to represent a single character, but any lengthy
segment of XHTML code (possibly containing further entities). Without processing
the DTD and verifying its correctness, we cannot talk about parsing XHTML.
Furthermore, syntactically, DTD is essentially the opposite of XML language.
In summary: both HTML and XHTML parsers must know the document type
definition. The XHTML parser additionally must be able to read it in DTD
language.
Myth: Parsing XHTML is much
faster
In terms of the syntactic similarity of both languages, the speed of parsing
is only determined by the skill of the programmers of the individual parsers.
The time required for machine processing of a typical web page (whether HTML or
XHTML) on a regular computer is imperceptible to human perception.
Myth: HTML parser must always
cope
Not at all. The HTML specification does
not dictate how an application should behave in case of processing an
erroneous document. Due to competitive pressures in the real world, browsers
have become completely tolerant of faulty HTML documents.
It is different in the case of XHTML. The specification, by referring to XML
dictates
that the parser must not continue processing the logical structure of the
document in case of an error. Again, due to competitive pressures in the real
world, RSS readers have become tolerant of faulty XML documents (RSS is an
application of XML, just like XHTML).
If we were to deduce something negative about HTML from the tolerance of web
browsers, then we must necessarily deduce something negative about XML from
the tolerance of RSS readers. Objectively, the draconian approach
of XML to errors in documents is utopian.
Conclusion?
If your mind is no longer burdened by any of the myths mentioned above, you
can better perceive the difference between HTML and XHTML. Or rather, you can
better perceive that there is no difference. The real difference occurs a level
higher: it is the departure from SGML and the transition to the new XML.
Unfortunately, it cannot be said that XML only solves the problems of SGML
and adds no new ones. I have encountered two in this article alone. One of them
is the draconian processing of errors in XML, which is not in line with
practice, and the other is the existence of a different DTD language inside XML,
which complicates parsing and the understandability of XML documents. Moreover,
the expressive capability of this language is so small that it cannot formally
cover even XHTML itself, so some features must be defined separately. For a
language not bound by historical shackles, this is a sad and striking finding.
However, criticism of XML is a topic for a separate article.
(If I encounter more myths, I will gradually update the article. If you
want to refer to them, you can take advantage of the fact that each headline has
its own ID)
As you might know, web forms have to by styled with care, since
their native look often is the best you can achieve.
That said, sometimes even default look has its bugs. A truly flagrant
mistake concerns buttons in Internet Explorer (including version 7) in Windows
XP. If the button's caption is too long, the browser produces such a
nasty thing:
…pokračování
Texy2 is a huge leap forward. More perfect, cleverer, highly
customizable. And above all – even more sexy! Web application developers can
chuckle in contentment.
Initially, Texy2 wasn’t even supposed to be released. But let's not get
ahead of ourselves…
How Software Is Designed
The best analysis of a program is done by programming it. Only then do you
realize what you really need from it. And only then can you write it
perfectly.
I was aware of this while writing Texy 1. I didn’t want to write API
documentation, I didn’t translate the website into other languages. I knew
that was just a rehearsal for the real Texy.
The first version was a labor because I had to crack a ton of nuts. Figure
out how to even do it. It’s not a joke. For instance, you might say:
“Texy will insert non-breaking spaces between a preposition and a word.” And
one might think a regular expression that finds v lese
and replaces
it with v lese
would suffice.
But, can it handle this too:
v <strong>lese</strong>
? Yes, a non-breaking space
belongs there too. Why wouldn’t it? Should we filter strings in angle
brackets? Okay, but what about this input:
v <span title="3 > 2">lese</span>
You'd suggest more cunning HTML tag filtering? Wait, but if there’s a
<br>
tag, then the non-breaking space shouldn’t be there.
So no filtering, but analysis instead.
Or… or just consider this! 🙂
v <span title="les > obora">  
<!-- hehe --></span>   lese
It’s still about the letter v
followed by a space and the
word lese
. Now, just try to design that regular expression in rough
outline ;)
Texy2 of course can do it. And
that's just one of thousands of features.
However, the precision of conversion is not the main attraction of Texy2.
Nope, that’s just a manifestation of maturing older ideas. The real bombshell
is the maximum customizability.
Texy is Flexible and Billable
Now you can easily change the behavior of any document element. Need to build
a wiki over Texy2? I.e., control all the links on the page? It took me just a
few lines of code.
Need to generate content based on headings? Want to insert flash animations
using [* movie.swf *]
? Want to automatically add a CSS class to all
phrases "hello .(description)"
? You can! And extremely easily.
Some solutions are found directly in the distribution, but mostly in the
documentation, which is not yet available 🙂 At least there’s a brief changelog. I’m sorry, I have such
important tasks now that there’s no time to write the manual. However, the
Texy website is now designed so that creating documentation does not have to
depend only on me.
Texy2 is Here
Texy2 wasn’t meant to be released. I realized that I had no motivation to
release my software as open source. It comes with many limitations, in the comfort zone you won’t find
(i.e., in the Czech Republic), everyone bothers with support, you encounter idiots.
If it weren’t for the Giraffe & co. at the last HBWBH, I would’ve
probably kept it to myself.
The revision released today with the beautiful number 111 is the
first official beta version of Texy2. Download it, play around, test it.
PHP 5.2.0 comes with a new DOM function named
registerNodeClass()
. What is it good for? The documentation says
nothing as well as uncle Google. But this function is really great!
…pokračování
I recently managed to speed up a PHP script to a hundredth of
its original execution time by changing just a few characters in the source
code. How is this possible? The drastic acceleration is due to the appropriate
use of references and assignments. I'll let you in on how it works. Don't
believe the sensational headline; it's not any kind of black magic. I repeat,
you just need to understand how PHP works internally. But don’t worry,
it's nothing too complicated.
In-depth Reference Counting
The PHP core stores variable names separately from their values in memory. An
anonymous value is described by the structure [zval.
Besides raw data, it includes information about the type (boolean, string, etc.)
and two additional items: refcount
and is_ref
. Yes,
refcount
is exactly the counter for the aforementioned reference
counting.
$abc = 'La Trine';
What does this code actually do? It creates a new zval
value in
memory, whose data section holds the 8 characters La Trine
and
indicates the type as a string. At the same time, a new entry abc
is added to the variable table, referring to this zval
.
Additionally, in the zval
structure, we initialize the
refcount
counter to one, because there is exactly one variable
($abc
) pointing to it.
…pokračování
For some, this is obvious, for me, it's mainly a cheat sheet.
I just can't remember extremely long numbers, meaning those that have more than
one digit.
In PHP, redirection is implemented with the following code:
$code = 301; // code in the range 300..307
$url = 'http://example.com';
header('Location: ' . $url, true, $code);
die('Please <a href="' . htmlSpecialChars($url) . '">click here</a> to continue.');
Note that after calling the header()
command, it is necessary to
explicitly terminate the script. It doesn't hurt to offer a text message and a
link for agents that do not automatically redirect.
Types of Redirection
The meanings of individual codes are described in detail in the standard RFC 2616:
HTTP/1.1 Redirection. Here they are:
300 Multiple Choices
There are several URLs to which redirection is possible (pages may differ,
for example, in language). Offer users a list of these. The preferred
destination can be indicated in the Location
header; not every
browser automatically redirects. Rarely used.
301 Moved Permanently
Use this when a resource that used to exist at the requested URL is now
(permanently) located at a new address. Specify this in the
Location
header. However, if it has been discontinued, announce
this with the code 410 Gone.
302 Found
A problematic code. It indicates that the resource has been temporarily
moved elsewhere and the browser should access the new URL using the same method
(GET, POST, HEAD, …) as used on the original. Additionally, with methods other
than GET and HEAD, user confirmation should be required for the redirection.
Most browsers, however, do not respect this and change the method to GET without
requiring confirmation.
The code is often mistakenly used instead of 303.
303 See Other – for PRG
The Post/Redirect/Get
technique prevents double submission of forms upon page reload or back button
click. After submitting a form using the POST method, a redirection is made
using the GET method to another page. This is exactly what the 303 code is for,
converting POST to GET.
304 Not Modified
For caching purposes. It responds to the If-Modified-Since
header that the resource has not changed since the previous visit. The response
must not contain a body, only headers.
307 Temporary Redirect
As mentioned, code 302 has become problematic due to non-compliance with the
standard by both web designers and browser creators. Code 307 is its
reincarnation, which mostly works correctly. It can be used, for example, to
perform a redirection using the POST method with transferred data.
This articles is actually an answer to e-mail by Honza Bien, who was asking
me about the manipulations I was
doing with conditional coments. Say, generally accepted idea is, that one
kind of a comments (downlevel-hidden) is valid and the other
(downlevel-revealed) is not. I tried to adapt those invalid comments the way
that they would be valid. I'll explain the whole sequence.
…pokračování
Although flash is the most spread active element of webpages, a
lot of designers still don't know the correct way to insert it into HTML
document.. The standard concept, advertised by Macromedia is absolutely
unusable.
…pokračování