ืžื’'ื ื˜ื• 2: ื™ื™ื‘ื•ื โ€‹โ€‹ืžื•ืฆืจื™ื ืžืžืงื•ืจื•ืช ื—ื™ืฆื•ื ื™ื™ื

Magento ื”ื•ื ืคืชืจื•ืŸ ืžืกื—ืจ ืืœืงื˜ืจื•ื ื™, ื›ืœื•ืžืจ. ืžื›ื•ื•ืŸ ื™ื•ืชืจ ืœืžื›ื™ืจืช ืžื•ืฆืจื™ื ืžืืฉืจ ืœืžื—ืกื ื™ื, ืœื•ื’ื™ืกื˜ื™ืงื” ืื• ื—ืฉื‘ื•ื ืื•ืช ืคื™ื ื ืกื™ืช ื”ื ืœื•ื•ื™ืช ืœืžื›ื™ืจื•ืช. ื™ื™ืฉื•ืžื™ื ืื—ืจื™ื (ืœืžืฉืœ, ืžืขืจื›ื•ืช ERP) ืžืชืื™ืžื•ืช ื™ื•ืชืจ ืœื™ื™ืฉื•ืžื™ื ื ืœื•ื•ื™ื. ืœื›ืŸ, ืœืขืชื™ื ืงืจื•ื‘ื•ืช ืœืžื“ื™ ื‘ืชืจื’ื•ืœ ื”ืฉื™ืžื•ืฉ ื‘ืžื’'ื ื˜ื• ืžืชืขื•ืจืจืช ื”ืžืฉื™ืžื” ืฉืœ ืฉื™ืœื•ื‘ ื—ื ื•ืช ืขื ืžืขืจื›ื•ืช ืื—ืจื•ืช ืืœื” (ืœื“ื•ื’ืžื”, 1C).

ื‘ื’ื“ื•ืœ, ื ื™ืชืŸ ืœืฆืžืฆื ืืช ื”ืื™ื ื˜ื’ืจืฆื™ื” ืœืฉื›ืคื•ืœ ื ืชื•ื ื™ื ืขืœ ื™ื“ื™:

  • ืงื˜ืœื•ื’ (ืžื•ืฆืจื™ื, ืงื˜ื’ื•ืจื™ื•ืช);
  • ื ืชื•ื ื™ ืžืœืื™ (ื™ืชืจื•ืช ืžื•ืฆืจื™ื ื‘ืžื—ืกื ื™ื ื•ืžื—ื™ืจื™ื);
  • ืœืงื•ื—ื•ืช;
  • ื”ื–ืžื ื•ืช;

ืžื’'ื ื˜ื• ืžืฆื™ืขื” ืžื—ืœืงื” ื ืคืจื“ืช ืฉืœ ืื•ื‘ื™ื™ืงื˜ื™ื ืœืžื ื™ืคื•ืœืฆื™ื” ืฉืœ ื ืชื•ื ื™ื ื‘ืžืกื“ ื”ื ืชื•ื ื™ื - ืžืื’ืจื™ื. ื‘ืฉืœ ื”ืคืจื˜ื™ื ื”ืกืคืฆื™ืคื™ื™ื ืฉืœ Magento, ื”ื•ืกืคืช ื ืชื•ื ื™ื ืœืžืกื“ ื”ื ืชื•ื ื™ื ื“ืจืš ืžืื’ืจื™ื ืงืœื” ืœืงื•ื“, ืื‘ืœ ื”ื™ื, ื ื ื™ื—, ืื™ื˜ื™ืช. ื‘ืคืจืกื•ื ื–ื”, ืื ื™ ืฉื•ืงืœ ืืช ื”ืฉืœื‘ื™ื ื”ืขื™ืงืจื™ื™ื ืฉืœ ื”ื•ืกืคืช ืžื•ืฆืจ ื‘ืื•ืคืŸ ืคืจื•ื’ืจืžื˜ื™ ืœืžื’'ื ื˜ื• 2 ื‘ืฆื•ืจื” ื”"ืงืœืืกื™ืช" - ืฉื™ืžื•ืฉ ื‘ืžื—ืœืงื•ืช ืจื™ืคื•.

