Attempted to call function from namespace symfony

2019-05-24 17:27发布

问题:

I try to use the functions TechParentInsert in the controller I am getting an error:

Attempted to call function "TechParentInsert" from namespace "TestyBundle\Controller".

500 Internal Server Error - UndefinedFunctionException

In controller I have: "use TestyBundle\Repository\TechParentRepository;" when i've defined "TechParentInsert"

What am I doing wrong?

-----------------------------My CODE

Controller TestyController:

namespace TestyBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\Query\AST\Functions\ConcatFunction;
use Doctrine\ORM\EntityRepository;


use TestyBundle\Entity\Sort;
use TestyBundle\Form\SortType;
use TestyBundle\Repository\SortRepository;
use TestyBundle\Repository\TechParentRepository;

/**
 * @Route("/testy")
 *
 */
class TestyController extends Controller
{
    /**
     * (other actions )
     *
     */


    /**
     * @Route(
     *     "/parent/{parent}", name="TEST_sort_new"
     * )
     *
     * @Template
     */
    public function TechParentNewAction( Request $request, int $parent = 0 )
    {
            $repo2  = $this->getDoctrine()->getRepository( 'TestyBundle:Sort' );
            $sortNew = $repo2->findOneBy( ['zz' => 0]);

            $sortNew->setParentString( $sortNew->getParentString( ) . (string) $sortNew->getId() );
            $sortNew->setZz( 1 );

            $newRecordID = $sortNew->getId();

            $op1 = TechParentInsert( $newRecordID );

            $em->persist( $sortNew );
            $em->flush();

            return $this->redirect( $this->generateUrl( 'TEST_sort' ) );
        }

        return  [ 'data1' => $sortNew ];
    }

}

Repository: TechParentRepository

<?php
namespace TestyBundle\Repository;
use TestyBundle\Entity\TechParent;

class TechParentRepository extends \Doctrine\ORM\EntityRepository
{
    public function TechParentInsert( $idsort)
    {
        $parent = new TechParent();

        $parent->setIdSorty( $idsort);
        $parent->setIdParent( $idsort);
        $parent->setIsOwn( TRUE);

        $em = $this->getDoctrine()->getManager();

        $em->persist($parent);
        $em->flush();

        return 1;
    }
}

My entity: TechParent

<?php
namespace TestyBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * TechParent
 *
 * @ORM\Table(name="tech_parent")
 * @ORM\Entity(repositoryClass="TestyBundle\Repository\TechParentRepository")
 */
class TechParent
{
/**
 * @var int
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var int
 *
 * @ORM\Column(name="idSorty", type="integer")
 */
private $idSorty;

/**
 * @var int
 *
 * @ORM\Column(name="idParent", type="integer")
 */
private $idParent;

/**
 * @var bool
 *
 * @ORM\Column(name="isOwn", type="boolean")
 */
private $isOwn;


/**
 * Get id
 *
 * @return int
 */
public function getId()
{
    return $this->id;
}

/**
 * Set idSorty
 *
 * @param integer $idSorty
 *
 * @return TechParent
 */
public function setIdSorty($idSorty)
{
    $this->idSorty = $idSorty;

    return $this;
}

/**
 * Get idSorty
 *
 * @return int
 */
public function getIdSorty()
{
    return $this->idSorty;
}

/**
 * Set idParent
 *
 * @param integer $idParent
 *
 * @return TechParent
 */
public function setIdParent($idParent)
{
    $this->idParent = $idParent;

    return $this;
}

/**
 * Get idParent
 *
 * @return int
 */
public function getIdParent()
{
    return $this->idParent;
}

/**
 * Set isOwn
 *
 * @param boolean $isOwn
 *
 * @return TechParent
 */
public function setIsOwn($isOwn)
{
    $this->isOwn = $isOwn;

    return $this;
}

/**
 * Get isOwn
 *
 * @return bool
 */
public function getIsOwn()
{
    return $this->isOwn;
}
}

回答1:

Since autowiring in Symfony 2.8 and moreover Symfony 3.3 (May 2017) there is much cleaner way to pass dependencies to controller.

1. Controller

namespace TestyBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

use TestyBundle\Repository\SortRepository;
use TestyBundle\Repository\TechParentRepository;

final class TestyController extends Controller
{
    /**
     * @var SortRepository
     */
    private $sortRepository;

    /**
     * @var TechParentRepository
     */
    private $techParentRepository;

    public function __constructor(
        SortRepository $sortRepository,
        TechParentRepository $techParentRepository,
    ) {
        $this->sortRepository = $sortRepository;
        $this->techParentRepository = $techParentRepository;
    }

    public function TechParentNewAction(int $parent = 0)
    {
        $sortNew = $this->sortRepository->findOneBy([
            'zz' => 0
        ]);

        $sortNew->setParentString($sortNew->getParentString() . (string) $sortNew->getId());
        $sortNew->setZz(1);

        $newRecordID = $sortNew->getId();

        $this->techParentRepository->TechParentInsert($newRecordID);

        // redirect etc...
    }
}

2. Controller services registration

# app/config/services.yml
services:
    _defaults:
        autowire: true

    # PSR-4 autodiscovery
    TestyBundle\:
        resource: '../../src/TestyBundle' # located in /src/TestyBundle

And you are ready to go!


You can read about Symfony 3.3 dependency injection (in this case registering services in config and using it in controller) news in these 2 posts:

  • https://www.tomasvotruba.cz/blog/2017/05/07/how-to-refactor-to-new-dependency-injection-features-in-symfony-3-3/
  • https://symfony.com/blog/the-new-symfony-3-3-service-configuration-changes-explained


回答2:

When you're accessing a method from different class you have to use ClassName::method(), but in this case the TechParentRepository has dependecies for sure. Because of dependency injection, there's a best practice in Symfony to define repository as a service and then use it this way:

$techParentRepository = $this->get('tech_parent_repository ');
$techParentRepository->TechParentInsert();

Little advice - good practise also is to name classes uppercase, but methods lowercase, so public function techParentInsert($idsort) would be better.