Symfony " 'use' statement for another namespace?" issue
Asked Answered
W

2

14

I have a problem with namespaces in connecting my entity class to an abstract-type class.

I needed to create an AbstractType Class I called BlogFactory. I intent to use it in my the createAction function of my BlogController.php Entity class for creating blog entries.

My BlogFactory class is created in the Form/Blog directory of my bundle, as the tree structure shows.

.
.
.
src/Blogger/BlogBundle/
├── Controller
│   ├── BlogController.php
│   └── PageController.php
├── DataFixtures
│   └── ORM
│       └── BlogFixtures.php
├── Entity
│   ├── Blog.php
│   ├── Blog.php~
│   └── Enquiry.php
├── Form
│   ├── Blog
│   │   ├── BlogFactory.php
│   │   └── Factory.php
│   └── EnquiryType.php
├── Resources
│   ├── config
│   │   ├── config.yml
│   │   ├── routing.yml
│   │   └── services.yml
.
.
.

In the BlogController.php entity class, I include the following use instruction:

namespace Blogger\BlogBundle\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Blogger\BlogBundle\Form\Blog\BlogFactory;

class BlogController extends Controller{
.
.
.

with the following createAction function:

public function createAction(){   
        $form = $this->createForm(new BlogFactory(), new Blog(), 
            array(
                'action' => $this->generateUrl('blog_create'),
                'method' => 'POST',
            )
        );

        $form->add('submit', 'submit', array('label'=>'Create'));
        return $form;
    }

Here is the code in my BlogFactory class:

namespace Blogger\BlogBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class BlogFactory extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('title');
        $builder->add('author');
        $builder->add('blog');
        $builder->add('image');
    }

    public function getName()
    {
        return 'newblog';
    }
}

However, my problem is I get the following error:

The autoloader expected class "Blogger\BlogBundle\Form\Blog\BlogFactory" to be defined in file "/var/www/Symfony-Blog/src/Blogger/BlogBundle/Form/Blog/BlogFactory.php". The file was found but the class was not in it, the class name or namespace probably has a typo

I'm quite stuck and not sure how to resolve this.

UPDATE:

As suggested by Gnucki, I added namespace Blogger\BlogBundle\Form\Blog; to my BlogFactory.php and use Blogger\BlogBundle\Form\Blog\BlogFactory; to BlogController.php, and got the slightly different error below:

Attempted to load class "Blog" from namespace "Blogger\BlogBundle\Controller".
Did you forget a "use" statement for another namespace?
Whitesell answered 29/12, 2014 at 1:44 Comment(5)
You should be using use Blogger\BlogBundle\Form\Blog\BlogFactory. With no use the new BlogFactory is being treated as in the same directory.Precast
As in the same namespace.Uncanny
In your controller, you need to use Blogger\BlogBundle\Form\Blog\BlogFactory; or need use whole path in create form new BlogFactory()Heartache
Thanks for your responses. Would you mind looking over the code again as I'm certain I'm doing what you suggested but I still get the same error. I apologize because I pasted the wrong abstract class first time around - I have now corrected that.Whitesell
you might have forgotten to install a dependency. This also causes "forget a "use" statement" error.Krone
P
20

There is a problem of mapping between your directories and namespaces:

You say that the class BlogFactory is in Form/Blog/BlogFactory.php and you define the class in the namespace Blogger\BlogBundle\Form.

You should use this namespace for your class BlogFactory:

namespace Blogger\BlogBundle\Form\Blog;

Then specify these use statements in your controller:

use Blogger\BlogBundle\Form\Blog\BlogFactory;
use Blogger\BlogBundle\Entity\Blog;

Explanation:

In a simple PHP application, you use some require or include to include files into each other. But it is really boring. Instead, you can use an autoload function to handle that. Symfony2 implements it in a manner that a namespace is mapped on a directory in a logical way. For instance, class Blogger\BlogBundle\Entity\Blog can be found in /Blogger/BlogBundle/Entity/Blog.php.

If you want to use the class in another one (with another namespace (so another directory)), you can use for example:

new \Blogger\BlogBundle\Entity\Blog();

or:

use Blogger\BlogBundle\Entity\Blog;

new Blog();

Imagine, you are in another namespace whitout that use:

namespace Blogger\BlogBundle\Controller;

new Blog();

The class Blog will be interpreted as class Blogger\BlogBundle\Controller\Blog.

namespace Blogger\BlogBundle\Controller;

use Blogger\BlogBundle\Entity\Blog;

new Blog();

Now, with the use, Blog will be interpreted as Blogger\BlogBundle\Entity\Blog.

See namespaces in PHP for more informations.

Pteridology answered 29/12, 2014 at 10:48 Comment(4)
Thanks Gnucki. I added an update indicating a new error after implementing your suggestion.Whitesell
Add use Blogger\BlogBundle\Entity\Blog; in your controller.Pteridology
Thank you. That got it working. Could you offer some explanation so I better understand how this works and how it fix it - next time? Thanks againWhitesell
I added an explanation. Tell me if it is not clear or if you want some details.Pteridology
K
-1

Note: You can transform

$builder->add('title');
    $builder->add('author');
    $builder->add('blog');
    $builder->add('image');

to

$builder
    ->add('title')
    ->add('author')
    ->add('blog')
    ->add('image')
;
Kunz answered 5/11, 2021 at 19:54 Comment(1)
Would be nice if you'd explain why (so because method returns object itself).Xmas

© 2022 - 2024 — McMap. All rights reserved.