ืœืงื•ื—ื•ืช ื•ื”ื–ืžื ื•ืช ืžืฉื•ื›ืคืœื•ืช ื‘ื“ืจืš ื›ืœืœ ืœื›ื™ื•ื•ืŸ ื”ืฉื ื™ - ืžืžื’'ื ื˜ื• ื•ืขื“ ืœืžืขืจื›ื•ืช ERP ื—ื™ืฆื•ื ื™ื•ืช. ืœื›ืŸ, ื–ื” ืคืฉื•ื˜ ื™ื•ืชืจ ืื™ืชื, ื‘ืฆื“ ื”ืžื’'ื ื˜ื• ืืชื” ืจืง ืฆืจื™ืš ืœื‘ื—ื•ืจ ืืช ื”ื ืชื•ื ื™ื ื”ืžืชืื™ืžื™ื, ื•ืื– "ื›ื“ื•ืจื™ื ืขืคื• ืžื”ืฆื“ ืฉืœื ื•".

ืขืงืจื•ื ื•ืช ืจื™ืฉื•ื ื ืชื•ื ื™ื ืœืžืกื“ ื ืชื•ื ื™ื

ื ื›ื•ืŸ ืœืขื›ืฉื™ื•, ื™ืฆื™ืจืช ืื•ื‘ื™ื™ืงื˜ื™ื ืฉื ืฉืžืจื• ื‘ืžืกื“ ื”ื ืชื•ื ื™ื ื‘ืื•ืคืŸ ืคืจื•ื’ืจืžื˜ื™ ื‘ืžื’'ื ื˜ื• ืžืชื‘ืฆืขืช ื‘ืืžืฆืขื•ืช ื‘ื™ืช ื—ืจื•ืฉืช:

function __construct (MagentoCmsModelBlockFactory $blockFactory) {
    $this->blockFactory = $blockFactory;
}

/** @var MagentoCmsModelBlock $block */
$block = $this->blockFactory->create();

ื•ื”ื›ืชื™ื‘ื” ืœืžืกื“ ื”ื ืชื•ื ื™ื ืžืชื‘ืฆืขืช ื‘ืืžืฆืขื•ืช Repository:

function __construct (MagentoCmsApiBlockRepositoryInterface $blockRepo) {
    $this->blockRepo = $blockRepo;
}

$this->blockRepo->save($block);

ื ื™ืชืŸ ืœื”ืฉืชืžืฉ ื‘ื’ื™ืฉืช "ืžืคืขืœ" ื•"ืžืื’ืจ" ืขื‘ื•ืจ ื›ืœ ื”ื“ื’ืžื™ื ื”ืขื™ืงืจื™ื™ื ื‘ืชื—ื•ื Magento 2.

ืžื™ื“ืข ื‘ืกื™ืกื™ ืขืœ ื”ืžื•ืฆืจ

ืื ื™ ืžืกืชื›ืœ ืขืœ ืžื‘ื ื” ื ืชื•ื ื™ื ืฉืžืชืื™ื ืœื’ืจืกืช Magento 2.3. ื”ืžื™ื“ืข ื”ื‘ืกื™ืกื™ ื‘ื™ื•ืชืจ ืขืœ ื”ืžื•ืฆืจ ื ืžืฆื ื‘ื˜ื‘ืœื” catalog_product_entity (ืจื™ืฉื•ื ืžื•ืฆืจื™ื):

entity_id
attribute_set_id
type_id
sku
has_options
required_options
created_at
updated_at

ืื ื™ ืžื•ื’ื‘ืœ ืœืกื•ื’ ืื—ื“ ืฉืœ ืžื•ืฆืจ (type_id='simple'), ืงื‘ื•ืฆื” ืฉืœ ืชื›ื•ื ื•ืช ื‘ืจื™ืจืช ืžื—ื“ืœ (attribute_set_id=4) ื•ืœื”ืชืขืœื ืžืชื›ื•ื ื•ืช has_options ะธ required_options. ืžืื– ื”ืชื›ื•ื ื•ืช entity_id, created_at ะธ updated_at ื ื•ืฆืจื™ื ื‘ืื•ืคืŸ ืื•ื˜ื•ืžื˜ื™, ื•ืื–, ืœืžืขืฉื”, ื›ื“ื™ ืœื”ื•ืกื™ืฃ ืžื•ืฆืจ ื—ื“ืฉ, ืื ื—ื ื• ืจืง ืฆืจื™ื›ื™ื ืœื”ื’ื“ื™ืจ sku. ืื ื™ ืขื•ืฉื” ืืช ื–ื”:

/** @var MagentoCatalogApiDataProductInterfaceFactory $factProd */
/** @var MagentoCatalogApiProductRepositoryInterface $repoProd */
/** @var MagentoCatalogApiDataProductInterface $prod */
$prod = $factProd->create();
$prod->setAttributeSetId(4);
$prod->setTypeId('simple');
$prod->setSku($sku);
$repoProd->save($prod);

ื•ืื ื™ ืžืงื‘ืœ ื—ืจื™ื’:

The "Product Name" attribute value is empty. Set the attribute and try again.

ืื ื™ ืžื•ืกื™ืฃ ืืช ืฉื ื”ืžื•ืฆืจ ืœื‘ืงืฉื” ื•ืžืงื‘ืœ ื”ื•ื“ืขื” ืฉื”ืชื›ื•ื ื” ื—ืกืจื” Price. ืœืื—ืจ ื”ื•ืกืคืช ื”ืžื—ื™ืจ, ื”ืžื•ืฆืจ ืžืชื•ื•ืกืฃ ืœืžืื’ืจ:

$prod = $factProd->create();
$prod->setAttributeSetId(4);
$prod->setTypeId('simple');
$prod->setSku($sku);
$prod->setName($name);
$prod->setPrice($price);
$repoProd->save($prod);

ืฉื ื”ืžื•ืฆืจ ืžืื•ื—ืกืŸ ื‘ื˜ื‘ืœืช ืชื›ื•ื ื•ืช ื”ืžื•ืฆืจ varchar (catalog_product_entity_varchar), ืžื—ื™ืจ - ื‘ื˜ื‘ืœื” catalog_product_entity_decimal. ืœืคื ื™ ื”ื•ืกืคืช ืžื•ืฆืจ, ืžื•ืžืœืฅ ืœืฆื™ื™ืŸ ื‘ืžืคื•ืจืฉ ืฉืื ื• ืžืฉืชืžืฉื™ื ื‘ื—ืœื•ืŸ ื”ืจืื•ื•ื” ื”ืื“ืžื™ื ื™ืกื˜ืจื˜ื™ื‘ื™ ืœื™ื™ื‘ื•ื โ€‹โ€‹ื ืชื•ื ื™ื:

/** @var MagentoStoreModelStoreManagerInterface $manStore */
$manStore->setCurrentStore(0);

ืชื›ื•ื ื•ืช ื ื•ืกืคื•ืช

ืขื™ื‘ื•ื“ ืชื›ื•ื ื•ืช ืžื•ืฆืจ ื ื•ืกืคื•ืช ื‘ืืžืฆืขื•ืช Magento ื”ื•ื ืชืขื ื•ื’. ืžื•ื“ืœ ื ืชื•ื ื™ื ืฉืœ EAV ืขื‘ื•ืจ ื™ืฉื•ื™ื•ืช ืขื™ืงืจื™ื•ืช (ืจืื” ื˜ื‘ืœื” eav_entity_type) ื”ื•ื ืื—ื“ ืžืžืืคื™ื™ื ื™ ื”ืžืคืชื— ืฉืœ ืคืœื˜ืคื•ืจืžื” ื–ื•. ืื ื• ืคืฉื•ื˜ ืžื•ืกื™ืคื™ื ืืช ื”ืชื›ื•ื ื•ืช ื”ืžืชืื™ืžื•ืช ืœืžื•ื“ืœ ื”ืžื•ืฆืจ:

$prodEntity->setData('description', $desc);
$prodEntity->setData('short_description', $desc_short);
// ะธะปะธ
$prodEntity->setDescription($desc);
$prodEntity->setShortDescription($desc_short);

ื•ื›ืืฉืจ ืฉื•ืžืจื™ื ืืช ื”ืžื•ื“ืœ ื“ืจืš ืื•ื‘ื™ื™ืงื˜ ื”-repo:

$repoProd->save($prod);

ืชื›ื•ื ื•ืช ื ื•ืกืคื•ืช ื™ืื•ื—ืกื ื• ื’ื ื‘ื˜ื‘ืœืื•ืช ืžืกื“ ื”ื ืชื•ื ื™ื ื”ืžืชืื™ืžื•ืช.

ื ืชื•ื ื™ ืžืœืื™

ื‘ืžื™ืœื™ื ืคืฉื•ื˜ื•ืช - ื›ืžื•ืช ื”ืžื•ืฆืจ ื‘ืžืœืื™. ื‘ืžื’'ื ื˜ื• 2.3, ืžื‘ื ื™ื ื‘ืžืกื“ ื”ื ืชื•ื ื™ื ื”ืžืชืืจื™ื ืืช ื”ืคื•ืจืžื˜ ืœืื—ืกื•ืŸ ื ืชื•ื ื™ ืžืœืื™ ื”ื ืฉื•ื ื” ื‘ืื•ืคืŸ ืžืฉืžืขื•ืชื™ ืžืžื” ืฉืงืจื” ืงื•ื“ื. ืขื ื–ืืช, ื”ื•ืกืคืช ื›ืžื•ืช ื”ืžื•ืฆืจ ื‘ืžืœืื™ ื‘ืืžืฆืขื•ืช ืžื•ื“ืœ ื”ืžื•ืฆืจ ืื™ื ื” ืงืฉื” ื‘ื”ืจื‘ื” ืžื”ื•ืกืคืช ืชื›ื•ื ื•ืช ืื—ืจื•ืช:

/** @var MagentoCatalogModelProduct $prodEntity */
/** @var MagentoCatalogApiProductRepositoryInterface $repoProd */
$inventory = [
    'is_in_stock' => true,
    'qty' => 1234
];
$prodEntity->setData('quantity_and_stock_status', $inventory);
$repoProd->save($prodEntity);

ืžื“ื™ื”

ื›ื›ืœืœ, ืชืžื™ื›ืช ืžื“ื™ื” ื‘ืžื•ืฆืจ ืœืœืงื•ื— ื‘ื—ื ื•ืช (ืžืกื—ืจ ืืœืงื˜ืจื•ื ื™) ืฉื•ื ื” ืžืชืžื™ื›ื” ื‘ืžื“ื™ื” ื‘ืื•ืชื• ืžื•ืฆืจ ืœืขื•ื‘ื“ ื‘ืžืขืจื›ืช ื”ื ื”ืœืช ื—ืฉื‘ื•ื ื•ืช ืคื ื™ืžื™ืช (ERP). ื‘ืžืงืจื” ื”ืจืืฉื•ืŸ, ืจืฆื•ื™ ืœื”ืจืื•ืช ืืช ื”ืžื•ืฆืจ ืคื ื™ื ืืœ ืคื ื™ื; ื‘ืžืงืจื” ื”ืฉื ื™, ื–ื” ืžืกืคื™ืง ื›ื“ื™ ืœืชืช ืžื•ืฉื’ ื›ืœืœื™ ืขืœ ื”ืžื•ืฆืจ. ืขื ื–ืืช, ื”ืขื‘ืจืช ืœืคื—ื•ืช ื”ืชืžื•ื ื” ื”ืจืืฉื™ืช ืฉืœ ืžื•ืฆืจ ื”ื™ื ื“ื™ ืฉื›ื™ื—ื”. case ื‘ืขืช ื™ื™ื‘ื•ื โ€‹โ€‹ื ืชื•ื ื™ื.

