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
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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:
with those 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)
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)
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)