Question and Answer Day: March 27th, 2013

Woh! KnpUniversity Question & Answer Day is March 27th, 2013!

Submit all your Symfony, Behat and PHP questions by March 26th, 2013 and we'll answer them. We're calling it KnpU Question/Answer Day - we're finally shutting up and doing the listening!


Your Guides

Ryan Weaver Leanna Pelham

Questions? Conversation?

  • 2016-08-11 weaverryan
  • 2016-08-09 Henri Tompodung

    How to make recursive function in symfony 3 with doctrine?
    I have script PHP native like below:

    mysql_connect("localhost","root","blablabla");
    mysql_select_db("demo");

    function html_menu(&$strmenu="", $parent=0) {
    $query = "SELECT * FROM menu
    WHERE code_parent='$parent'
    ORDER BY code_menu";
    $sql = mysql_query($query);

    if (mysql_num_rows($sql) > 0) {
    $strmenu .= '<ul>'.PHP_EOL;
    }

    // show children
    while ($row = mysql_fetch_array($sql)) {
    $strmenu .= "<li>".PHP_EOL;
    $strmenu .= sprintf("%s", $row['link'], $row['nm_menu'], $row['nm_menu']).PHP_EOL;

    html_menu($strmenu, $row['code_menu']);
    $strmenu .= "</li>".PHP_EOL;
    }

    if (mysql_num_rows($sql) > 0) {
    $strmenu .= '</ul>'.PHP_EOL;
    }

    }

    $strmenu = "";
    html_menu($strmenu, 0);
    echo $strmenu;

  • 2014-09-26 Yusuf Ibr.
  • 2014-09-25 weaverryan

    Hi Yusuf!

    Sorry - right now I have all the comments on one page (changing that today or tomorrow)! So, which exact post inside of this were you asking about?

    Thanks!

  • 2014-09-25 Yusuf Ibr.

    nice article, very clear and easy to follow, I have general question, can we implement this way in Digital Ocean or Webfaction cloud hosting ?

  • 2014-09-25 Yusuf

    thanks, it solved now

  • 2014-09-22 weaverryan

    Hi Yusuf!

    This looks like a problem with your service configuration (i.e. services.yml). It looks like you need to pass the entity manager as your second argument. You're doing something a bit different than what we show, but it'll look something like this:

    https://gist.github.com/weaver...

    Cheers!

  • 2014-09-22 Yusuf

    I got this error, anybody can help ?

    ContextErrorException:
    Catchable Fatal Error: Argument 2 passed to XX\XXXBundle\EventListener\CurrentSiteListener::__construct() must
    be an instance of Doctrine\ORM\EntityManager, none given, called in
    /var/www/html/XPROJECT/app/cache/dev/appDevDebugProjectContainer.php on
    line 642 and defined in
    /var/www/html/XPROJECT/src/KW/CoffeeHRBundle/EventListener/CurrentSiteListener.php
    line 16

  • 2014-09-13 Ethan Finni

    Perfect! Thank you very much, sounds right to me, I am going to play with it.

  • 2014-09-12 weaverryan

    Hey Ethan!

    Hmm, interesting! The first approach that comes to mind is to create multiple applications, one for each user (well, sort of). As you mentioned, all you *really* need is different database configuration for each user. I would try something like this:

    1) In your front controller, add a new line like this (the new AppKernel line already exists, just showing for context):

    $kernel = new AppKernel('dev', true);

    $kernel->configureUser($request);

    2) In AppKernel, create a new configureUser(Request $request) function. In here, read the host from the request, parse out the user part (e.g. u01, u02) and set that on a new "userKey" property on AppKernel.

    3) In AppKernel, override getCacheDir and getLogDir. In each, use the "userKey" property to make each unique per user:


    public function getCacheDir()
    {
    return return $this->rootDir.'/cache/'.$this->environment.'/'.$this->userKey;
    }

    4) In AppKernel, add a new line to registerContainerConfiguration that loads a "userKey" specific configuration file, where you can override any database parameters you want:


    $loader->load(__DIR__.'/config/database_'.$this->userKey.'.yml');

    This should result in one application, but which has different cache and log directories (cache is the important one) and different database connection information for each.

    Try it out! I've never done something quite like this, so it may be imperfect, but we'll see :).

    Cheers!

  • 2014-09-08 Ethan Finni

    I am having a similar question but my case may be simpler. I am running a web-app and currently, all my users share the same database schema.

    I would like to create "pipelines" on my server where users login on their "own" sub-domain (u01.x.org, u02.x.org etc) and access their "own" separate database schema (u01, u02 etc) on a single database installation. I need this to ensure data isolation and keep the queries faster by accessing smaller tables (each user only hitting tables with only their own data)

    The number of users we host is small (~10) and fairly fixed (no fluctuation), so "managing" the pipeline is not much of an issue and it does not need to be automatic.

    Is there a way in Symfony to do this with the domains sharing a common code or, I need to create an instance of the code for each sub-domain and then configure databases.yml of each instance to route traffic to a particular schema?

    Thanks!
    Ethan

  • 2014-09-02 Sufiyan

    Just use this in your twig file

    {% do form.yourFieldName.setRendered %}

    And here you go :)

  • 2014-07-22 weaverryan

    Hi Hardik!

    There are multiple ways to approach this. Here is one:

    For this, you'll need to either have a different kernel class (e.g. AppKernel) for each site OR, at least, override the AppKernel::getCacheDir and have each site use a different cache directory. The point is this: if you're going to vary the configuration based on the site, then you need a different cache directory for each site. Next, you'll probably want to have a parameters.php file (like parameters.yml, but written in PHP, see the PHP tab of http://symfony.com/doc/current..., that dynamically figures out which site is being loaded, which database name to use, then, sets the "database_name" parameter to the correct database (assuming you are still using a parameter by that name in your Doctrine configuration inside config.yml).

    The parameters.php will cause your database to use the right database name, based on the site. Using a different kernel or cache directory will make sense that each site has its own version of the configuration (without this, all sites would use the same database_name, based on the site of the first request).

    Alternatively, you *may* also be able to leverage multiple "entity managers". Then, early in Symfony, dynamically change the "default" entity manager to be based on the site.

    Again, these are all a bit more complex, but I hope this gives you at least some direction!

    Cheers!

  • 2014-07-21 Hardik Raval

    How to achieve this with dynamic database connection. means what if every site has different database connection.

  • 2014-06-27 Hernan

    Thanks so much weaverryan! Good answer!

  • 2014-06-27 weaverryan

    Hi Hernan!

    To do this, you'll need to create your own security authentication mechanism. I don't think you'll be able to re-use many parts of the normal form login system, because that system really expects only a username and password (no third field).

    The best way to do this is probably to follow this tutorial: http://symfony.com/doc/current..., except that you would be reading the username, client number and password from the request's post data (e.g. $request->request->get('username'). You would need to create your own Token class (that has an extra "client number" field). You'll also need to check the URL of the request and only run your authentication code if the user is POST'ing to some specific url (e.g. /login_check).

    To actually do the database switching, I'd inject Doctrine's Registry object (service: "doctrine"). You can use it to get out whatever entity manager or connection you want, dynamically, based on the client name.

    I hope this gives you some direction!

  • 2014-06-24 Hernan

    Hi, I'm working on Symfony2 app where I need to have one login form with THREE fields, username, client number and password. With client number I could choose the corresponding entity manager, connection and login against client database. I have one database for admin purposes (clients, contracts and another backend tables) and one database per client. If I want to login as administrator I can use a client number 0000 or another special number. How can I use three login field to connect to client DB dynamically? Thanks and sorry for my english

  • 2014-06-21 Rodolfo Freeman

    Great article, you finally explained HOW to create services step by step. I think that on all of the documentation I've read so far it understates that you have to call your service from your router, otherwise it won't inject the dependencies. Thank you so much!

  • 2014-06-02 Sergio

    Thanks a lot KnpUniversity !!! Great job! Looking forward for more screencasts!

  • 2014-05-27 Carlo Maria Piacenti

    Thanks for the useful lesson. I've been searching the web for days to discover some more deep explanation of the topic, and finally found this one. Your info & examples really pushed me forward... thanks a lot!

  • 2014-05-20 kendoctor

    well done.

  • 2014-05-16 weaverryan

    Yeaaa! Awesome! Good luck!

  • 2014-05-16 MortisDux

    You totally answered the right question, I'm sorry my question was not so clear, but you did great!
    It's working fine, thanks a lot! Cheers!

  • 2014-05-15 weaverryan

    Hi there!

    Wow, really great question (if I understand it correctly)! So, you have a custom constraint (DatePosterieure) and the corresponding custom validator service (service id date_posterieure). And the question is how you could use the custom validator. It should look like this:


    // gives you the value of your form's date field
    $data = $form->get('date')->getData();
    $dateConstraint = new DatePosterieure(); //this is my Constraint
    $errorList = $this->get('validator')->validateValue($data, array($dateConstraint));

    And that's it. Internally, DatePosterieure returns a string from its validatedBy() method (http://symfony.com/doc/current... which matches the "alias" on the "validator.constraint_validator" tag. This is how the "validator" service knows to use your service, when all you pass it is a simple DatePosterieure object.

    To do all this directly on the form, it would basically be the same:


    $builder->add('date', 'date', array(
    'constraints' => array(new DatePosterieure())
    ))->getForm();

    I'm writing this without trying it, so let me know if it works out... or if I didn't answer the right question ;).

    Cheers!

  • 2014-05-15 MortisDux

    Hello there, thanks for the all explication, but just a quick question: how could you use the custom constraint in a controller you would do with an already existing constraint??

    $data = $form->get('date')->getData();
    $DateConstraint = new DatePosterieure(); //this is my Constraint
    $errorList = $this->get('date_posterieure')->validate( //"date_posterieure" is my service (ConstraintValidator)
    $data,
    $emailConstraint
    );

    this is not working, service is non existent even if annotation is working well
    I'd like to use the custom constraint to validate entities (with annotation) or custom forms not linked to any entity
    thanks in advance.

  • 2014-05-06 weaverryan

    Hey Jan!

    I'm really glad you got it figured out! :) Cheers!

  • 2014-05-03 RedKite CMS

    UPDATED
    The problem is caused by permissions, so it has nothing to do with this tutorial.

    Jan

    Hi,
    I'm trying to run my behat/mink suite at travis following this awesome tutorial, but the response I get is always a blank page: any idea on what I'm doing wrong? https://travis-ci.org/janxin/R...

    Thanks in advance
    Jan

  • 2014-04-30 weaverryan

    Oh wow, yes that is annoying. We were just dealing with this on a project today, and unfortunately, there's no *one* thing that can cause these odd failures on Travis. For us, we had some 3rd party server that was dying every now and then, as well as some JavaScript that was loading in a way that needed some extra setup. It's very specific. In general, this is one of the things that makes continuous integration hard, especially if you don't have it setup on day 1: you almost always get weird failures at first. Once you have them all fixed, handling any new ones going forward is pretty easy.

    My best advice is to keep using the "And print last response". Alternatively, you could even add an @AfterScenario hook so that the last response is *always* printed out on a failure. Here's a gist for my version of this code :) https://gist.github.com/weaver...

    Good luck!

  • 2014-04-29 Pablo María Martelletti

    Hi Ryan,

    Thanks a lot for your response. The problem in adding "And print last response" is that it is not always the same test that fails, so not sure if that's a good solution for my case (as I have tons of tests and adding print last response to all would made the logs unreadable :( ).

    The worst is that they give me a debug VM to test the commands I run in travis, and the first time I run the tests they fail. So, now that they fail, I add the print last response on that test and I run it again.. and all test passes. :S Very weired.

    Any idea on what could be causing this?

  • 2014-04-28 weaverryan

    Hey Pablo!

    I'm not sure about the "export" issue, that *is* weird. But as far as the "Form field with..." error, it could be something simpler than what you're thinking. For example, perhaps Firefox is opening totally fine, but there's an issue with your database, so instead of a login form, you are seeing a huge error page! I would add a debug stuff right before the failure to see the HTML of the page in the Travis log:

    And print last response

    Then you'll be able to see if maybe there's just some other issue (and not really a Travis/xvfb setup).

    Good luck!

  • 2014-04-22 Pablo María Martelletti

    hi guys!

    I'm having problems getting this right. If I keep the default config (that's it, the default firefox driver), I get the following error:

    "Form field with id|name|label|value "Username" not found."

    with all fields and text in the page. I've tried adding "-scree 0 1280x1024x24" to the xvfb start command, but still not solved.

    I'm also getting the following error if I put the export BEFORE the xvfb start:

    "org.openqa.selenium.firefox.NotConnectedException: Unable to connect to host 127.0.0.1 on port 7055 after 45000 ms. Firefox console output:

    Error: cannot open display: :99.0"

    which is weired, because in travis blog, they use the export first:

    http://docs.travis-ci.com/user...

    So... any ideas what could be wrong with my config? Any missed steps that are considered obvious here and I may lost in my way? :S

    Thanks! :)

  • 2014-04-08 weaverryan

    You're right about the potential slowness of creating your own logic - that's one of the best things (speed) of using the native ACL's. Unfortunately, we've never given the ACL's much love in the documentation, but I have seen a few people using them successfully.

    Good luck mate!

  • 2014-04-07 Cassiano Tartari

    Thank you so much for the answer!!
    I will try to use a mix of permission technologies, the ROLE and ACL permission. The role to control globally the access to classes, like media and other stuff. It is good because I'm using SonataAdminBundle and it work with roles to show menus, edit, list... And ACL to control access to medias in user level. I am studying very hard the docs about ACL and I will try to create a GroupSecurityIdentity that is related with the group of roles from FOSUserBundle and is related to users. Because my idea is create a easy permission set interface to users. So, set permission to groups of users sometimes will me more interesting than set user by user. And like you said, ACL has a very complex logic with your bitmasks mappings and other stuffs. So I will try to create a voter that can handle ROLES and ACL with an affirmative strategy.

    My only afraid to create my own logic is the slowness that can exist in a huge database. This system will be used in a digital media archive with external storage.

  • 2014-04-07 weaverryan

    Hi Cassiano Tartari!

    I'll see if I can try :).

    There are 2 types of permissions to consider:

    A) Global permissions. For example, if I give some permission (e.g. "ROLE_MEDIA_EDIT") to a user, then that user can edit *any* media in the system. When I say "global", I mean "a user has a permission regardless of the media - they can always or can never do something".

    B) Data-specific (Media-specific in your case) permissions: This is when the decision of "should the user be able to "edit" a Media depends on the Media itself. I may be able to edit Media id #1, but not Media id #2 (perhaps because I "own" Media id #1, but not #2 - whatever specific logic you have).

    If what you need is (A), then use FOSUserBundle and its Group and User relationships. This allows you to assign a role (ROLE_MEDIA_EDIT) to a user *or* to a group (then assign the user to that group).

    If what you need is (B), you're fine to still use FOSUserBundle. BUT, the Group functionality will not help you. In this case, you should model your database however makes sense for your app - perhaps every Media has an "owner" property that is a ManyToOne relationship to User, or perhaps there is a ManyToMany relationship between Media and User, which defines all of the Users that can "edit" that Media. Perhaps you even go a little crazier and have a MediaPermission table, with a media ManyToOne property to Media, a user ManyToOne property to User and a column called "permission" (which you fill with a string like EDIT, DELETE, etc). Regardless, once you're done, you'll use a custom voter to actually hold your logic (e.g. the logic that says "yes this user can edit this Media because the User can be found in the ManyToMany relationship between User and Media). We have a relatively new cookbook article on using voters like this in the official docs: http://symfony.com/doc/current...

    For situation (B) - especially if you have the complex "MediaPermission" setup - you're basically starting to recreate Symfony's ACL functionality (http://symfony.com/doc/current.... But the ACL's are *very* complex, and so doing a custom voter is a good solution :).

    I know this is a lot of information, but I hope this helps start to guide you!

  • 2014-04-02 Cassiano Tartari

    Hello! Great post! Thank you!

    I'm reading for 3 days and I'm still without know the best practice or if Symfony provides some tool for my question.

    I'm coding a media storage system and I need to control media permissions by user and groups of user. ACL do a great job but it doesn't fit exactly for what I need. I would like to give the same permissions that I can do for a user to a group of users. I'm using FOSUserBundle, there are group of roles and I can set a group for a user. But I would like to set read, edit, delete to a group for a media.

    Can you help me? Thanks!

  • 2014-02-13 Alan

    I spent 10 hours trying to find a solution to my problem and found it on this post. This is VERY helpful, thank you very much.

  • 2014-02-10 leevigraham

    "You still have the issue of knowing when something was a temporary failure versus a one-time failure"

    True. I had a quick think about that and thought you could either increment the filename or even add a new header to the email and re-encode.

  • 2014-02-10 weaverryan

    leevigraham I think that's very interesting. And with the console events, I think you could do this even easier (i.e. even without making a new Swift plugin) - create a listener on `ConsoleEvents::EXCEPTION` that does exactly what you're saying.

    You still have the issue of knowing when something was a temporary failure versus a one-time failure, but you could certainly add some little local storage in the listener to know whether or not this was the first failure of a mail, or the 10th failure.

    So yea, good thoughts! Untested for me as well, but it makes sense!

  • 2014-02-10 leevigraham

    Throwing this out there (untested)…

    Given that

    1. `AbstractSmtpTransport ` throws an Exception: https://github.com/swiftmailer...
    2. and the Logger plugin catches these exceptions could you:
    3. create a new logger plugin which implements Swift_Plugins_Logger

    4. catch the exception
    5. delete the file

    Thoughts?

  • 2014-01-18 weaverryan

    Hi Mirza Selimovic

    In the access_control you have here, the host ^\.mydomain.com has the opening "^", which means it will only match hosts that start with .mydomain.com. If you remove that, it should only match your subdomains (since your base domain doesn't have a "." before the domain). Still, be careful, because only one access_control entry matches per request. So with the 2 access_control entries you have here, going to "/login" of a subdomain would *not* be secure (because the first entry matches). Of course, that's exactly what you want in this case. But just be careful with this :).

    If you really can't get access_control to work for you, you could also register your own event listener, and throw an AccessDeniedException in that listener if the user should not have access, based on whatever logic you need.

    Cheers!

  • 2014-01-16 Mirza Selimovic

    Hi, thanks for the article !
    I'm doing exactly the same thing expect that I have to secure each subdomain.
    The users from foo.mydomain.com can't connect to bar.mydomain.com that's ok I have solved the problem with a custom UserManager but, what should the firewall/access_control looks like to secure every subdomain but not the base domain ?

    I'm trying this but it doesn't work :

    fos:
    pattern: ^/
    host: ^\.mydomain.com
    form_login:
    provider: fos_userbundle
    csrf_provider: form.csrf_provider
    use_referer: true
    logout: true
    anonymous: false

    access_control:
    - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { host: ^\.mydomain.com, path: ^/, roles: ROLE_USER }

    Any suggestions ?

  • 2014-01-13 gondoSVK

    hello
    would you be able to help me with this symfony2 form problem?
    http://stackoverflow.com/quest...

    thanks

    weaverryan

  • 2013-12-17 Sargath

    Thx for repair!

  • 2013-11-27 SimonSimCity

    Just to complete this ... I found the answer to the last question:

    It takes thousands of dinosaurs millions of years......cos they have to evolve deposable thumbs so that they can grip the bulb to screw it in.

  • 2013-11-11 weaverryan

    Hey gondoSVK

    No worries :). Yes, to me, it sounds like a Callback validator would be a really good idea. The article you're linking to is also concerned about HTML5 validation (e.g. the required attribute). In your situation, just use a Callback validator so that you have working server-side validation and make sure the required HTML5 attribute is never there. This should work perfectly, and is nice and easy!

    Cheers!

  • 2013-11-11 gondoSVK

    :) sorry, i did not realize that there is no 1 discussion per problem.

    i was referring to "Conditionally Requiring a Form Field in Symfony2"
    http://knpuniversity.com/scree...

    more specifically im trying to make a form fields required (starting state is not required) based on checkbox value (if checkbox is clicked) in the same form. but i guess i should just use custom form validation, i guess "Callback validation" seems to be the best candidate here, unless you have better solution?

    anyways, great page with lots of helpful resources so far
    thanks

  • 2013-11-11 weaverryan

    Agreed - I've emailed Travis before and there were awesome. And yes, the built-in PHP web server is much easier. I did try it and starting getting some build errors with my tests, but strictly speaking, it should likely work just fine. It may be a bit slower than Apache, but my guess is that it's probably not a noticeable difference.

  • 2013-11-11 weaverryan

    Hey gondoSVK!

    Which issue are you talking about? The conversation probably seems chaotic because (a) people were originally posting questions here and (b) right now we have the same comment stream for each chapter. We're thinking about changing that so that each page has its own comments :).

    Cheers!

  • 2013-11-11 gondoSVK

    so is there any working solution for this problem? the discussion seems to be quite chaotic and unrelated to this post btw

  • 2013-11-07 weaverryan

    Hi @Sargath!

    Yep, this screencast is free. And well, most of the chapters here are just text answers - only one of them actually has a screencast :). What problems are you having?

    Cheers!

  • 2013-11-07 Sargath

    This screencast is free right ??? hmm I get some problems about buying this screencast on some questions choice ....

  • 2013-08-16 Brayden Williams

    You can simplify your builds hugely if you use PHP 5.4's built in web server instead of jumping through hoops installing apache2. Also, if you are having trouble getting things set up properly, email Travis and ask them to boot you a VM.

  • 2013-08-02 Cayetano Soriano Gallego

    You can do that through the finishView method with something like this, for the selected field

    public function finishView(FormView $view, FormInterface $form, array $options)
    {
    if ($form->getData()->getId()) {
    // this is not new, so make it not required
    $view->offsetGet('photo')->vars['required'] = false;
    }

    }

  • 2013-08-02 nikunj

    How change view on basis of user role in symfony2

  • 2013-06-27 weaverryan

    Hey @d8c39eaab53d4ff54bb423d1e5abe5ed!

    Yes, you're absolutely right! It's not anything related to Symfony 2.3, I just missed adding the `use Doctrine\ORM\EntityManager` at the top of that class. I've updated that chapter - so you can take a look at the corrected code now.

    Thanks for pointing that out!

  • 2013-06-20 Rob

    Thanks for the tutorial. I found that the CurrentSiteListener.php was missing the Doctrine class. It was looking for it in the set NameSpace. I'm not a Symfony Exert by any means. Am I missing something or is this something related to version 2.3?

  • 2013-06-07 Sergey Vershinin

    Hello!

    i have a difficult question about extra routing and i hope that You help me to choose a right way..

    In our project we have a difficult routing rule.

    In example, we have a base domain "superdomain". Our project must "understand" {region}.superdomain.{zone} host - i guess it`s solved by

    _acme_demo:

    resource: "@AcmeDemoBundle/Resources/config/routing.yml"

    host: "{region}.superdomain.{zone}"

    defaults: {region: vrn, zone: dev }

    $region = $this->getRequest()->get('region');

    $zone = $this->getRequest()->get('zone');

    {{ url('_welcome', {region: 'kharkov', zone: 'com'}) }}

    It works, but we also have a special promo sites and they have a own routing.

    Promo sites host could be "{megapromo}.superdomain.{zone}" or "{megapromo}.{zone}"

    and these promo sites must use a special routing in PromoBundle ..

    so i can`t understand How handle and process special promo sites routing :(

    i guess i must extend a Routing object or UrlMatcher or Dumper, but i have no idea how..

    p.s. sorry for my English

  • 2013-05-10 Azeem

    thx, sorry realized the date after posting. Loved your symfony videos. So far the best once out there. I tried linda.com but yous were way more helpful. Hope you guys do more videos soon. Would love to see some topics covered e.g., processing third party APIs via crons or writing Restful APIs etc. I've been telling everyone about knpuniversity.

  • 2013-05-10 weaverryan

    Hi Azeem!

    We're all done with KnpU QA day, but this is a nice question.

    First, there is now an official package you can use to get Twitter Bootstrap direclty: https://packagist.org/packages.... If you use it, you'll need to create a symbolic link from your vendor directory into your web directory so that they're publicly accessible (this isn't the only way to do this if you're using Assetic, but by far the easiest).

    In my projects, I usually just commit bootstrap the the repository. It's small and saves me the trouble of trying to manage bootstrap's dependencies. The MopaBootstrapBundle is nice because it gives you other things, like form integration. But overall, I find it to be pretty "heavy-handed" for bringing in a CSS library. I do reference it to bring in things I want, but I don't use it.

    Also, if you're looking or something to manage your CSS dependencies, try: http://bower.io/

    Good luck!

  • 2013-05-09 Azeem

    what's the best way to integrate Twitter Bootstrap with Symfony2? http://bootstrap.braincrafted.... and http://knpbundles.com/phiamo/M... seem to be the most popular -- which one would you recommend?

  • 2013-04-18 weaverryan

    Yo Peter Rehm

    You're right that AccessDecisionManager calls `supportsAttribute` on each voter inside its `supportsAttribute` method. However, last time I checked, nothing in the framework actually *uses* this function and all the voters are called regardless of their `supportsAttribute` method. So, that's the confusing part - they *are* called... just not by a function that anyone else calls ;).

    I agree that the only cookbook on this topic is not fully adequate (http://symfony.com/doc/current... - I think we probably need an additional article that covers something that actually uses a custom attribute.

    Cheers!

  • 2013-04-18 weaverryan

    Hi @6525119e9fb009c9fb3ca1454a0db5be! Thanks for the nice message :). We're not sure if or when we'll do this again - but watch us on Twitter or the newsletter and you won't miss out. And yes, more screencasts and other changes are coming soon - we'll say more when we know a bit more!

    Cheers!

  • 2013-04-18 weaverryan

    Hey Tiago Brito

    The solution depends on what you need to do and each part is handled differently. And yes, this stuff can get very very complex, so work up little by little if possible. The most advanced use-cases are much beyond what we can cover in a short response.

    1) If you want to change the logic, you'll just need your own user provider: http://symfony.com/doc/current.... We also cover this in Episode 2 (http://knpuniversity.com/scree... - where we load a user by username or email. That's a pretty simply example - but this will fit a lot of use cases.

    2) If you need to change the logic behind checking a password, you have a few options. One fairly easy one that you might try is by overriding the default "UserChecker". This class is called before and after the password is checked (see UserAuthenticationProvider::authenticate) and allows you to throw different types of exceptions if you determine - for some reason - that the user shouldn't be authenticated. By default, this checks to see if your User class implements AdvancedUserInterface to force a few checks, but you could add whatever checks you want.

    3) If things get much more complex than this, then you may need your own custom "authentication provider", which holds all the logic for checking passwords, etc etc.

    That's quick, but I hope it helps!

    Cheers and thanks for the nice words!

  • 2013-04-17 Tiago Brito

    Hi there, I'm a big fan of Knpuniversity, great work!

    I have a question, any I think you can help me.

    I want to allow user to login into my SF2 app, but I want to add an additional logic to the password and user match (which comes out of the box with security component), I also want to check the has a certain age.

    Want is the best practice?
    Should I implement a custom UserAuthenticationProvider?

    Can you recommend any video in particular?

    Thanks in advance ;)

  • 2013-04-15 roxana

    Hey everyone!! I just wanted to ask when do we get to ask other questions if this time the deadline was March?!?! And if and when are you planning to make other screencasts?! Could you give some suggestions?! Thanks!! Bye!!!!

  • 2013-04-11 Peter Rehm

    Are you sure about that? In the AccessDecisionManager there seems to be a call on supportsAttribute.

    I have definitely not found anything suitable in the docs, and would suport with that if I am going the right way.

    Can you cross check if its a bug or lack of documentation? Than I can support with that.

  • 2013-04-10 xdrew

    Thanks!

  • 2013-04-10 spolischook

    Thanks Rayan, It's awesome, and its work!!! Only I add:
    - cp app/config/parameters.yml.dist app/config/parameters.yml
    All work like a charm!

  • 2013-04-10 weaverryan

    @192e935d8bee6e80d55c577a4b26d9a7 The voters work oddly (quite possibly a bug actually). The "supportsAttribute" is basically never used in the core, and your "vote" function is *always* called, which means that you need to manually call your "supportsAttribute" inside your vote function and abstain if it returns false. If this isn't in the cookbook article, it should be - if you can open an issue at least, that would be awesome! It's definitely a "gotcha" with the voters :).

    Cheers!

  • 2013-04-10 Peter Rehm

    In your post http://knpuniversity.com/scree... you are showing the possibilities with voters in the security configuration.

    However the Symfony cookbook does not show how to properly invent a custom attribute. If you just modify to like

    public function supportsAttribute($attribute)
    {
    return 'ENTITY_ACCESS' === $attribute;
    }

    the vote() function will always be executed always. The only way is to access the supportsAttribute within the vote function and act accordingly. Is this wanted behaviour? If so, it might make sense to add this to the cookbook entry - if you want I can help out on this, just let me know.

    Peter

  • 2013-04-05 weaverryan

    The "Page" model of working with Behat is very interesting, and anyone who is new to it should check it out for him/herself via the brand new "Page Object Extension": http://extensions.behat.org/pa...

    I have no big opinion on this - it looks very nice, and Jakub Zalas (the guy who wrote it) is very smart! So, check it out!

  • 2013-04-05 weaverryan

    Hi xdrew !

    I'm sorry we didn't have time to get to your question. Many people disagree with me, but I do not bring in my JavaScript dependencies with Composer. I either download them directly and commit them, or have started to use bower: https://github.com/twitter/bow....

    Regardless, I don't believe that any JS file should contains code that actually points to images (or cursors in this point) - the JavaScript library should add classes, and then a different CSS file should reference the image (or cursor) and attach it to that class. For CSS files, these paths should always be relative (e.g. ../images/foo.jpg), and as long as the CSS file doesn't live in a vendor directory (again, I don't install them via Composer), then it's easy for you to change out the image (or cursor) that's located at that spot.

    So, my overall answer is to avoid this issue and don't install via Composer. Additionally, if you have JS code that references assets like this, I think that's not a great JS library - you might try to find something else. And if you do ned to use it, commit it to your repository and modify it. Yes, that's "wrong", but if the JavaScript library you're using is making your life hard, it's worth it. And with git history, if you upgrade, you have a log of what needs to change.

    Good luck!

  • 2013-04-05 Christian

    Hi Ryan, thanks for your advise. I'll take a closer look and consider your feedback :)
    This question was rather specific, i've followed the qhole weeks Q&A topics, good pick!

    Thanks & Greetings from Germany,
    Chris

  • 2013-04-05 weaverryan

    Hi Jorge Vahldick !

    I'm sorry we didn't have time to get to any of your questions, but let me try to offer a little bit of advice!

    1) Your best source for dynamic form stuff with the event dispatcher is here: http://symfony.com/doc/current.... You've probably read this article before, but we just added several big sections to it - so read it again! :)

    2) If you have "extra" data that you need in a form, you have 2 options:

    a) Instead of using some existing Entity for your form, create an entirely new Model class that has the exact fields you need, and connect this with your form. After bind(), you will need to do some work to take the data off of this new Model class and use it, but your form will be simple.

    b) If you just have a few "extra" fields, mark those fields as "mapped" => false. For example:

    $builder->add('payment_method', 'text', array(
    'mapped' => false
    )

    This will avoid the extra fields error. Then, to get your data later, simply say in your controller:

    $paymentMethod = $form['payment_method']->getData()

    3) I'm not sure about your last question unfortunately - I'm not totally sure what the situation is :/

    Thanks and good luck!a

  • 2013-04-05 weaverryan

    Hi Christian

    I'm sorry we didn't get to your question! But let me see if I can help a little bit :).

    First, no, form field order - at least at this time - is not meant to be something that really controls order. I think the official answer to this would be that you need to take care of ordering when you render your form - meaning that `form_widget(form)` or `form_rest(form)` will not be good enough.

    You can see a working pull request to change this, along with references (in the description of the ticket) to other people asking about this: https://github.com/symfony/sym...

    My only suggestion would be to pass an array of the field names (in your preferred order) into the view. It's too much work to show here, but basically:

    1) Override `finishView` in your form class. The `$view` variable here is a `FormView` object, with a public `children` property. The `children` property is an associative array holding a FormView object for all of your fields. You can simply re-order this `children` array however you want to, and when you render, they will render in your order!

    2) Repeat this in all embedded form classes.

    3) Celeberate!

    My disclaimer is that I've never tried this - but with a little effort and love, it looks like it should work just fine :).

    Good luck!

  • 2013-04-05 weaverryan

    Hi Malian!

    We didn't have time to get to your question unfortunately (which was actually a really interesting one)!

    But, I can at least offer a little direction :). When I do this, I typically have some sort of a "Configuration" service. This service might have a method like `get($key)` that allows you to get some configuration by its key/name. The "Configuration" service would have access to the EntityManager, and would query for things as needed. This has a nice advantage that you can also put caching into the Configuration service to save performance.

    There are a few other more "technically" correct ways to do things. Technically, you want to inject only the smallest amount of things into a service that it needs. So if I have a service called `NewsletterManager`, and it needs 2 different keys from my database configuration, then I should inject *only* those 2 keys instead of injecting this whole Configuration object. This can be done with a little more work with something called a configurator (http://symfony.com/doc/current.... This would allow your new NewsletterManager service to be automatically passed to the Configuration object, which could then give it *only* the 2 pieces of information it needs. It's a bit more advanced, but a really fun feature.

    Good luck!

  • 2013-04-05 weaverryan

    Hey Audrius!

    I know we pinged you on Twitter, but for reference - your answer is here: http://knpuniversity.com/scree...

    Cheers!

  • 2013-04-04 Kevin Bond

    "...don’t fool yourself by thinking that you can separate your features into totally standalone, decoupled bundles." I fooled myself once and regret it almost daily...

  • 2013-04-03 pieter lelaona

    greate... thank you soo much..

  • 2013-04-03 Gerard Araujo

    Thanks, well played on question 3 :)

  • 2013-04-03 KnpUniversity

    And here it is! http://knpuniversity.com/scree...

    Cheers!

  • 2013-04-03 weaverryan

    @twitter-12162742 I think the answer to this is unfortunately easy: it's not possible :). Ultimately your resource needs to make it into TwigRendererEngine as either a "defaultTheme" (and array of these are passed to the constructor) or as a "theme" (via setTheme, which is specific to a specific FormView instance).

    The "defaultThemes" passed to the constructor are filled in by a `twig.form.resources` parameter, which is set in TwigExtension from the `twig` form resources stuff. So, there's basically no hook point into any of this, short of adding a compiler pass that mutates this argument after the container is built. So yes, I suppose it *is* possible, though it may be a question of whether this is too heavy-handed or not :).

    Cheers!

  • 2013-04-03 Gerard Araujo

    @twitter-429749331 , I'm really looking forward to the answers for this, thanks.

  • 2013-04-02 Jorge Vahldick

    Explain better:
    Form with "sub-forms", how payment method and extra information.

    In accordance with the chosen form of payment, it needs add new forms, how data extra.
    On my case:
    - credit card payment method
    - more data how credit card number

    The payment may be modified as part of the same form, but occur error like: "This form Should not contain extra fields."
    Example: when i choose financial transfer (between banks)

    I solved working with the session, but I believe that is not the best solution.

    Could you show an example like this?
    And how to work same "POST BIND" validation,not validating the children form at first bind if the form has children.

  • 2013-04-02 KnpUniversity

    Woo!! Your answer is live: http://knpuniversity.com/scree...

  • 2013-04-02 piter lelaona

    hi thanks.. i will wait the answer.. :)

  • 2013-04-01 KnpUniversity

    Happy Monday @acd95cccc60a3bceabbb74110dd2f3fa ! Your question has an answer: http://bit.ly/sf2-RAD

  • 2013-04-01 KnpUniversity

    Hello @0f36cd3c7e16a42dc93feceadc339c98 ! No fooling, your answer has arrived! http://bit.ly/Xm5ZAS

  • 2013-03-31 Gerard Araujo

    Sounds good. about question 1. by fos extension, i mean fosuserbundle :)

  • 2013-03-30 dbu

    uh, i notice that the gist is incomplete. i am extending the FileType form element. when creating an entity with a file in it, i want the file to be required. when editing that entity, it already has the file as it was required when creating it. the way file upload and forms work, it won't see the file is already there. if the form element is required, the user would have to re-upload the file each time he changes anything in the form. so the idea is to force uploading the image file for the create case, but not for the edit case. and i want to do this in a form type, not manually where i build the form. (the reason for that is here: https://github.com/symfony-cmf..., but in general i think it would be more elegant if the form element would handle this.)

  • 2013-03-29 Malian

    How to manage some settings in a database that can be used throughout the application? Whether it's for a specific bundle or not. Thank you!

  • 2013-03-29 Christian

    Is there an easy way to manipulate form field order when using inheritance for your form classes? There's many common elements, thus inheritance saved us lots of work.
    To render the forms we're using {{ form_rest(form) }}.
    Works quite handy, as long as we don't want to change order of some specific elements... Welcome for any form magic :) Thanks! @weyandch

  • 2013-03-29 weaverryan

    This is actually really, really interesting question :). But, I wanted to find out your end goal. Of course the Form::isRequired can be used anyway you want, but out-of-the box, it's only used to set the "required" FormView variable and in the logic for a field's "empty_data". I know you're not worried about the latter, since in the event listener callback, you're already assuming that there's data (so obviously it was never empty). So then, what is the true reason behind wanting to set the required option dynamically?

    Let me know - this has been a fun one to dig around in :).

    Cheers!

  • 2013-03-28 KnpUniversity

    Your answer is now published! :)

  • 2013-03-28 Philipp Rieber

    WOW! Thanks a lot for discussing my question in such detail - I'm not even able to read all at once ;-) Fortunately we'll have the easter weekend right ahead... :-) http://knpuniversity.com/scree...

  • 2013-03-27 KnpUniversity

    Wow! This is a great big question, and we'll do our best to answer it on Monday (April 1) :)

  • 2013-03-27 KnpUniversity

    Thanks for the RAD question to KnpU Q&A! We'll get your answer posted on Monday (April 1) :)

  • 2013-03-27 KnpUniversity

    We love form questions! And your answer will be posted on Monday (April 1st)!

  • 2013-03-27 KnpUniversity

    Awesome questions! We have some field research to do on #3 this weekend and your answers will be posted on Tuesday, April 2nd :)

  • 2013-03-27 KnpUniversity

    Thank you for the great question! Your answer will be in tomorrow's release (Thursday March 28) :)