PhpStorm has a problem when referencing to a Type named "Resource" - phpstorm

PHPStorm version: 2022.2.3 (Build #PS-222.4345.15, built on October 5, 2022)
I have following class:
<?php declare(strict_types=1);
namespace App\API\Resources;
final class ConfiguredResourceFinder implements ResourceFinder
{
/** #var $resources Resource[] */
private array $resources;
public function find(string $key): Resource
{
foreach ($this->resources as $resource) {
$resource-> // public method suggestion from type Resource not appearing
}
}
}
And following interface in the same namespace:
<?php declare(strict_types=1);
namespace App\API\Resources;
interface Resource
{
public function getKey(): string;
}
When I type $resource->, no method suggestion getKey() is coming.
But when I change the Type, for example to /** #var $resources Foo[] */:
<?php declare(strict_types=1);
namespace App\API\Resources;
interface Foo
{
public function getKey(): string;
}
I receive suggestions:
Any idea why this is not working with the Resource interface? I already invalidated the PhpStorm cache.

Related

FOSRestBundle woes with Symfony4, 204 no content response

I've made a rest controller for Movie objects with a get action.
My database manager one movies with id:3.
When I try to access localhost:8000/api/movie/3 or any other idea for that matter it goes straight back to the page I came from, with only a hint of no content response.
[Tue May 29 16:06:42 2018] 127.0.0.1:61540 [204]: /api/movie/3
I have the following configurations:
services.yaml
services:
...
sensio_framework_extra.view.listener:
alias: Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener
...
routes/rest.yaml
movies:
type: rest
resource: App\Controller\MovieController
prefix: /api
packages/fos_rest.yaml
fos_rest:
param_fetcher_listener: true
allowed_methods_listener: true
routing_loader:
include_format: false
view:
view_response_listener: 'force'
format_listener:
rules:
- { path: '^/api', priorities: ['json'], fallback_format: 'json' }
zone:
- { path: ^/api/* }
packages/framework.yaml:
framework:
...
templating: { engines: ['twig'] }
And the following files:
Controller/MovieController.php
<?php
namespace App\Controller;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Routing\ClassResourceInterface;
use FOS\RestBundle\Controller\FOSRestController;
/**
* #Rest\RouteResource("Movie", pluralize=false)
*/
class MovieController extends FOSRestController implements ClassResourceInterface {
/**
* #Rest\View()
* #Rest\Get("/movie/{id}")
*/
public function getAction(string $id) {}
}
Entity/Movie.php
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\MovieRepository")
*/
class Movie {
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=32)
*/
private $title;
public function __construct($title) {
$this->title = $title;
}
...
}
Debug router is giving me this result:
$ bin/console debug:router | grep movie
get_movie GET ANY ANY /api/movie/{id}
[update]
Due to earlier wrong configurations I encountered the errors:
1
Warning: ReflectionObject::__construct() expects parameter 1 to be object, null given
2
An instance of Symfony\Bundle\FrameworkBundle\Templating\EngineInterface >must be injected in FOS\RestBundle\View\ViewHandler to render templates.
3
Type error: Argument 2 passed to Twig_Environment::render()
must be of the type array
4
There are no registered paths for namespace "FOSRest".
5
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
I had to edit MovieController to return the object or return an exception.
MovieController.php
<?php
namespace App\Controller;
use App\Repository\MovieRepository;
use Doctrine\ORM\EntityManagerInterface;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Routing\ClassResourceInterface;
use FOS\RestBundle\Controller\FOSRestController;
/**
* #Rest\RouteResource("Movie", pluralize=false)
*/
class MovieController extends FOSRestController implements ClassResourceInterface {
/**
* #var EntityManagerInterface
*/
private $entityManager;
/**
* #var MovieRepository
*/
private $movieRepository;
public function __construct(
EntityManagerInterface $entityManager,
MovieRepository $movieRepository
) {
$this->entityManager = $entityManager;
$this->movieRepository = $movieRepository;
}
public function getAction(string $id) {
$movie = $this->movieRepository->find($id);
if($movie === null) {
throw new NotFoundHttpException();
}
return $this->view($movie);
}
}
you should add populateDefaultVars in the view annotation parameters like this :
/**
*
* #rest\View(populateDefaultVars=false)
*/

Having a challenge with Laravel 5.4 requests namespace

I'm trying to reference the Requests class in Laravel, I've tried so many fixes with the keyword "use" but each time I keep getting Reflection exception
that says app\path\specified doesn't exist. I'm confused.
Here is my code:`
<?php
namespace App\Http\Controllers;
//namespace App\Http\Request;
//use Illuminate\Http\Requests;
//use app\Http\Requests\ContactFormRequest;
use App\Message;
use App\Mail\SendMessage;
use Session;
//use App\Requests;
class AboutController extends Controller
{
public function create()
{
return view ('about.contact');
}
public function store(App\Requests\SendMessageRequest $request)
{
$message = $request->message;
Mail::to('myemail')
->send(new SendMessage($message, $request->email,$request->name));
THE REQUESTS CLASS
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class SendMessageRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
//
'name' => 'required',
'email' => 'required|email',
"message" => 'required',
];
}
}
The commented line(//) are what I've tried
SendMessageRequest is the name of my Request class.
Sorry, I can´t comment your post. However can you also send the SendMessageRequest Class? Is that a subclass of the Request in Laravel?

How to implement common method in php?

How to implement a method in a class that can be used by everyone users in php ?
My idea is not to repeat the implementation of readsales in each of the entities
i have 3 users:
admin readSales function,
manager readSales function,
employee, insertSale AND readSales function
Is it possible to implement common methods in a single class? And then call each of the methods to the daughter classes?
abstract class commonMethods {
abstract readSales() {
$pdo = new PDO();
//statements
//readSales
//return $list;
}
}
class Manager extends commonMethods {
function readSales(){
return readSales();
}
}
Yes this is possible, what you need is either a trait or an abstract class.
Here's an example with Abstract class :
<?php
/**
* The abstract class
*/
abstract class CommonMethods
{
public function readSales(){
// Your code
}
public function hello(){
echo "Hello";
}
}
/**
* The Class
*/
class Manager extends CommonMethods
{
// No need to add the "readSales" or "hello" method
// Since we had extended them
public function world(){
echo "World";
}
}
$Manager = new Manager;
$Manager->readSales(); // Works!
$Manager->hello(); // Output: "Hello"
$Manager->world(); // Output: "World"
// The final output: "HelloWorld"
Reference: http://php.net/manual/en/language.oop5.abstract.php

How to pass parameters to mainLayoutAsset.php file?

I have following code in mainLayoutAsset.php file
<?php
/**
* #link http://www.yiiframework.com/
* #copyright Copyright (c) 2008 Yii Software LLC
* #license http://www.yiiframework.com/license/
*/
namespace frontend\assets;
use yii\web\AssetBundle;
/**
* #author Qiang Xue <qiang.xue#gmail.com>
* #since 2.0
*/
class MainLayoutAsset extends AssetBundle
{
public $basePath = '#webroot';
public $baseUrl = '#web';
public $css = [
];
public $js = [
'member-area/AdminLTE/app.js',
];
}
Now I want to access params file parameter in to this file
eg.
public $js = [
'member-area/AdminLTE/app.js?v='.Yii::$app->params["version"],
]
but it giving error
PHP Parse Error – yii\base\ErrorException
syntax error, unexpected '.', expecting ']'
'js/tooltip.js?v='.Yii::$app->params["incFileVersion"],
From PHP documentation about class properties :
They are defined by using one of the keywords public, protected, or private, followed by a normal variable declaration. This declaration may include an initialization, but this initialization must be a constant value--that is, it must be able to be evaluated at compile time and must not depend on run-time information in order to be evaluated.
http://php.net/manual/en/language.oop5.properties.php
You could simply override init() :
public function init()
{
parent::init();
$this->js = [
'member-area/AdminLTE/app.js?v=' . Yii::$app->params['version'],
];
}
And you should may be try this instead.

ninject factory constructor selection with runtime generics

How can I use a ninject factory, which creates an instance with constructor parameters, without relying on the argument names.
The problem is that the ToConstructor()-Method not works, because I bind it to a generic definition.
The following example works, if I use the factory method with the corresponding constructor argument name, but I don't like it rely on names.
Because the following solution is very fragil and breaks if someone chooses a wrong name or renames the ctor-argument in the derived class.
Any solution?
Here's the example code:
[TestFixture]
public class NinjectFactoryBindingsTest
{
[Test]
public void ConstructorSelectionWithArguments()
{
NinjectSettings ninjectSettings = new NinjectSettings();
ninjectSettings.LoadExtensions = false;
using (var kernel = new StandardKernel(ninjectSettings, new FuncModule()))
{
// IDependencyA will be passed to the factory, therefore it is not bounded
//kernel.Bind<IDependencyA>().To<DependencyA>();
kernel.Bind<IDependencyB>().To<DependencyB>();
kernel.Bind(typeof(IGenericBaseClass<>)).To(typeof(GenericDerivedClass<>));
kernel.Bind<IGenericClassFactory>().ToFactory();
IGenericClassFactory factory = kernel.Get<IGenericClassFactory>();
DependencyA dependencyA = new DependencyA();
IGenericBaseClass<GenericImpl> shouldWorkInstance = factory.Create<GenericImpl>(dependencyA);
Assert.NotNull(shouldWorkInstance);
}
}
}
public interface IGenericClassFactory
{
IGenericBaseClass<TGeneric> Create<TGeneric>(IDependencyA someName) where TGeneric : IGeneric;
// This works, but relies on ctor-param-names!!!
// IGenericBaseClass<TGeneric> Create<TGeneric>(IDependencyA otherNameThanInBaseClass) where TGeneric : IGeneric;
}
public class DependencyA : IDependencyA
{
}
public class DependencyB : IDependencyB
{
}
public class GenericDerivedClass<TGeneric> : GenericBaseClass<TGeneric> where TGeneric : IGeneric
{
public GenericDerivedClass(IDependencyA otherNameThanInBaseClass, IDependencyB dependencyB)
: base(otherNameThanInBaseClass, dependencyB)
{
}
}
public abstract class GenericBaseClass<TGeneric> : IGenericBaseClass<TGeneric> where TGeneric : IGeneric
{
protected GenericBaseClass(IDependencyA dependencyA, IDependencyB dependencyB)
{
}
}
public interface IGenericBaseClass<TGeneric> where TGeneric : IGeneric
{
}
public interface IDependencyB
{
}
public interface IDependencyA
{
}
public class GenericImpl : IGeneric
{
}
public interface IGeneric
{
}
The factory extension has the convention that arguments must have the same name as the constructor argument they will be passed to. There are no easy ways to do it differently. The only way I can think of is about the following:
Create a new IParameter implementation that can hold a reference to an IDependencyA.
Create either a hardcoded factory or a custom IInstanceProvider (see documentation) that creates an instance of your IParameter implementation so that it is passed to the Get<> request
Add a new binding for IDependencyA: Bind<IDependency>().ToMethod(ctx => extract and return your parameter from the context)