Symfony 5 use getDoctrine() in another Controller - php-7

I try to call "class CltvController" from another class like this :
class StatLtvcController extends AbstractController
{
$cltv_temp = new CltvController();
return $this->render('admin/statltvc.html.twig', [ 'cltv_temp' => $cltv_temp->cltv(), ]);
}
but this class :
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use App\Entity\Game;
use App\Entity\Adventure;
use Symfony\Component\Routing\Annotation\Route;
class CltvController extends AbstractController
{
public function cltv(): float{
$periodh = '2021-06-01'; // $request->request->get('')
$periodi = '2021-07-31'; // $request->request->get('')
$em = $this->getDoctrine()->getManager();
$con = $em->getRepository(Game::class);
$con3 = $em->getRepository(Adventure::class);
$ncnt[] = $con->findByCountncn($periodh,$periodi);
$nadvt[] = $con3->findByCountadv($periodh,$periodi);
return $nadvt[0][0][1]/$ncnt[0][0][1];
}
}
is returning this error :
Call to a member function has() on null
Error
in G:\Mes_TPs\TP_Symfony_PHP\Quaestyo\vendor\symfony\framework-bundle\Controller \AbstractController.php (line 345)
*
* #throws \LogicException If DoctrineBundle is not available
*/
protected function getDoctrine(): ManagerRegistry
{
if (!$this->container->has('doctrine')) {
throw new \LogicException('The DoctrineBundle is not registered in your application. Try running "composer require symfony/orm-pack".');
}
return $this->container->get('doctrine');
}
I don't understand why $this->getDoctrine is returning an error?

Try to add this bloc over CltvController class:
/**
* #method getDoctrine()
*/
class CltvController extends AbstractController {
• If that didn't work, can you tell me the exact version of php & symfony of your project please?

Thanks for your answer. It's the same error message with your solution.Actually, Symfony is calling getDoctrine() in the class StatLtvcController. (i didn't put all because code was too long). How could i call getdoctrine() in the class CltvController ?
I use last versions : PHP 7.4.9 and Symfony 5.2.14

Related

Phpstan is not recognizing my abstract class

I have a request with an authorize method that makes use of:
Illuminate\Http\Request::user()
And it gives me a phpstan error that says
phpstan: Cannot call method hasAnyRole() on App\Models\User|null.
And that makes sense.
So I made an abstract class that makes use of
Illuminate\Http\Request::user()
like this:
<?php
namespace App\Http\Requests;
use App\Models\User;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Http\FormRequest;
abstract class VbpRequest extends FormRequest
{
/**
* Get the user making the request.
*
* #param string|null $guard
* #return User
* #throws AuthenticationException
*/
public function user($guard = null): User
{
$user = parent::user($guard);
if ($user instanceof User) {
return $user;
}
throw new AuthenticationException('Trying to resolve a user, but no one is logged in.');
}
}
In theory this should only return an instance of the User model or an exception.
but when I use this new method it gives me the exact same phpstan warning.
phpstan: Cannot call method hasAnyRole() on App\Models\User|null.
Does anyone have an idea of what is going wrong or could be going wrong?
Here is the Request:
<?php
declare(strict_types=1);
namespace App\Http\Requests;
use App\Models\Role;
use App\Traits\RequestCast;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Validation\Rule;
class BelnotitieRequest extends VbpRequest
{
use RequestCast;
/**
* #throws AuthenticationException
*/
public function authorize(): bool
{
return $this->user()->hasAnyRole(Role::ADMIN_ID, Role::PROJECTMANAGER_ID, Role::ADMINISTRATIEF_MEDEWERKER_ID);
}
}
I'm using Laravel 9.24 and larastan 2.1.12

i wanna do php artisan db:seed, then i got this error " ErrorException array_merge(): Expected parameter 2 to be an array, int given"

I wanna make API Authentication Laravel Passport - Forgot and Reset Password with this source video on Youtube : https://www.youtube.com/watch?v=F9Xmc3iHc88&t=6s
My source Youtube use Laravel 6x, and i use Laravel 8x.
When i do step "seeding and factory database" in minute video 8:17 , i got
ErrorException array_merge(): Expected parameter 2 to be an array, int given
This is my error cmd
this is my UserFactory.php :
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\User;
class UserFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = User::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
'first_name' => $this->faker->firstName,
'last_name' => $this->faker->lastName,
'email' => $this->faker->unique()->safeEmail,
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
];
}
}
this is my UsersTableSeeder.php :
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
class UsersTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
User::factory(App\Models\User::class, 10)->create();
}
}
and my DatabaseSeeder.php :
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* #return void
*/
public function run()
{
$this->call(UsersTableSeeder::class);
}
}
Can someone help me to explain why i got this error merge array?
Case Closed guys, in Laravel 8x u dont need type "
User::factory(App\Models\User::class, 10)->create();
just type :
User::factory(10)->create();
because u already call it User at first word..