ื‘ืขืช ื”ื•ืกืคืช ืชืžื•ื ื” ื“ืจืš ืคืื ืœ ื”ื ื™ื”ื•ืœ, ื”ืชืžื•ื ื” ื ืฉืžืจืช ืชื—ื™ืœื” ื‘ืกืคืจื™ื™ื” ื–ืžื ื™ืช (./pub/media/tmp/catalog/product) ื•ืจืง ื‘ืขืช ืฉืžื™ืจืช ื”ืžื•ืฆืจ ืžื•ืขื‘ืจ ืœืกืคืจื™ื™ืช ื”ืžื“ื™ื” (./pub/media/catalog/product). ื›ืžื• ื›ืŸ, ื›ืืฉืจ ื”ื•ืกืคื” ื“ืจืš ืœื•ื— ื”ื ื™ื”ื•ืœ, ื”ืชืžื•ื ื” ืžืชื•ื™ื’ืช image, small_image, thumbnail, swatch_image.

/** @var MagentoCatalogApiProductRepositoryInterface $repoProd */
/** @var MagentoCatalogModelProductGalleryCreateHandler $hndlGalleryCreate */
/* $imagePath = '/path/to/file.png';  $imagePathRelative = '/f/i/file.png' */
$imagePathRelative = $this->imagePlaceToTmpMedia($imagePath);
/* reload product with gallery data */
$product = $repoProd->get($sku);
/* add image to product's gallery */
$gallery['images'][] = [
    'file' => $imagePathRelative,
    'media_type' => 'image'
    'label' => ''
];
$product->setData('media_gallery', $gallery);
/* set usage areas */
$product->setData('image', $imagePathRelative);
$product->setData('small_image', $imagePathRelative);
$product->setData('thumbnail', $imagePathRelative);
$product->setData('swatch_image', $imagePathRelative);
/* create product's gallery */
$hndlGalleryCreate->execute($product);

ืžืกื™ื‘ื” ื›ืœืฉื”ื™, ื”ืžื“ื™ื” ืžืงื•ืฉืจืช ืจืง ืœืื—ืจ ืฉืžื™ืจืช ื”ืžื•ืฆืจ ืชื—ื™ืœื” ื•ืฉืœืคืชื• ืฉื•ื‘ ืžื”ืžืื’ืจ. ื•ืืชื” ืฆืจื™ืš ืœืฆื™ื™ืŸ ืืช ื”ืชื›ื•ื ื” label ื‘ืขืช ื”ื•ืกืคืช ืขืจืš ืœื’ืœืจื™ื™ืช ื”ืžื“ื™ื” ืฉืœ ื”ืžื•ืฆืจื™ื (ืื—ืจืช ื ืงื‘ืœ ื—ืจื™ื’ื” Undefined index: label in .../module-catalog/Model/Product/Gallery/CreateHandler.php on line 516).

ืงื˜ื’ื•ืจื™ื•ืช

