VSCode and jsDoc definitions for classes in other files - ecmascript-6

I am super confused about how Intellisense works - sometimes it's "automagic" and sometimes I can never get it to work.
Here's an example where I just can't get it to work:
// item.js
export default class Item {
/**
* Creates an Item
* #param {string} type The item type
*/
constructor(type) {
this.type = type;
}
/**
* Logs the type of this item
*/
outputType() {
console.log(this.type);
}
}
// itemlist.js
import Item from './item';
export default class ItemList {
/**
* Makes an item list
* #type {string[]} items The types of the items to generate
*/
constructor(items) {
/**
* #type {Item[]}
*/
this.items = items.map(i => new Item(i));
}
}
In the above example, in itemlist.js, Intellisense does not know that this.items should be treated as a list of Item objects, and therefore does not autosuggest class properties or methods when I type something like:
this.items[0].
Not even this works in itemlist.js:
const item = new Item('simple');
item.
^ in the above examples there are no Intellisense suggestions for "outputType" or anything related to the item.

Related

Validating JSON input Laravel

I am using laravel , and json input from the client. I would like to know if there is a way to create a form request that does json validation instead of url parameters. I found this class online :
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
abstract class JsonRequest extends FormRequest {
/**
* Get the validator instance for the request.
*
* #return \Illuminate\Validation\Validator
*/
protected function getValidatorInstance()
{
$factory = $this->container->make('Illuminate\Validation\Factory');
if (method_exists($this, 'validator'))
{
return $this->container->call([$this, 'validator'], compact('factory'));
}
return $factory->make(
$this->json()->all(), $this->container->call([$this, 'rules']), $this->messages(), $this->attributes()
);
}
}
Now , when I make a class that extends this instead of Request, I am able to validate. This is an example:
<?php
namespace App\Http\Requests;
use App\Http\Middleware\AuthTokenMiddleware;
use App\Http\Requests\Request;
use Illuminate\Support\Facades\Input;
class VotesCreateRequest extends JsonRequest
{
public function response(array $errors)
{
//
return response()->json(["error_list" => $errors], 200);
}
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{return true;
if(AuthTokenMiddleware::getUser()->can('access-group',Input::get("grp_id"))){
return true;
}
else{
return false;
}
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'sub_items'=>'required|array',
'sub_items.*.email' =>'required'
];
}
}
But I want to know how to validate items inside items of the json file .
For example, i have :
{"sub_items":["something","another thing","yet another","another ","last"]}
How do I validate if all these items in sub sub_items are of type email ?

Creating a one-to-many relationship in Yii2

Let's say we have two entities: User and Post.
In my understanding, in order to have a one-to-many relationship between User and Post, you need to do the following:
class User {
...
public function getPosts()
{
return $this->hasMany(Order::className(), ['user_id' => 'id']);
}
}
class Post {
...
public function getUser()
{
return $this->hasOne(Order::className(), ['id' => 'user_id']);
}
}
Is this right? Is there anything else I need to add in order to make everything work? The Yii2 documentation is not very clear to me.
Yes, this is enough (except that you inserted Order class name instead), however it's also recommended to add PHPDoc for relations:
User model:
/**
* ...
*
* #property Post[] $posts
*/
class User
{
/**
* #return \yii\db\ActiveQuery
*/
public function getPosts()
{
return $this->hasMany(Post::className(), ['user_id' => 'id']);
}
}
Post model:
/**
* ...
*
* #property User $user
*/
class Post
{
/**
* #return \yii\db\ActiveQuery
*/
public function getUser()
{
return $this->hasOne(User::className(), ['id' => 'user_id']);
}
}
Then when you will call $user->posts or $post->user you will get full autocomplete if you are using IDE. It's also useful because you can see the relation list just by looking at the top of the file, because relations accessed as virtual properties, $user->getPosts() call will return yii\db\ActiveQuery object and not \yii\db\ActiveRecord array. It's better to separate them with linebreak from model attributes (they are also added for autocomplete and seeing the structure of according database table without looking at database).
By the way, if you generate model with Gii, if you specified foreign keys correctly, relations and PHPDoc will be generated automatically.
Note that if you don't need to use $post->user, you can omit user relation declaration in Post model. You can declare relations that are only needed for usage.

Yii2 missing required parameter in a constructor