Doctrine ORM create method phpspec test failure

I try to write, at first glance, it would seem a trivial test for my repository's "update" method:
<?php
declare(strict_types=1);
namespace Paneric\Authorization\ORM\Repository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\ORMException;
use Paneric\Authorization\DTO\FieldDTO;
use Paneric\Authorization\ORM\Entity\Field;
use Doctrine\ORM\EntityRepository;
use Paneric\Authorization\Interfaces\FieldRepositoryInterface;
class FieldRepository extends EntityRepository implements FieldRepositoryInterface
{
const ENTITY_CLASS = Field::class;
public function __construct(EntityManagerInterface $_em)
{
parent::__construct($_em, $_em->getClassMetadata(self::ENTITY_CLASS));
}
...
public function update(int $fieldId, FieldDTO $fieldDTO): void
{
try {
$field = $this->find($fieldId);
$field->transfer($fieldDTO);
$this->_em->flush();
} catch (ORMException $e) {
echo $e->getMessage();
}
}
...
}
with a spec method:
<?php
namespace spec\Paneric\Authorization\ORM\Repository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\QueryBuilder;
use Paneric\Authorization\DTO\FieldDTO;
use Paneric\Authorization\ORM\Entity\Field;
use Paneric\Authorization\ORM\Repository\FieldRepository;
use Doctrine\ORM\AbstractQuery;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class FieldRepositorySpec extends ObjectBehavior
{
public function let(EntityManagerInterface $_em, ClassMetadata $classMetadata)
{
$_em->getClassMetadata(Field::class)->willReturn($classMetadata);
$this->beConstructedWith($_em);
}
...
public function it_updates(Field $field, FieldDTO $fieldDTO, EntityManagerInterface $_em)
{
$fieldId = 1;
$field = $this->find($fieldId);
$field->transfer($fieldDTO)->shouldBeCalled();
$_em->flush()->shouldBeCalled();
$this->update($fieldId, $fieldDTO);
}
...
}
and receive the following error:
Unexpected method call on Double\EntityManagerInterface\EntityManagerInterface\P1:
- find(
null,
1,
null,
null
)
expected calls were:
- getClassMetadata(
exact("Paneric\Authorization\ORM\Entity\Field")
)
- find(
exact("Paneric\Authorization\ORM\Entity\Field"),
exact(1)
)
- flush(
)
Apparently issue is related to the call:
...
$field = $this->find($fieldId);
...
Although the second remark related to getClassMetadata, looks strange, considering the fact that my spec let method:
public function let(EntityManagerInterface $_em, ClassMetadata $classMetadata)
{
$_em->getClassMetadata(Field::class)->willReturn($classMetadata);
$this->beConstructedWith($_em);
}
does its job in case of other spec tests.
Can anyone help me to solve this issue ? Thx in advance.
In my repository's "update" metod, line:
$field = $this->find($fieldId);
has to be replaced by:
$field = $this->_em->find(Field::class, $fieldId);
so the complete spec test looks like:
public function it_updates(Field $field, FieldDTO $fieldDTO, EntityManagerInterface $_em)
{
$fieldId = 1;
$_em->find(Field::class, $fieldId)->willReturn($field);
$field->transfer($fieldDTO)->shouldBeCalled();
$_em->flush()->shouldBeCalled();
$this->update($fieldId, $fieldDTO);
}

Symfony 3 get current user inside entity

I was wondering if there is a way that i can initialize the property owner with an entity User of FOSUserBundle so that it contains the user who created the Post
I want to do this inside the constructor as shown below.
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="post")
* #ORM\Entity(repositoryClass="AppBundle\Repository\PostRepository")
*/
class Post
{
/* here are defined some attributs */
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="posts")
* #ORM\JoinColumn(name="owner", referencedColumnName="id")
*/
private $owner;
public function __construct()
{
$this->owner = /* get current user */ ;
}
}
Is there a way to do this by replacing the comment in the constructor with something ?
Thank you for your answers
No, there isn't. [*]
There are at least two ways to deal with this:
Create your Post entities through a factory service which populates the
owner property:
namespace My\Bundle\EntityFactory;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use My\Bundle\Entity\Post;
class PostFactory
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function createPost()
{
$user = $this->tokenStorage()->getToken()->getUser();
$post = new Post($user);
}
}
(for this example, you will have to modify your Post constructor to
accept the owner as a parameter)
In services.yml:
services:
post_factory:
class: My\Bundle\EntityFactory\PostFactory
arguments: [#security.token_storage]
To create an entity from your controller:
$post = $this->container->get('post_factory')->createPost();
If you can tolerate that the owner will only be set once you persist the
entity, you can use a doctrine event listener:
namespace My\Bundle\EventListener;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use My\Bundle\Entity\Post;
class PostOwnerAssignmentListener
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function prePersist(LifecycleEventArgs $event)
{
$entity = $event->getEntity();
if ($entity instanceof Post && !$entity->getOwner()) {
$entity->setOwner($this->tokenStorage->getToken()->getUser());
}
}
}
In services.yml:
services:
post_owner_assignment_listener:
class: My\Bundle\EventListener\PostOwnerAssignmentListener
arguments: [#security.token_storage]
tags:
- { name: doctrine.event_listener, event: prePersit }
The advantage here is that the owner gets assigned no matter how and where
the Post is created.
[*]: Well, technically with the default app.php you could access the
kernel by declaring global $kernel; in your constructor and go from there,
however this is very strongly discouraged and may break in strange and subtle
ways.
I think you are way over-complicating this issue. When you create a new Post in your controller, either in the controller or in the repository do something like this:
use AppBundle\Entity\Post; //at top of controller
$em = $this->getDoctrine()->getManager();
$user = $this->container->get('security.token_storage')->getToken()->getUser();
$post = new Post();
$em->persist( $post );
$post->setOwner( $user );
// set other fields in your post entity
$em->flush();
For Symfony 4+ with Autowiring and Entity event listener:
In /EventListener/PostPrePersistListener.php:
namespace App\EventListener;
use App\Entity\Post;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class PostPrePersistListener
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function prePersist(Post $post, LifecycleEventArgs $event)
{
$post->setOwner($this->tokenStorage->getToken()->getUser());
}
}
In services.yaml:
services:
App\EventListener\PostPrePersistListener:
autowire: true
tags:
- { name: doctrine.orm.entity_listener, entity: 'App\Entity\Post', event: prePersist }
Modifying services.yaml is required as Symfony cannot know that this custom service is tagged to hook on doctrine.event_listener
This works at Entity-level as asked, to ensure Controller do not handle the owner value.

Yii Framework - from url to route

I searched, but couldnt find something.
So, I have route rules:
...
'/reg' => '/user/user/registration',
...
in
Yii::app()->request
I couldn find any route information.
So, how can I get in module init function and having only url, route lile
/reg -> user/user/registration
UPD
The route is only available from the running controller. By the time when a module is initialized the controller is not yet available, thus you can't find out the route there. (You can follow CWebApplication::processRequest to see what happens when a request is resolved up to the point where the controller is run.)
It depends on what you try to achieve, but you could override WebModule::beforeControllerAction to do something before the module controller is run.
Today (next day after my question), I could solve this.
I will try to explain:
As Michael wrote, we cant know in module in which controller we are.
But I net get just reversed route, so, its quite esay.
Yii::app()->getUrlManager()->parseUrl('/reg');
This will return my reversed route
user/user/registration
parseUrl
Solution for Yii 1.1.15 workes for me.
class HttpRequest extends CHttpRequest {
protected $_requestUri;
protected $_pathInfo;
public function setUri($uri){
$this->_requestUri = $uri;
}
public function setPathInfo($route){
$this->_pathInfo = $route;
}
public function getPathInfo(){
/* copy from parent */
}
public function getRequestUri(){
/* copy from parent */
}
}
The usage:
$uri_path = 'my/project-alias/wall';
/** #var HttpRequest $request */
$request = clone Yii::app()->getRequest();
$request->setUri($uri_path);
$request->setPathInfo(null);
$route = Yii::app()->getUrlManager()->parseUrl($request);
//$route equals 'project/profile/wall' etc here (like in route rules);
I'm using a slightly different sub-class of CHttpRequest:
class CustomHttpRequest extends \CHttpRequest
{
/**
* #var string
*/
var $pathInfo;
/**
* #var string
*/
private $method;
public function __construct($pathInfo, $method)
{
$this->pathInfo = $pathInfo;
$this->method = $method;
}
public function getPathInfo()
{
return $this->pathInfo; // Return our path info rather than the default
}
public function getRequestType()
{
return $this->method;
}
}
Then to call it (to create a controller, which is what I want):
$request = new CustomHttpRequest($uri, $method); // e.g. 'my/project-alias/wall' and 'GET'
$route = \Yii::app()->getUrlManager()->parseUrl($request);
list($jcontroller, $actionName) = \Yii::app()->createController($route);