EzDevInfo.com

Silex

The PHP micro-framework based on the Symfony2 Components Homepage - Silex - The PHP micro-framework based on Symfony2 Components silex - the php micro-framework based on symfony2 components

REST web services: Symfony 2 vs silex [closed]

We're going to implement a set of REST web services in PHP. We've selected 2 frameworks to do that: Symfony 2 and Silex (micro-framework as a phar archive, based on Symfony2).

For now, there will be only a few services, with a few resources returned as GET, but the set of method will eventually grow and include other rest actions (put/post/delete).

here is the list of pros and cons I've got so far for these 2 frameworks

Symfony2

Pros:

  • more powerful
  • Doctrine ORM
  • can debug with XDebug
  • config in YML
  • more used in the community
  • more support
  • autocompletion in IDE
  • fast

cons:

  • Need FOSBundle to do REST (?) (actually, I'd like to know if this is really useful)

Silex

Pros:

  • lightweight
  • seems easier to create REST urls (?)
  • easier to deploy (phar archive)

Cons:

  • no Doctrine ORM
  • cannot debug (phar archive)
  • no autocompletion in IDE
  • config must be hardcoded
  • may be a bit slower, as it's in a phar archive ?

Which one do you think is the best?

Thanks


Source: (StackOverflow)

The difference between Symfony and Silex

I would like to try Silex but i've some questions.

I know to use Symfony2 and i would like to know if Silex is very different of Symfony or it's the same thing (same operation, same code... ) ?

Moreover, Silex is recommanded for small PHP projects and Symfony for medium or big projects , it's true ?


Source: (StackOverflow)

Advertisements

Bootstrap 3: formatted checkboxes with Symfony & Twig

How to create a formatted group of checkboxes as described in the Bootstrap documentation using the Symfony Form Factory and Twig?

Using something like

<div class="row">
  <div class="col-lg-4">
    {{ form_label(form.sample) }}
  </div>
  <div class="col-lg-8">
    {{ form_widget(form.sample) }}
  </div>
</div>

will not result in the needed output:

a) each checkbox within a Bootstrap 3 structure like:

<div class="radio">
  <label>
    <input type="radio" ... />Option one
  </label>
</div>

b) in addition the ability to output the checkboxes in two or more columns if needed:

<div class="row">
  <div class="col-lg-6 col-md-6">
    <div class="radio"> ... </div>
  </div>
  <div class="col-lg-6 col-md-6">
    <div class="radio"> ... </div>
  </div>
</div>

Source: (StackOverflow)

Sessions do not work in Silex\App

For whatever reason, Sessions don't work in my Silex-app. I set error_reporting in my php.ini to E_ALL | E_STRICT and errors are displayed and logged. Nothing to see there. But for some reason no session is created and there is no file in /project-root/tmp/sessions/ (and also not, when using the default session.save_path). Switching to PdoSessionStorage, to rule out problems with read/write-permissions on the filesystem, brought no results either. I also tried switching between $app['session'], $request->getSession() and $app['request']->getSession() to no avail.

I am at a loss as to where else to look for problems...

Here is a very simple test-app I wrote (use is omitted to save space). Basically this test shows what I try to achieve in my actual app. I want to store an array in the session. In $app->before() I check if the value is set and then pass it to twig to be displayed, e.g. login info: You are logged in as {{ user.name }}:

$app = new Application;
$app['debug'] = true;
$app->register(new SessionServiceProvider, array(
    'session.storage.save_path' => dirname(__DIR__) . '/tmp/sessions'
));
$app->register(new TwigServiceProvider, array(
    'twig.path' => __DIR__ . '/views'
));

$app->before(function (Request $request) use ($app) {
//    if ($app['debug'] == true) {
//        $request->getSession()->set('test', array('key' => 'value'));
//    }
    if ($request->hasPreviousSession() && $request->getSession()->has('test')) {
        $test = $request->getSession()->get('test');
        if ($test !== null) {
            $app['twig']->addGlobal('before', $test);
        }
    }
});

$app->get('/', function () use ($app) {
    return $app['twig']->render('sessiontest.twig');
});
$app->get('/test', function () use ($app) {
    $app['session']->set('test', array('key' => 'value'));
    return $app['twig']->render('sessiontest.twig',
        array('get' => $app['session']->get('test')));
});
$app->run();

sessiontest.twig looks like this:

