Last days I’ve been working within a Phonegap project for Android devices using Push Notifications. The idea is simple. We need to use the Push Notification Plugin for Android. First we need to register the Google Cloud Messaging for Android service at Google’s console, and then we can send Push notifications to our Android device.
The Push Notification plugin provides a simple example to send notifications using Ruby. Normally my backend is built with PHP (and sometimes Python) so instead of using the ruby script we are going to build a simple PHP script to send Push Notifications.
Maybe we could improve the library with a parser of google’s ouptuput, basically because we need to handle this output to notice if the user has uninstalled the app (and we need the remove his reg-id from our database), but at least now it cover all my needs. You can see the code at github
In the last Desymfony conference I was speaking with Luis Cordova and he introduced me “Stack” (I must admit Stack was in my to-study-list but only marked as favorite). The idea behind Stack is really cool. (In fact every project where Igor Wiedler appears is brilliant, even the chicken one :)).
Nowadays almost every modern framework/applications implements HttpKernelInterface (Symfony, Laravel, Drupal, Silex, Yolo and even the framework that I’m working in ;)) and we can build complex applications mixing different components and decorate our applications with an elegant syntax.
The first thing than come to my mind after studying Stack is to join different Silex applications in a similar way than Symfony (the full stack framework) uses bundles. And the best part of this idea is that it’s pretty straightforward. Let me show you one example:
Imagine that we’re working with one application with a blog and one API. In this case our blog and our API are Silex applications (but they can be one Symfony application and one Silex application for example).
That’s our API application:
use Silex\Application;
$app = new Application();
$app->get('/', function () {
return "Hello from API";
});
$app->run();
And here our blog application:
use Silex\Application;
$app = new Application();
$app->get('/', function () {
return "Hello from Blog";
});
$app->run();
We can organize our application using mounted controllers or even using RouteCollections but today we’re going to use Stack and it’s cool url-map.
First we are going to create our base application. To do this we’re going to implement the simplest Kernel in the world, that’s answers with “Hello” to every request:
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class MyKernel implements HttpKernelInterface
{
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
return new Response("Hello");
}
}
Stack needs HttpKernelInterface and Silex\Application implements this interface, so we can change our Silex applications to return the instance instead to run the application:
// app/api.php
use Silex\Application;
$app = new Application();
$app->get('/', function () {
return "Hello from API";
});
return $app;
// app/blog.php
use Silex\Application;
$app = new Application();
$app->get('/', function () {
return "Hello from API";
});
return $app;
And now we will attach those two Silex applications to our Kernel:
use Symfony\Component\HttpFoundation\Request;
$app = (new Stack\Builder())
->push('Stack\UrlMap', [
"/blog" => include __DIR__ . '/app/blog.php',
"/api" => include __DIR__ . '/app/api.php'
])->resolve(new MyKernel());
$request = Request::createFromGlobals();
$response = $app->handle($request);
$response->send();
$app->terminate($request, $response);
And that’s all. I don’t know what you think but with Stack one big window just opened in my mind. Cool, isn’t it?
The last week I attend to deSymfony conference. This year the conference was in Madrid and I collaborate as speaker with a talk about Dependency Injection and Dependency Injection Containers in PHP. It was a great experience. 400 attendees, two tracks, Fabien Potencier’s key-note and a brilliant organization could be one fast summary. We also could enjoy with good talks especially (in my humble opinion) one great talk about Advanced Silex with Javier Egiluz (please Javier write a book about Silex soon 🙂 ). A good place to put the real face to colleagues and to know to the most important people at the PHP/Symfony community in Spain. Nice talks (and beers too) with people from Zaragoza, Extremadura, Valladolid, Valencia, Barcelona, with the people of Symfony-Madrid …
As I said before I participated as speaker with one talk about Dependencies, Containers and SOLID principles. Here you can see the slides of the talk.
The organization will publish soon the video with the talk (in Spanish). And here a couple of pictures of the talk.
And that’s all. Thanks to the organization, the sponsors and of course to all the people who choose to attend to my talk one saturday at 9:30 AM. Say cheese …
The previous post was about how to use AngularJS resources with Silex. AngularJS is great and when I need to switch back to jQuery it looks like I go back 10 years in web development, but business is business and I need to live with jQuery too. Because of that this post is about how to use the Silex RestFull resources from the previous post, now with jQuery. Let’s start:
We’re going to write a simple javascript object to handle the RestFull resource using jQuery:
This days I’m playing with AngularJS. Angular is a great framework when we’re building complex front-end applications with JavaScript. And the best part is that it’s very simple to understand (and I like simple things indeed). Today we are going to play with Resources. Resources are great when we need to use RestFull resources from the server. In this example we’re going to use Silex in the backend. Let’s start.
First of all we must realize that resources aren’t included in the main AngularJS js file and we need to include angular-resource.js (it comes with Angular package). We don’t really need resources. We can create our http services with AngularJS without using this extra js file but it provides a very clean abstraction (at least for me) and I like it.
We’re going to create a simple application with CRUD operations in the table. In the example we will use one simple SqlLite database (included in the github repository)
CREATE TABLE main.messages (
id INTEGER PRIMARY KEY NOT NULL ,
author VARCHAR NOT NULL ,
message VARCHAR NOT NULL );
As we can see we will use ng-app=”MessageService” defined within the js/services.js file:
angular.module('MessageService', ['ngResource']).factory('Message', ['$resource', function ($resource) {
return $resource('/api/message/resource/:id');
}]);
And our controller in js/controllers.js:
function MessageController($scope, Message) {
var currentResource;
var resetForm = function () {
$scope.addMode = true;
$scope.author = undefined;
$scope.message = undefined;
$scope.selectedIndex = undefined;
}
$scope.messages = Message.query();
$scope.addMode = true;
$scope.add = function () {
var key = {};
var value = {author: $scope.author, message: $scope.message}
Message.save(key, value, function (data) {
$scope.messages.push(data);
resetForm();
});
};
$scope.update = function () {
var key = {id: currentResource.id};
var value = {author: $scope.author, message: $scope.message}
Message.save(key, value, function (data) {
currentResource.author = data.author;
currentResource.message = data.message;
resetForm();
});
}
$scope.refresh = function () {
$scope.messages = Message.query();
resetForm();
};
$scope.deleteMessage = function (index, id) {
Message.delete({id: id}, function () {
$scope.messages.splice(index, 1);
resetForm();
});
};
$scope.selectMessage = function (index) {
currentResource = $scope.messages[index];
$scope.addMode = false;
$scope.author = currentResource.author;
$scope.message = currentResource.message;
}
$scope.cancel = function () {
resetForm();
}
}
Now the backend part. As we said before we will use Silex. We’re going to use also RouteCollections to define our routes (you can read about it here). So our Silex application will be:
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Routing\Loader\YamlFileLoader;
use Symfony\Component\Routing\RouteCollection;
use Silex\Application;
$app = new Silex\Application();
$app['routes'] = $app->extend('routes', function (RouteCollection $routes, Application $app) {
$loader = new YamlFileLoader(new FileLocator(__DIR__ . '/config'));
$collection = $loader->load('routes.yml');
$routes->addCollection($collection);
return $routes;
}
);
$app->register(
new Silex\Provider\DoctrineServiceProvider(),
array(
'db.options' => array(
'driver' => 'pdo_sqlite',
'path' => __DIR__ . '/db/app.db.sqlite',
),
)
);
$app->run();
<?php
namespace Message;
use Silex\Application;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
class MessageController
{
public function getAllAction(Application $app)
{
return new JsonResponse($app['db']->fetchAll("SELECT * FROM messages"));
}
public function getOneAction($id, Application $app)
{
return new JsonResponse($app['db']
->fetchAssoc("SELECT * FROM messages WHERE id=:ID", ['ID' => $id]));
}
public function deleteOneAction($id, Application $app)
{
return $app['db']->delete('messages', ['ID' => $id]);
}
public function addOneAction(Application $app, Request $request)
{
$payload = json_decode($request->getContent());;
$newResource = [
'id' => (integer)$app['db']
->fetchColumn("SELECT max(id) FROM messages") + 1,
'author' => $payload->author,
'message' => $payload->message,
];
$app['db']->insert('messages', $newResource);
return new JsonResponse($newResource);
}
public function editOneAction($id, Application $app, Request $request)
{
$payload = json_decode($request->getContent());;
$resource = [
'author' => $payload->author,
'message' => $payload->message,
];
$app['db']->update('messages', $resource, ['id' => $id]);
return new JsonResponse($resource);
}
}
And that’s all. Our prototype is working with AngularJS and Silex as REST provider. We must take care about one thing. Silex and AngularJS aren’t agree in one thing about REST services. AngularJS removes the trailing slash in some cases. Silex (and Symfony) returns HTTP 302 moved temporaly when we’re trying to access to the resource without the trailing slash but when we’re working with mounted controllers we will obtain a 404 page not found (bug/feature?). That’s because my REST service is /api/message/resource/:id instead of /api/message/:id. If I chose the second one, when angular tries to create a new resource, it will POST /api/message instead of POST /api/message/. We’re using mounted routes in this example:
With one simple Silex application (without mounted routes) in one file it doesn’t happen (we will see HTTP 302 and a new request with the trailing slash). Because of that I use this small hack to bypass the problem.
You can see the full code of the example in my github account
Today I’d like to play with ZeroMQ. ZeroMQ is a great tool to work with sockets. I will show you the problem that I want to solve: One web application needs to execute background processes but I need to execute those processes in order. Two users cannot execute one process at the same time. OK, if we face to this problem we can use Gearman. I’ve written various posts about Gearman (here and here for example). But today I want to play with ZeroMQ.
I’m going to use one great library called React. With react (reactor pattern implementation in PHP) we can do various thing. One of them are ZeroMQ bindings.
In this simple example we are going to build a simple server and client. The client will send to the server one string that the server will enqueue and executes using the Symfony’s Process component.
Here is the client:
<?php
include __DIR__ . '/../vendor/autoload.php';
use Zmqlifo\Client;
$queue = Client::factory('tcp://127.0.0.1:4444');
echo $queue->run("ls -latr")->getOutput();
echo $queue->run("pwd")->getOutput();
And finally the server:
<?php
include __DIR__ . '/../vendor/autoload.php';
use Symfony\Component\Process\Process;
use Zmqlifo\Server;
$server = Server::factory('tcp://127.0.0.1:4444');
$server->registerOnMessageCallback(function ($msg) {
$process = new Process($msg);
$process->setTimeout(3600);
$process->run();
return $process->getOutput();
});
$server->run();
You can see the working example here:
you can check the full code of the library in github and Packagist.
UPDATE
As Igor Wiedler said React is not necessary here.
ZMQ is used for blocking sends
and blocking tasks, having an event loop does not really make much sense.
I’ve working in a pet-project with Silex and I wanted to perform a Sign-in with Twitter. Implementing Sign in with Twitter is pretty straightforward and it’s also well explained in the Twitter’s developers site. Now we only need to implement those HTTP client requests within PHP. We can create the REST client with curl but nowadays I prefer to use the great library called Guzzle to perform those kind of opperations. So let’s start.
The idea is to create something reusable. I don’t want to spend too much time including the Sign-in with Twitter in my proyects, so my first idea was to create a class with all the needed code and mount this class as group of Silex controllers (as it’s defined here). I also want to keep the class as standard as possible and avoiding the usage of any other external dependencies (except Guzzle)..
Imagine a simple Silex application:
<?php
// www/index.php
include __DIR__ . "/../vendor/autoload.php";
$app = new Silex\Application();
$app->get('/', function () {
return 'Hello';
});
$app->run();
Now I want to use a Sign-in with Twitter, so I will change the application to:
<?php
include __DIR__ . "/../vendor/autoload.php";
$app = new Silex\Application();
$app->register(new Silex\Provider\SessionServiceProvider());
$consumerKey = "***";
$consumerSecret = "***";
$twitterLoggin = new SilexTwitterLogin($app, 'twitter');
$twitterLoggin->setConsumerKey($consumerKey);
$twitterLoggin->setConsumerSecret($consumerSecret);
$twitterLoggin->registerOnLoggin(function () use ($app, $twitterLoggin) {
$app['session']->set($twitterLoggin->getSessionId(), [
'user_id' => $twitterLoggin->getUserId(),
'screen_name' => $twitterLoggin->getScreenName(),
'oauth_token' => $twitterLoggin->getOauthToken(),
'oauth_token_secret' => $twitterLoggin->getOauthTokenSecret()
]);
});
$twitterLoggin->mountOn('/login', function () {
return '<a href="/login/requestToken">login</a>';
});
$app->get('/', function () use ($app){
return 'Hello ' . $app['session']->get('twitter')['screen_name'];
});
$app->run();
The application will redirects all requests (without the correct session) to the route “/login”. The login page has a simple link to the route: “/login/requestToken” (we can create a fancy template with Twig if we want, indeed). This route redirects the request to Twitter’s login page and after a successful login it will redirects back to the route that we have defined within our Twitter application. The library assumes that this callback’s url is “/login/callbackUrl”. All this default routes can be defined by the user using the proper setters of the class.
When the sign-in is finished the application will trigger the callback defined in registerOnLoggin function and will redirects to the route “/”. This route (called internally “redirectOnSuccess”) is also customizable with a setter.
In the post Scaling Silex applications I wanted to organize a one Silex application. In one comment Igor Wiedler recommended us to use RouteCollections instead of define the routes with a Symfony’s Dependency Injection Container. Because of that I started to hack a little bit about it and here I show you my outcomes:
I want to build an imaginary application with silex. This application has also one Api and one little blog. I want to organize those parts. Our index.php file
<?php
// www/index.php
require_once __DIR__ . '/../vendor/autoload.php';
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Routing\Loader\YamlFileLoader;
use Symfony\Component\Routing\RouteCollection;
use Silex\Application;
$app = new Application();
$app['routes'] = $app->extend('routes', function (RouteCollection $routes, Application $app) {
$loader = new YamlFileLoader(new FileLocator(__DIR__ . '/../config'));
$collection = $loader->load('routes.yml');
$routes->addCollection($collection);
return $routes;
});
$app->run();
<?php
// lib/Gonzalo123/AppController.php
namespace Gonzalo123;
use Symfony\Component\HttpFoundation\Response;
use Silex\Application;
class AppController
{
public function homeAction()
{
return new Response("AppController::homeAction");
}
public function helloAction(Application $app, $name)
{
return new Response("Hello" . $app->escape($name));
}
}
<?php
// lib/Gonzalo123/ApiController.php
namespace Gonzalo123;
use Symfony\Component\HttpFoundation\Response;
class ApiController
{
public function listAction()
{
return new Response("AppController::listAction");
}
}
<?php
// lib/Gonzalo123/BlogController.php
namespace Gonzalo123;
use Symfony\Component\HttpFoundation\Response;
class BlogController
{
public function homeAction()
{
return new Response("BlogController::homeAction");
}
}
And that’s all. Here also the needed dependencies within our composer.json file
In my humble opinion Silex is great. It’s perfect to create prototypes, but when our application grows up it turns into a mess. That was what I thought until the last month, when I attended to a great talk about Silex with Javier Eguiluz. OK. Scaling Silex it’s not the same than with a Symfony application, but it’s possible.
It’s pretty straightforward to create a Silex application with composer:
But there’s a better way. We can use the Fabien Potencier’s skeleton. With this skeleton we can organize our code better.
We also can use classes as controllers instead of using a closure with all the code. Igor Wiedler has a great post about this. You can read it here.
Today I’m playing with Silex and I want to show you something. Let’s start:
Probably you know that I’m a big fan of Symfony’s Dependency Injection Container (you can read about it here and here), but Silex uses Pimple. In fact the Silex application extends Pimple Class. My idea is the following one:
In the Igor’s post we can see how to use things like that:
My idea is to store this information within a Service Container (we will use Symfony’s DIC). For example here we can see our routes.yml:
routes:
video_info:
pattern: /video/{id}
controller: Gonzalo123\ApiController::initAction
requirements:
_method: GET
As we can see we need to implement one Extension for the alias “routes”. We only will implement the needed functions for YAML files in this example.
<?php
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class SilexRouteExtension implements ExtensionInterface
{
/**
* Loads a specific configuration.
*
* @param array $config An array of configuration values
* @param ContainerBuilder $container A ContainerBuilder instance
*
* @throws InvalidArgumentException When provided tag is not defined in this extension
*
* @api
*/
public function load(array $config, ContainerBuilder $container)
{
}
/**
* Returns the namespace to be used for this extension (XML namespace).
*
* @return string The XML namespace
*
* @api
*/
public function getNamespace()
{
}
/**
* Returns the base path for the XSD files.
*
* @return string The XSD base path
*
* @api
*/
public function getXsdValidationBasePath()
{
}
/**
* Returns the recommended alias to use in XML.
*
* This alias is also the mandatory prefix to use when using YAML.
*
* @return string The alias
*
* @api
*/
public function getAlias()
{
return "routes";
}
}
And now we only need to prepare the DIC. According to Fabien’s recommendation in his Silex skeleton, we only need to change the src/controllers.php
<?php
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
// Set up container
$container = new ContainerBuilder();
$container->registerExtension(new SilexRouteExtension);
$loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../config/'));
// load configuration
$loader->load('routes.yml');
$app['container'] = $container;
$app->mount('/api', include 'controllers/myApp.php');
$container->compile();
$app->error(function (\Exception $e, $code) use ($app) {
if ($app['debug']) {
return;
}
$page = 404 == $code ? '404.html' : '500.html';
return new Response($app['twig']->render($page, array('code' => $code)), $code);
});
and now we define the config/routes.yml
routes:
video_info:
pattern: /video/{videoId}
controller: Gonzalo123\ApiController::initAction
requirements:
_method: GET
And finally the magic in our controllers/myApp.php:
The class for this example is: src/Gonzalo123/ApiController.php
<?php
namespace Gonzalo123;
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
class ApiController
{
public function initAction(Request $request, Application $app)
{
return new JsonResponse(array(1, 1, $request->get('id')));
}
}
As you can see the idea is to use classes as controllers, define them within the service container and build the silex needed code iterating over the configuration. What do you think?
Keeping on with the series about Symfony’s Services container (another posts here and here), now we will use the service container to use Twitter API from a service.
To use Twitter API we need to handle http requests. I’ve written several post about http request with PHP (example1, example2), but today we will use one amazing library to build clients: Guzzle. Guzzle is amazing. We can easily build a Twitter client with it. There’s one example is its landing page:
If we are working within a Symfony2 application or a PHP application that uses the Symfony’s Dependency injection container component you can easily integrate this simple script in the service container. I will show you the way that I use to do it. Let’s start:
The idea is simple. First we include guzzle within our composer.json and execute composer update:
"require": {
"guzzle/guzzle":"dev-master"
}
Then we will create two files, one to store our Twitter credentials and another one to configure the service container: