Blog
All posts (105)
Pages:
< Previous 1–10 11–20 21–30 31–40 41–50 51–60 61–70 71–80 81–90 91–100 101–110 Next >
Ordering:
Ascending Descending
91. Beta version of Safari for Windows released
2007-06-12 01:41:03 by Martynas Jusevičius
Today, Apple has released a public beta of Safari 3, which for the first time includes a version for Windows. It is now claimed to be the fastest browser on the market.
92. Denmark's national broadcaster digitizes archives
2007-06-11 14:16:47 by Martynas Jusevičius
DR (Danmarks Radio), Denmark's national TV, radio, and online broadcaster, has announced a few days ago that it will digitize its archives and make them available for public.
A part of archives will be opened from January 1st, 2008. Before that, people will be able to express their wishes on the broadcaster's website as to what shows should be digitized first from the 30-kilometer-long shelves. Examples include children programs, drama classics, and documentaries. DR plans launch of custom, specialized digital TV and radio channels based on the archival content.
According to DR, it is the first decision of this kind in the world. With the help of new technologies, it is going to make access to nation's cultural heritage easier. However, there was no promise that the access will be totally open and unrestricted.
93. DIY tips: implementing search with Propel
2007-06-10 11:27:31 by Martynas Jusevičius
Implementing search functionality on your website has never been easier. Here is how we do it with the DIY Framework and Propel:
class SearchView extends XSLTView
{
function display(Request $request, Response $response)
{
$search = strip_tags($request->getAttribute("search-form")->getSearch());
$pageForm = new PageForm($request);
$offset = 0;
if ($pageForm->getOffset() != null) $offset = $pageForm->getOffset();
$limit = 10;
if ($pageForm->getLimit() != null) $limit = $pageForm->getLimit();
$desc = true;
if ($pageForm->getDesc() == "false") $desc = false;
$orderBy = 1;
$c = new Criteria();
$criterion = $c->getNewCriterion(PagePeer::TITLE, "%".$search."%", Criteria::LIKE);
$criterion->addOr($c->getNewCriterion(PagePeer::CONTENT, "%".$search."%", Criteria::LIKE));
$c->add($criterion);
$pageCount = PagePeer::doCount($c);
$c->setLimit($limit);
$c->setOffset($offset);
if ($desc)
{
$c->addDescendingOrderByColumn(PagePeer::DATETIME);
$c->addDescendingOrderByColumn(PagePeer::TITLE);
}
else
{
$c->addAscendingOrderByColumn(PagePeer::DATETIME);
$c->addAscendingOrderByColumn(PagePeer::TITLE);
}
$pages = PagePeer::doSelectJoinAll($c);
$this->proc->setParameter("", "total-item-count", $pageCount);
$this->proc->setParameter("", "offset", $offset);
$this->proc->setParameter("", "limit", $limit);
$this->proc->setParameter("", "desc", $desc);
$this->proc->setParameter("", "search-result", $request->getAttribute("search-result"));
if ($request->getAttribute("search-result") != null) $this->resolver->setArgument("search-form", XMLSerializer::serialize($request->getAttribute("search-form")));
$this->resolver->setArgument("pages", XMLSerializer::serialize($pages));
$this->template->load(ROOT_DIR."view/views/search/Search.xsl");
parent::display($request, $response);
}
}We get the search string $search and paging parameters such as $offset and $limit from forms. We then tell Propel to look for Pages (which we have defined as our Model class) in the database that match this search string either in their title or their content. First we check the total number of matches ($pageCount), and later retrieve the actual result ($pages) — a sorted array of Pages that should appear on the current search result page.
The rest of the code is just the usual View stuff — setting parameters and passing serialized objects to the XSLT processor, which renders them using an XSLT template into a nice XHTML page of search results when the parent::display($request, $response) is called.
94. Why XSLT is the perfect template engine
2007-06-09 12:20:29 by Martynas Jusevičius
Most of web application architectures these days include one or another kind of a template engine. The template engine applies various templates on data contents and produces various presentation outputs. Using templates, it is easy to achieve style standardization (a common look-and-feel) on the web site, separate concerns of programming and presentation design etc.
We use XSLT 1.0 stylesheets as templates and PHP's XSL extension as a template engine. XSLT is a language for transforming XML documents into other XML documents (not only, really). The engine on which the the transformations are run is usually called an XSLT processor.
For example, using 3 different templates, we produce XHTML, RSS, and Atom presentations from the same data contents.
There is a great variety of template engines, with Smarty being probably the most popular one for PHP. We argue however, that XSLT is the perfect template engine, and that is why we use it in our DIY Framework:
- It is a standard
- It is non-proprietary and platform-independent
- It can be used in a wider context than web templating, i. e. in XML processing in general
- It is a functional, Turing-complete language
- It is included by default in many platforms
- It readily includes many control structures, such as conditional statements/branches, sorting, and even file/HTTP access
- There is a great variety of XSLT processors. These are usually separate highly-optimized C or Java libraries and therefore very fast.
- Used correctly, it produces only well-formed XML (or XHTML, for that matter)
It is definitely worth learning XSLT instead of a proprietary template language that has yet another kind of syntax and a very narrow application.
Of course, it's easiest to use XSLT when you have your data contents already present in an XML format (e. g. stored in XML files or a native XML database). But even if they are not, it is worth to serialize them into XML and then enjoy all the benefits of XSLT.
95. State of Semantic Web tools in PHP
2007-06-08 11:22:08 by Martynas Jusevičius
We have been using RDF and SPARQL in several of our PHP projects. So far that is a hard thing to do, since there are few quality software tools for working with Semantic Web technologies in PHP.
We have used RAP (RDF API for PHP), a software package for parsing, querying, manipulating, serializing and serving RDF models, and ARC (Appmosphere RDF Classes), a lightweight, SPARQL-enabled RDF system.
RAP is feature-rich and tries to emulate some of Jena's API. It has
extensive object-oriented interfaces that allow manipulating RDF models from different perspectives.
However, RAP was just too buggy when we tried it. Especially its SPARQL interface, which was quite a new feature at that time. Moreover, RAP delivered unacceptable query times for quite simple SPARQL queries that we used. It is most likely related to its use of PHP objects instead of arrays and query processing in PHP rather than at the database level.
Another problem with RAP was that it was rarely updated. However, a new 0.9.5 version was released just a few days ago. It includes multiple bug fixes and a new SPARQL engine which they claim is much faster and supports all features of the W3C SPARQL recommendation. That looks promising and we will have to give RAP another try.
ARC is what we switched to from RAP and eventually contributed some bug fixes to. It takes another approach to SPARQL queries: it uses a technique to rewrite them into SQL. That way the expensive part of query processing takes place in the highly-optimized database. ARC does less validation and operates using lightweight PHP arrays as its data structures instead of objects.
ARC was really fast enough, but we soon encountered bugs in its SPARQL support as well. MySQL froze when too many UNION patterns where combined; variable bindings contained malformed values in UNION patterns with a different number of variables; language filtering was not fully suppported etc.
Moreover, ARC's array-based interfaces are quite clumsy. We had to implement a more object-oriented wrapper. Another problem is that it works on the RDF level only and lacks more advanced features such as OWL and inference support. And it seems like ARC is not being actively developed at the moment.
To conclude, there is still a lack of mature Semantic Web tools for PHP. We have tested only 2 of them which seemed to be the most promising, and they still have a way to go before they could be used in production environments. The reason for that may be that semantic technologies are still emerging. They are used in research but quite distant to the PHP community which is on the practical side of things.
It would be interesting to try some SW tool built as a PHP extension, but haven't come across any.
96. PHP wrappers to emulate Java Servlet API
2007-06-07 14:15:14 by Martynas Jusevičius
We had a goal to use only object-oriented PHP code in our DIY framework. However, this is hard to achieve when even the basic and probably the most used constructs in PHP such as $_GET or $_SESSION are not object-oriented in itself.
For that reason, we implemented lightweight object-oriented wrappers for these constructs with basic functionality. The interface design was taken from Java Servlet API. The classes are as follows:
- MultipartRequest
- Provides OO access to
$_FILES. API taken from Java's MultipartRequest. - Request
- Provides OO access to
$_GETand$_POST. API taken from Java's HttpServletRequest. - Response
- Provides OO access to headers and the
header()function. API taken from Java's HttpServletResponse. - Session
- Provides OO access to
$_SESSION. API taken from Java's HttpSession.
When you download the framework package, you will find the implementation in the controller/ folder and API documentation in docs/ folder.
97. Printer- and handheld-friendly websites with CSS media types
2007-06-06 19:27:09 by Martynas Jusevičius
Nowadays the web is accessed not only via computers, but through a range of various devices: handhelds, mobile phones, TVs and even game consoles. The websites are also being printed, projected on the screen, and read by voice synthesizers. Each of these media has its own specifics of presentation. You might want to have several different ways to render your website to give the user the most accessible experience.
Fortunately, you do not need to have different versions of your website like in the old days in order to achieve this. Here is where CSS comes to help. Using it, you can specify different style rules for different media types. This can be done in several ways:
- By placing links to CSS stylesheets with different media types in your (X)HTML code:
<link rel="stylesheet" type="text/css" media="print" href="print.css"/> <link rel="stylesheet" type="text/css" media="screen" href="screen.css"/> - By using the
@mediaCSS rule that defines a media type for a set of rules in the block it encloses. This approach allows rules for various media in the same style sheet.
We used the second approach to make our website printer-friendly and hide the elements that are not wanted in the printed version. The CSS code now looks like this:
/* Common rules */
html, body { font-family: "Verdana"; font-size: 10pt; }
/* Screen rules */
@media screen
{
body { margin: 0; }
/* ...more screen rules */
}
/* Print rules */
@media print
{
div#header, div#footer, div#right, p.comment-controls, p#paging { display: none; }
}98. DIY tips: reusing common templates
2007-06-06 11:45:06 by Martynas Jusevičius
You might end up in a situation where several different Views contain identical or similar templates in their XSLT stylesheets.
For example, we have a PostListView for a general list of blog posts, YearlyPostListView for a list of posts from a specific year, and MonthlyPostListView for a list of posts from a specific month. While these are 3 separate views with 3 separate stylesheets, they all have to produce the same XHTML snippet for blog archive links (placed on the right) and keep the same look-and-feel. And, of course, you don't want to keep 3 versions of code that is supposed to be identical and make changes several times in different files.
There is a fairly trivial solution to it — extract that common template and place it in a separate stylesheet that the Views could include.
We do it by creating a stylesheet called common.xsl and placing it in the views/ folder (not one of the specific View folders) next to master.xsl. The XSLT code for including it from the specific Views is simply <xsl:include href="../common.xsl"/>.
99. DIY tips: HTTP content negotiation
2007-06-05 18:16:08 by Martynas Jusevičius
Content negotiation is a mechanism defined in the HTTP specification that makes it possible to serve different versions of a document (or more generally, a resource) at the same URL, so that user agents can choose which version fit their capabilities the best [Wikipedia].
Negotiation is based on HTTP Accept headers that the clients send. It can be used for different things, such as determining client's language or locale, but we mainly use it to deliver our content with the right MIME content type. That is important when delivering XHTML since the correct content type for it is application/xhtml+xml while plain old HTML should be served with text/html.
These are the only 2 lines that do the negotiation in our XSLTView class. They serve the XHTML content type to clients that support it (Internet Explorer does not) or revert to HTML otherwise:
if (strstr($request->getHeader("HTTP_ACCEPT"), ContentType::XHTML_XML)) $response->setContentType(ContentType::XHTML_XML);
else $response->setContentType(ContentType::TEXT_HTML);100. DIY tips: Propel does a great job for Views
2007-06-05 10:52:27 by Martynas Jusevičius
You often want your views (especially those which list items) to do sorting, filtering, paging and that kind of things. Using Propel, you can achieve that by calling a few simple methods, without a single line of SQL!
Here is how our View class for listing blog posts looks like:
class PostListView extends XSLTView
{
function display(Request $request, Response $response)
{
$pageForm = new PageForm($request);
$offset = 0;
if ($pageForm->getOffset() != null) $offset = $pageForm->getOffset();
$limit = 10;
if ($pageForm->getLimit() != null) $limit = $pageForm->getLimit();
$desc = true;
if ($pageForm->getDesc() == "false") $desc = false;
$orderBy = 1;
$c = new Criteria();
$c->add(PagePeer::TYPE, PagePeer::CLASSKEY_POSTPAGE);
$postCount = PagePeer::doCount($c);
$c->setLimit($limit);
$c->setOffset($offset);
if ($desc)
{
$c->addDescendingOrderByColumn(PagePeer::DATETIME);
$c->addDescendingOrderByColumn(PagePeer::TITLE);
}
else
{
$c->addAscendingOrderByColumn(PagePeer::DATETIME);
$c->addAscendingOrderByColumn(PagePeer::TITLE);
}
$posts = PagePeer::doSelectJoinAll($c);
$this->proc->setParameter("", "total-item-count", $postCount);
$this->proc->setParameter("", "offset", $offset);
$this->proc->setParameter("", "limit", $limit);
$this->proc->setParameter("", "desc", $desc);
$this->resolver->setArgument("posts", XMLSerializer::serialize($posts));
$this->template->load(ROOT_DIR."view/views/postList/PostList.xsl");
parent::display($request, $response);
}
}The parameters are used for paging. offset specifies the number of posts to skip (i. e. the post number where the result should start at), limit specifies the number of posts in the result (on one page), and desc specifies whether it should be sorted in the descending order or not.
We just retrieve request parameters using a Form, pass them to Propel to do the sorting/filtering stuff (using Criteria and PagePeer classes), and then pass them to XSLT — that's it, the job is done.
Pages:
< Previous 1–10 11–20 21–30 31–40 41–50 51–60 61–70 71–80 81–90 91–100 101–110 Next >
Ordering:
Ascending Descending