<html>
<head><title>test</title></head>
<body>
    {% if before is defined %}before: {{ before.key }}{% endif %}
    {% if get is defined %}get: {{ get.key }}{% endif %}
</body>
</html>

When going to / nothing is displayed, when going to /test only "get: test" is displayed (but not actually stored, as neither returning to / nor refreshing triggers before).


Source: (StackOverflow)

Silex and Doctrine ORM

I am trying to use Silex together with Doctrine ORM (not just DBAL) but I am unable to get the configuration correct.

composer.json

{
  "require": {
    "silex/silex": "1.0.*@dev",
    "symfony/monolog-bridge": "~2.1",
    "symfony/twig-bridge": "~2.1",
    "symfony/form": "~2.1",
    "symfony/yaml": "2.2.*",
    "symfony/form": "2.2.*",
    "symfony/translation": "~2.1",
    "symfony/config": "2.2.*",
    "dflydev/doctrine-orm-service-provider": "1.0.*@dev"
  },
  "autoload": {
    "psr-0": {
      "Entities": "src/"
    }  
  }
}

bootstrap.php located in my project root folder

use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;

require_once __DIR__ ."/vendor/autoload.php";

$isDevMode = true;
$config = Setup::createAnnotationMetadataConfiguration(array(__DIR__."/src/Entities"), $isDevMode);

$params = array(
    'driver' => 'pdo_sqlite',
    'path' => __DIR__ . '/development.sqlite',
);

$entityManager = EntityManager::create($params, $config);

cli-config.php also located inside the root folder

require_once "bootstrap.php";

$helperSet = new \Symfony\Component\Console\Helper\HelperSet(array(
    'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($entityManager->getConnection()),
    'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($entityManager)
));

Customer.php entity located inside src/Entities

/**
 * @Entity @Table(name="customers")
 **/
class Customer {
    /** @Id @Column(type="integer") @GeneratedValue **/
    protected $id;
    /** @Column(type="string") **/
    protected $name;

    public function getName() {
        return $this->name;
    }

    public function setName($name) {
        $this->name = $name;
    }

    public function getId() {
        return $this->id;
    }
}

I am able to run commands like php vendor/bin/doctrine orm:schema-tool:create and have it generate a table called customs just as it should. But how do I load that entity inside my Silex application

Here is my index.php

require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();

use Symfony\Component\Yaml\Yaml;
$app['config'] = function () {
    $config = Yaml::parse(__DIR__ .'/../config.yml');

    return $config;
};

$app->register(new Silex\Provider\DoctrineServiceProvider(), array(
    'dns.options' => $app['config']['database']['development']
));
$app->register(new Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider, array(
    'orm.em.options' => array(
        'mappings' => array(
            array(
                'type' => 'annotation',
                'path' => __DIR__ .'/src/Entities',
            )
        )
    ),
));
$app->get('/', function () use ($app) {
    $customer = $app['orm.em']->getRepository('Customer');

return '<pre>'. $customer->getName() .'</pre>';
});

The result when loading the localhost inside my browser

Warning: class_parents() [function.class-parents]: Class Customer does not exist and could not be loaded in /Users/me/Documents/project/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/RuntimeReflectionService.php on line 40

UPDATE I am not sure this is the correct way to solve this issue, but by using the following approach the problem got solved and I can now use my entities in Silex

$app['em'] = function ($app) {
    $config = Setup::createAnnotationMetadataConfiguration(array(__DIR__."/src/Entities"), true);
    $params = array(
        'driver' => 'pdo_sqlite',
      'path' => __DIR__ . '/../development.sqlite',
    );
    $entityManager = EntityManager::create($params, $config);

    return $entityManager;
};

I used the dependency approach because that way I can use $app['config'] to store DB information and other environment specific configurations.

$customer = new \Entities\Customer();
$customer->setName('Multi Corp '. uniqid());

$app['em']->persist($customer);
$app['em']->flush();

Source: (StackOverflow)

User authentication with a db-backed UserProvider in Silex

I am developing a Silex application, and now I'm in the security phase. I've read all the documentation I've found on the net about this subject, but I have many doubts, and I wish someone would help me, if possible.

Basically I followed this tutorial:

"http://www.johannreinke.com/en/2012/08/28/mysql-authentication-in-silex-the-php-micro-framework/"

and naturally the Silex documentation:

"http://silex.sensiolabs.org/doc/providers/security.html"

Also everything I found on Google.

But still, I think Silex still lacks a lot of documentation, I am lost in many ways.

My code:

 $app->register(new Silex\Provider\SessionServiceProvider(), array(
  'session.storage.save_path' => __DIR__.'/../vendor/sessions',
 ));

$app->register(new Silex\Provider\DoctrineServiceProvider(), array(
'db.options' => array(
'driver'    => 'pdo_mysql',
'host'      => 'localhost',
'dbname'    => 'dbname',
'user'      => 'someuser',
'password'  => 'somepass',
'charset'   => 'utf8',
),
));



$app['security.encoder.digest'] = $app->share(function ($app) {
    return new MessageDigestPasswordEncoder('sha1', false, 1);
});


$app['security.firewalls'] = array(
    'acceso' => array(
    'pattern' => '^/confirmar',
    'form' => array('login_path' => '/acceso', 'check_path' => '/confirmar/comprobar_acceso'),
    'logout' => array('logout_path' => '/confirmar/salir'),
    'users' => $app->share(function() use ($app) {
     return new Acme\User\UserProvider($app['db']);
    }),
),
);


$app->register(new Silex\Provider\SecurityServiceProvider(array(
'security.firewalls' => $app['security.firewalls'],
'security.access_rules' => array(
array('^/confirmar', 'ROLE_USER'),
),
)));

I have so many doubts in the controller:

$app->match('/acceso', function(Request $request) use ($app) {

$username = $request->get('_username');
$password = $request->get('_password');

if ('POST' == $request->getMethod())
    {
    $user = new Acme\User\UserProvider($app['db']);
    $encoder = $app['security.encoder_factory']->getEncoder($user);
    // compute the encoded password
    $encodedPassword = $encoder->encodePassword($password, $user->getSalt());

    // compare passwords
        if ($user->password == $encodedPassword)
            {
            // set security token into security
            $token = new UsernamePasswordToken($user, $password, '', array('ROLE_USER'));
            $app['security']->setToken($token);
           //return $app->redirect('/jander');
           // redirect or give response here
         } else {
         // error feedback
         }

         }


return $app['twig']->render('login.twig', array(
    'error'         => $app['security.last_error']($request),
    'last_username' => $app['session']->get('_security.last_username'),
));
})
->bind('acceso');

This is my class, User Provider:

// src/Acme/User/UserProvider.php
namespace Acme\User;

use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Doctrine\DBAL\Connection;




class UserProvider implements UserProviderInterface
{
private $conn;

public function __construct(Connection $conn)
{
    $this->conn = $conn;
}

public function loadUserByUsername($username)
{
    $stmt = $this->conn->executeQuery('SELECT * FROM compradores WHERE idemail = ?', array(strtolower($username)));
    if (!$user = $stmt->fetch()) {
        throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
    }

    return new User($user['idemail'], $user['pass'], explode(',', $user['roles']), true, true, true, true);
}

public function refreshUser(UserInterface $user)
{
    if (!$user instanceof User) {
        throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
    }

    return $this->loadUserByUsername($user->getUsername());
}

public function supportsClass($class)
{
    return $class === 'Symfony\Component\Security\Core\User\User';
}
}

And my form:

<form action="{{ path('confirmar_comprobar_acceso') }}" method="post">
{{ error }}
<input type="text" name="_username" value="{{ last_username }}" />
<input type="password" name="_password" value="" />
<input type="submit" />
</form>

And this is my mysql table:

id          int(15) 
idemail varchar(255)
nombre  varchar(255) 
apellidos   varchar(255)
telefono    int(11)
activo  tinyint(4)
pass    varchar(40)
roles   varchar(255)
iva         tinyint(4)
nifcif      varchar(255)

I always get a "Bad credentials" response when attempt login. Any ideas? Thanks and Cheers!


Source: (StackOverflow)

How do you setup the controller in a Silex PHP Framework project?

I can't seem to get anything to work past the root path so far:

Do you put all your controller calls in the app.php file?

$app->get('/', function ($id) {
  ...
});

$app->get('/about', function ($id) {
  ...
});

Or do you put them in separate files? So far the root get method works fine and renders a twig template, but anything past that does nothing.


Source: (StackOverflow)

Silex: Redirect with Flash Data

I need to redirect one page to another with a message in Silex. Hopefully there's a Laravelesque way of doing it, but I highly doubt it:

$app->redirect('/here', 301)->with('message', 'text');

I'd then want to display the message in my template:

{{ message }}

If not, is there another way?

Update

I see there's a getFlashBag method in Symfony - is that what I'm supposed to use? Specifically, I am using the Bolt Content Management system.


Source: (StackOverflow)

Mockery - call_user_func_array() expects parameter 1 to be a valid callback

I have a class I need to mock:

class MessagePublisher {

/**
 * @param \PhpAmqpLib\Message\AMQPMessage $msg
 * @param string $exchange - if not provided then one passed in constructor is used
 * @param string $routing_key
 * @param bool $mandatory
 * @param bool $immediate
 * @param null $ticket
 */
public function publish(AMQPMessage $msg, $exchange = "", $routing_key = "", $mandatory = false, $immediate = false, $ticket = null)
{
    if (empty($exchange)) {
        $exchange = $this->exchangeName;
    }

    $this->channel->basic_publish($msg, $exchange, $routing_key, $mandatory, $immediate, $ticket);
}

I am using Mockery 0.7.2

    $mediaPublisherMock = \Mockery::mock('MessagePublisher')
        ->shouldReceive('publish')
        ->withAnyArgs()
        ->times(3)
        ->andReturn(null);

unfortunately my tests failed, due to this error

call_user_func_array() expects parameter 1 to be a valid callback, class 'Mockery\Expectation' does not have a method 'publish' in /vendor/mockery/mockery/library/Mockery/CompositeExpectation.php on line 54

I have tried to debug I found that tests fails in this code

public function __call($method, array $args)
{
    foreach ($this->_expectations as $expectation) {
        call_user_func_array(array($expectation, $method), $args);
    }
    return $this;
}

where
$method = 'publish'
$args = array()
$expectation is instance of Mockery\Expectation object ()

I am using php 5.3.10 - any idea what is wrong?


Source: (StackOverflow)

Silex - Twig_Error_Syntax: The function "path" does not exist

According to the Silex documentation:

Symfony provides a Twig bridge that provides additional integration between some Symfony2 components and Twig. Add it as a dependency to your composer.json file.

I include the following in my composer.json file:

{
    "require": {
        "silex/silex": "1.*",
        "twig/twig": ">=1.8,<2.0-dev",
        "symfony/twig-bridge": "2.3.*"
    }
}

I register the TwigServiceProvider() like so:

$app->register(new Silex\Provider\TwigServiceProvider(), array(
    'twig.path' => __DIR__ . '/views'
));

I'm attempting to use the twig path() method like so:

<a rel='nofollow' href="{{ path('logout') }}">Log out</a>

The error I get is as follows:

Twig_Error_Syntax: The function "path" does not exist

Why am I getting this error?