ืœืขืชื™ื ืงืจื•ื‘ื•ืช, ืžื‘ื ื” ื”ืงื˜ื’ื•ืจื™ื” ืฉืœ ื”ื—ื ื•ืช ื•ื™ื™ืฉื•ื ื”-backend ืื• ืžื™ืงื•ื ื”ืžื•ืฆืจื™ื ื‘ื”ื ื™ื›ื•ืœื™ื ืœื”ื™ื•ืช ืฉื•ื ื™ื ื‘ืื•ืคืŸ ืžืฉืžืขื•ืชื™. ืืกื˜ืจื˜ื’ื™ื•ืช ืœื”ืขื‘ืจืช ื ืชื•ื ื™ื ืขืœ ืงื˜ื’ื•ืจื™ื•ืช ื•ืžื•ืฆืจื™ื ื‘ืชื•ื›ื ืชืœื•ื™ื•ืช ื‘ื’ื•ืจืžื™ื ืจื‘ื™ื. ื‘ื“ื•ื’ืžื” ื–ื• ืื ื™ ื ืฆืžื“ ืœื“ื‘ืจื™ื ื”ื‘ืื™ื:

  • ืงื˜ื’ื•ืจื™ื•ืช ืงืฆื” ื•ื—ื ื•ืช ืžื•ืฉื•ื•ืช ืœืคื™ ืฉื;
  • ืื ืžื™ื•ื‘ืืช ืงื˜ื’ื•ืจื™ื” ืฉืื™ื ื” ื‘ื—ื ื•ืช, ื”ื™ื ื ื•ืฆืจืช ืชื—ืช ืงื˜ื’ื•ืจื™ื™ืช ื”ืฉื•ืจืฉ (Default Category) ื•ืžื™ืงื•ืžื• ื”ื ื•ืกืฃ ื‘ืงื˜ืœื•ื’ ื”ื—ื ื•ืช ืžื•ื ื—ื” ื‘ืื•ืคืŸ ื™ื“ื ื™;
  • ืžื•ืฆืจ ืžื•ืงืฆื” ืœืงื˜ื’ื•ืจื™ื” ืจืง โ€‹โ€‹ื›ืืฉืจ ื”ื•ื ื ื•ืฆืจ ื‘ื—ื ื•ืช (ื™ื‘ื•ื ืจืืฉื•ืŸ);

ืžื™ื“ืข ื‘ืกื™ืกื™ ืขืœ ื”ืงื˜ื’ื•ืจื™ื” ื ืžืฆื ื‘ื˜ื‘ืœื” catalog_category_entity (ืงื˜ืœื•ื’ ืงื˜ื’ื•ืจื™ื•ืช). ื™ืฆื™ืจืช ืงื˜ื’ื•ืจื™ื” ื‘ืžื’'ื ื˜ื•:

/** @var MagentoCatalogApiDataCategoryInterfaceFactory $factCat */
/** @var MagentoCatalogApiCategoryRepositoryInterface $repoCat */
$cat = $factCat->create();
$cat->setName($name);
$cat->setIsActive(true);
$repoCat->save($cat);

ืงื™ืฉื•ืจ ืžื•ืฆืจ ืœืงื˜ื’ื•ืจื™ื” ืžืชื‘ืฆืข ื‘ืืžืฆืขื•ืช ืžื–ื”ื” ื”ืงื˜ื’ื•ืจื™ื” ื•ืžืง"ื˜ ื”ืžื•ืฆืจ:

/** @var MagentoCatalogModelCategoryProductLinkFactory $factCatProdLink */
/** @var MagentoCatalogApiCategoryLinkRepositoryInterface $repoCatLink */
$link = $factCatProdLink->create();
$link->setCategoryId($catMageId);
$link->setSku($prodSku);
$repoCatLink->save($link);

ื‘ืกืš ื”ื›ืœ

ื›ืชื™ื‘ืช ืงื•ื“ ืœื”ื•ืกืคืช ืžื•ืฆืจ ื‘ืื•ืคืŸ ืคืจื•ื’ืจืžื˜ื™ ืœืžื’'ื ื˜ื• 2 ื”ื™ื ื“ื™ ืงืœื”. ืฉื™ืœื‘ืชื™ ืืช ื›ืœ ืžื” ืฉืฆื•ื™ืŸ ืœืขื™ืœ ืœืžื•ื“ื•ืœ ื”ื“ื’ืžื” "flancer32/mage2_ext_demo_import". ื™ืฉ ืจืง ืคืงื•ื“ืช ืžืกื•ืฃ ืื—ืช ื‘ืžื•ื“ื•ืœ fl32:import:prod, ื”ืžื™ื™ื‘ืืช ืืช ื”ืžื•ืฆืจื™ื ื”ืžืชื•ืืจื™ื ื‘ืงื•ื‘ืฅ JSON "./etc/data/products.json":