I've created a new XmlResponseFormatter and now I want to change the rootTag.
class newXmlResponseFormatter extends XmlResponseFormatter
{
/**
* #var string the name of the root element.
*
*/
public $rootTag;
public function __construct($rootTag) {
parent::__construct();
$this->rootTag = $rootTag;
}
}
From a controller I set that value:
$xmlFormater = new newXmlResponseFormatter('newRootTag');
In the controller that value is available, and it sets in $rootTag but it threw the following exception:
exception 'yii\base\InvalidConfigException' with message 'Missing required parameter "rootTag" when instantiating "app\components\override\newXmlResponseFormatter".' in /var/www/html/Admin/vendor/yiisoft/yii2/di/Container.php:451
Does anyone know what can be a problem?
Thanks in advance!
First parameter in XmlResponseFormatter is $config, because XmlResponseFormatter extends Object class. You are violated liskov substitution principle.
You should rewrite your constructor like this:
class newXmlResponseFormatter extends XmlResponseFormatter
{
/**
* #var string the name of the root element.
*
*/
public $rootTag;
/**
* newXmlResponseFormatter constructor.
*
* #param string $rootTag
* #param array $config
*/
public function __construct($rootTag, $config = [])
{
$this->rootTag = $rootTag;
parent::__construct($config);
}
}
In yii2 you should call parent constructor after your code, and call parent init before your code.
$config need for simple configure model like this:
new newXmlResponseFormatter(['rootTag' => 'newRootTag']);

JMS Serializer ignoring non-persisted property

I've been struggling with a property on one of my Symfony2/Doctrine objects that isn't persisted in the database. It's an array of objects that contain properties like label, key and value, but even if it is defined as a simple array of arrays, it doesn't show up.
Here is the way that the array is defined in the object that is normally persisted:
/*
* #Accessor(getter="getReceipt",setter="setReceipt")
* #Type("ArrayCollection<MyProject\ReceiptProperty>")
* #Expose
* #Groups({"details"})
*/
protected $receipt;
public function setReceipt($receipt) {
$this->receipt = $receipt;
}
public function getReceipt() {
return $this->receipt;
}
And here is how the object in the array is defined
/**
* #ExclusionPolicy("all")
*/
class ReceiptProperty extends APIObject {
/**
* #Type("string")
* #Expose
* #Groups({"basic"})
*/
public $label;
/**
* #Type("string")
* #Expose
* #Groups({"basic"})
*/
public $type;
/**
* #Type("string")
* #Expose
* #Groups({"basic"})
*/
public $key;
/**
* #Expose
* #Groups({"basic"})
*/
public $value;
public function __construct($data) {
$this->label = $data['label'];
$this->type = $data['type'];
$this->key = $data['key'];
$this->value = $data['value'];
}
}
By straight printing the objects before going into serialization with print_r, I can see that the data is there, but no matter what the configuration is, that field is never shown.
In an effort to help those that might have similar issues going forward, my problem was essentially an incorrect annotation.
In the first code block you'll notice that the annotation comment begins with /*
It turns out that JMS Serializer does not process comments that do not start with /** so effectively it was ignoring my commands. After updating the annotation comment, it worked as expected. It's always the little things...

Symfony2-Doctrine: ManyToMany relation is not saved to database

I have two PHP model classes named Category and Item. A Category may have many Items and an Item may belong to many Categories.
I have created a ManyToMany relation to both classes:
class Category
{
/**
* #ORM\ManyToMany(targetEntity="Item", mappedBy="categories", cascade={"persist"})
*/
private $items;
/**
* Add items
*
* #param Ako\StoreBundle\Entity\Item $items
*/
public function addItems(\Ako\StoreBundle\Entity\Item $items)
{
$this->items[] = $items;
}
/**
* Get items
*
* #return Doctrine\Common\Collections\Collection
*/
public function getItems()
{
return $this->items;
}
}
And:
class Item
{
/**
* #ORM\ManyToMany(targetEntity="Category", inversedBy="items", cascade={"persist"})
* #ORM\JoinTable(name="item_category",
* joinColumns={#ORM\JoinColumn(name="item_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="category_id", referencedColumnName="id")}
* )
*/
private $categories;
/**
* Add categories
*
* #param Ako\StoreBundle\Entity\Category $categories
*/
public function addCategories(\Ako\StoreBundle\Entity\Category $categories)
{
$this->categories[] = $categories;
}
/**
* Get categories
*
* #return Doctrine\Common\Collections\Collection
*/
public function getCategories()
{
return $this->categories;
}
}
Now in my controller:
$em = $this->getDoctrine()->getEntityManager();
$item = $em->getRepository('AkoStoreBundle:Item')->find($item_id);
$category = $em->getRepository('AkoStoreBundle:Category')->find($category_id);
$category->addItems($item);
$em->flush();
// Render the same page again.
In this page, I show the list of all items in a select field. The user can select one item, and add it to the category.
The list of items which belong to the category are shown below the form.
When the I submit the form, the selected item is added to the list of Category items, and is shown below, but it is not stored in the database, and if refresh the page, it disappears.
Can anyone please help me with this?
Thanks in advance.
Your Category entity is the inverse side of the relationship.
Try changing addItems to look like this:
public function addItem(\Ako\StoreBundle\Entity\Item $item)
{
$item->addCategory($this);
$this->items[] = $item;
}
Note that I changed your plural names to singular, since you're dealing with single entities, not collections.
I had the same problems...I think you forgot
$category->addItems($item);
$em->persist($category);
$em->flush();