  • I have tried switching around versions to check if it is a version issue
  • One google groups comment suggested 'registering' the twig bridge provider, but this doesn't exist
  • I don't want to have to use: app.url_generator.generate in all my templates instead

A temporary solution I have found:

Ensure The UrlGeneratorServiceProvider() is registered:

$app->register(new UrlGeneratorServiceProvider());

Create a new function for twig for path():

$app['twig']->addFunction(new \Twig_SimpleFunction('path', function($url) use ($app) {
    return $app['url_generator']->generate($url);
}));

I shouldn't have to do this!! How can I get this working properly?


Source: (StackOverflow)

Unexpected character in input: '\' (ASCII=92) state=1 in a Silex Application

I moved my website from local to a hosting, and something happened to me. I include this config file into my index.php (it's the first thing I do):

<?php
require_once __DIR__.'/../../vendor/autoload.php';

// some other stuff

$app = new Silex\Application();
$app['debug'] = true;

$defaultLocale = 'en';

$app->register(new Silex\Provider\TwigServiceProvider(), array(
    'twig.path' => array(
                            __DIR__.'/../views', 
                            __DIR__.'/../views/backend', 
                            __DIR__.'/../views/layouts',
                            __DIR__.'/../views/components',
                            __DIR__.'/../views/backend/components', 
                        ),
));
$app->register(new Nicl\Silex\MarkdownServiceProvider());

But the website complains this way:

Warning: Unexpected character in input: '\' (ASCII=92) state=1 in /public_html/_inc/config.php on line 7

Parse error: syntax error, unexpected T_STRING in /public_html/_inc/config.php on line 7

Basically, line 7 is $app = new Silex\Application();. I'm using Silex and the server is running PHP 5.2. The vendor folder (which contains all the framework and third parties stuff) is in root (/)

I was wondering it had some problems with autoload, but I don't find what could exactly be or how to test it. Do you find anything strange? Thanks in advance.


Source: (StackOverflow)

How do you register a namespace with Silex autoloader

I'm experimenting with creating an extension with the Silex php micro framework for user authentication but I can't seem to get the autoloader to work. Can anyone shed any light?

I have a directory structure like this (truncated)

usertest
|_lib
| |_silex.phar
| |_MyNamespace
|   |_UserExtension.php
|   |_User.php
|_www
  |_index.php

The pertinent bits of index.php, which serves as the bootstrap and the front controller look like this:

require '../lib/silex.phar';

use Silex\Application;
use MyNamespace\UserExtension;

$app = new Application();
$app['autoloader']->registerNamespace( 'MyNamespace', '../lib' );
$app->register( new UserExtension() );

The class I'm trying to load looks similar this:

namespace MyNamespace;

use Silex\Application;
use Silex\ExtensionInterface;

class UserExtension implements ExtensionInterface {
    public function register( Application $app ) {
        $app['user'] = $app->share( function() use( $app ) {
            return new User();
        });
    }
}

All pretty straight forward except it throws this error:

Fatal error: Class 'MyNamespace\UserExtension' not found in /home/meouw/Projects/php/usertest/www/index.php on line 8

I have dabbled with symfony2 and have successfully followed the instructions for setting up the universal class loader, but in this instance I am stumped. Am I missing something? Any help would be appreciated.


Source: (StackOverflow)

Backbone.js and REST api with Silex (PHP)

lets say I have a model called John with those params:

{
    Language : {
        code    :  'gr',
        title   :  'Greek'
    },
    Name : 'john'
}

So now when I trigger John.save() it POST those to server:

post params

with those headers:

headers

The code in Silex is really simple:

<?php

require_once __DIR__.'/silex.phar';

$app = new Silex\Application();

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

// definitions
$app['debug'] = true;

$app->post('/api/user', function (Request $request) {
    var_dump($request->get('Name'));

    $params = json_decode(file_get_contents('php://input'));
    var_dump($params->Name);
});

$app->run();

but first var_dump return null second var_dump of course works since I'm getting the request directly from php://input resource. I'm wondering how I could get the params using Request object from Silex

Thanks


Source: (StackOverflow)

How to use a YAML config file in Silex Framework

Is it possible to configure a Silex Application with YAML config files? I bet yes, but how is it done correctly? For instance I want to use different configurations according to the environment, like config.dev.yml and config.prod.yml.

The config file should contain parameters for the app itself and for the registered extensions/services.

Example:

// Debug flag should be set in the config file
$app['debug'] = true;

// Extension options should also be set in config file
$app->register(new Silex\Extension\TwigExtension(), array(
    'twig.path'       => __DIR__.'/views',
    'twig.class_path' => __DIR__.'/vendor/Twig/lib',
));

Do I have to parse the YAML file by myself and set the parameters accordingly or is there a more "magic" way to do this?


Source: (StackOverflow)

How do I obtain all the GET parameters on Silex?

I've been using Silex for a day, and I have the first "stupid" question. If I have:

$app->get('/cities/{city_id}.json', function(Request $request, $city_id) use($app) {
    ....
})
->bind('city')
->middleware($checkHash);

I want to get all the parameters (city_id) included in the middleware:

$checkHash = function (Request $request) use ($app) {

    // not loading city_id, just the parameter after the ?
    $params = $request->query->all();

    ....
}

So, how do I get city_id (both the parameter name and its value) inside the middleware. I'm going to have like 30 actions, so I need something usable and maintainable.

What am I missing?

thanks a lot!

Solution

We need to get those extra parameters of $request->attributes

$checkHash = function (Request $request) use ($app) {

    // GET params
    $params = $request->query->all();

    // Params which are on the PATH_INFO
    foreach ( $request->attributes as $key => $val )
    {
        // on the attributes ParamaterBag there are other parameters
        // which start with a _parametername. We don't want them.
        if ( strpos($key, '_') != 0 )
        {
            $params[ $key ] = $val;
        }
    }

    // now we have all the parameters of the url on $params

    ...

});

Source: (StackOverflow)