[
  {
    "sku": "...",
    "name": "...",
    "desc": "...",
    "desc_short": "...",
    "price": ...,
    "qty": ...,
    "categories": ["..."],
    "image_path": "..."
  }
]

ืชืžื•ื ื•ืช ืœื™ื™ื‘ื•ื โ€‹โ€‹ื ืžืฆืื•ืช ื‘ืงื˜ืœื•ื’ ./etc/data/img.

ื”ื–ืžืŸ ืœื™ื™ื‘ื 10 ืžื•ืฆืจื™ื ื‘ืฉื™ื˜ื” ื–ื• ื”ื•ื ื‘ืขืจืš 10 ืฉื ื™ื•ืช ื‘ืžื—ืฉื‘ ื”ื ื™ื™ื“ ืฉืœื™. ืื ื ืคืชื— ืืช ื”ืจืขื™ื•ืŸ ื”ื–ื”, ืงืœ ืœื”ื’ื™ืข ืœืžืกืงื ื” ืฉื ื™ืชืŸ ืœื™ื™ื‘ื ื›-3600 ืžื•ืฆืจื™ื ื‘ืฉืขื”, ื•ื™ื›ื•ืœ ืœืงื—ืช ื›-100 ืฉืขื•ืช ืœื™ื™ื‘ื 30K ืžื•ืฆืจื™ื. ื”ื—ืœืคืช ืžื—ืฉื‘ ื ื™ื™ื“ ื‘ืฉืจืช ืžืืคืฉืจืช ืœื”ื—ืœื™ืง ืžืขื˜ ืืช ื”ืžืฆื‘. ืื•ืœื™ ืืคื™ืœื• ื›ืžื” ืคืขืžื™ื. ืื‘ืœ ืœื ื‘ืกื“ืจื™ ื’ื•ื“ืœ. ืื•ืœื™ ื”ืžื”ื™ืจื•ืช ื•ื”ืื˜ื™ื•ืช ื”ื–ื• ื”ื™ื ื‘ืžื™ื“ื” ืžืกื•ื™ืžืช ืื—ืช ื”ืกื™ื‘ื•ืช ืœื”ื•ืคืขืชื• ืฉืœ ื”ืคืจื•ื™ืงื˜ ื™ื™ื‘ื•ื โ€‹โ€‹ืžื’'ื ื˜ื•/ืืกื™ื ื›ืจื•ืŸ.

ืคืชืจื•ืŸ ืงื™ืฆื•ื ื™ ืœื”ื’ื‘ืจืช ืžื”ื™ืจื•ืช ื”ื™ื™ื‘ื•ื โ€‹โ€‹ื™ื›ื•ืœ ืœื”ื™ื•ืช ื›ื ื™ืกื” ื™ืฉื™ืจื” ืœืžืกื“ ื”ื ืชื•ื ื™ื, ืื‘ืœ ื‘ืžืงืจื” ื–ื” ื›ืœ ื”"ื˜ื•ื‘ื•ืช" ืœื’ื‘ื™ ื”ื”ืจื—ื‘ื” ืฉืœ ืžื’'ื ื˜ื• ื”ื•ืœื›ื™ื ืœืื™ื‘ื•ื“ - ืชืฆื˜ืจืš ืœืขืฉื•ืช ื”ื›ืœ "ืžืชืงื“ื" ื‘ืขืฆืžืš. ืขื ื–ืืช, ื–ื” ืฉื•ื•ื” ืืช ื–ื”. ืื ื–ื” ื™ืฆืœื™ื—, ืืฉืงื•ืœ ืืช ื”ื’ื™ืฉื” ืขื ื›ืชื™ื‘ื” ื™ืฉื™ืจื” ืœืžืื’ืจ ื‘ืžืืžืจ ื”ื‘ื.

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”