Giter VIP home page Giter VIP logo

module-eavcleaner-m2's Introduction

Magento 2 EAV Cleaner Console Command

Purpose of this project is to check for different flaws that can occur due to EAV and provide cleanup functions.

Usage

Run bin/magento in the Magento 2 root and look for the eav: commands.

Commands

  • eav:config:restore-use-default-value Check if config admin value and storeview value are the same, so "use default" doesn't work anymore. Delete the storeview values.
  • eav:attributes:restore-use-default-value Check if product attribute admin value and storeview value are the same, so "use default" doesn't work anymore. Delete the storeview values.
  • eav:attributes:remove-unused Remove attributes with no values set in products and attributes that are not present in any attribute sets.
  • eav:media:remove-unused Remove unused product images.
  • eav:clean:attributes-and-values-without-parent Remove orphaned attribute values - those which are missing a parent entry (with the corresponding backend_type) in eav_attribute.

Dry run

Use --dry-run to check result without modifying data.

Force

Use --force to skip the confirmation prompt before modifying data.

Installation

Installation with composer:

composer require magento-hackathon/module-eavcleaner-m2

Contributors

  • Nikita Zhavoronkova
  • Anastasiia Sukhorukova
  • Peter Jaap Blaakmeer

Special thanks to

  • Benno Lippert
  • Damian Luszczymak
  • Joke Puts
  • Ralf Siepker

module-eavcleaner-m2's People

Contributors

bennolippert avatar daim2k5 avatar fredden avatar jokeputs avatar perryholden avatar peterjaap avatar pixelhed avatar riconeitzel avatar seansan avatar sprankhub avatar tjitse-e avatar tmotyl avatar valguss avatar xcom-magento avatar yfleuren avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

module-eavcleaner-m2's Issues

Show all images for deletion.

Hi,
I ran it with --dry-run mode but it showed that it will delete all photos, not just those that are not in catalog_product_entity_media_gallery.

Magento 2.4.3-p1

Error in tables

When I ran: bin/magento eav:attributes:remove-unused --dry-run

I receive:

In Mysql.php line 599:

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'ee.catalog_product_entity_static' doesn't exist, query was:
SELECT COUNT(*) FROM catalog_product_entity_static WHERE attribute_id = ?

In Mysql.php line 110:

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'ee.catalog_product_entity_static' doesn't exist, query was:
SELECT COUNT(*) FROM catalog_product_entity_static WHERE attribute_id = ?

In Mysql.php line 91:

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'ee.catalog_product_entity_static' doesn't exist

`eav:attributes:remove-unused` removes attributes used by configurable products

I've run bin/magento eav:attributes:remove-unused.

It appears that it removed some attributes that were used as configurable attributes (in catalog_product_super_attribute table I believe), which then caused that product pages was displaying error as well as accessing the product from admin was impossible.

The error message then said:

Next Zend_Db_Statement_Exception: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'entity_value.value' in 'field list', query was: SELECT `entity`.`sku`, `product_entity`.`entity_id` AS `product_id`, `attribute`.`attribute_code`, `entity_value`.`value` AS `value_index`, `attribute_label`.`value` AS `super_attribute_label`, IFNULL(option_value.value, default_option_value.value) AS `option_title`, `default_option_value`.`value` AS `default_title` FROM `catalog_product_super_attribute` AS `super_attribute`
 INNER JOIN `catalog_product_entity` AS `product_entity` ON product_entity.entity_id = super_attribute.product_id
 INNER JOIN `catalog_product_super_link` AS `product_link` ON product_link.parent_id = super_attribute.product_id
 INNER JOIN `eav_attribute` AS `attribute` ON attribute.attribute_id = super_attribute.attribute_id
 INNER JOIN `catalog_product_entity` AS `entity` ON entity.entity_id = product_link.product_id
 INNER JOIN `catalog_product_entity` AS `entity_value` ON entity_value.attribute_id = super_attribute.attribute_id AND entity_value.store_id = 0 AND entity_value.entity_id = entity.entity_id
 LEFT JOIN `catalog_product_super_attribute_label` AS `attribute_label` ON super_attribute.product_super_attribute_id = attribute_label.product_super_attribute_id AND attribute_label.store_id = 0
 LEFT JOIN `eav_attribute_option` AS `attribute_option` ON attribute_option.option_id = entity_value.value
 LEFT JOIN `eav_attribute_option_value` AS `option_value` ON option_value.option_id = entity_value.value AND option_value.store_id = 1
 LEFT JOIN `eav_attribute_option_value` AS `default_option_value` ON default_option_value.option_id = entity_value.value AND default_option_value.store_id = 0 WHERE (super_attribute.product_id = 56814) AND (attribute.attribute_id = '') ORDER BY `attribute_option`.`sort_order` ASC
 in /var/www/html/vendor/magento/framework/DB/Statement/Pdo/Mysql.php:109
Stack trace:
#0 /var/www/html/vendor/magento/framework/DB/Statement/Pdo/Mysql.php(91): Magento\Framework\DB\Statement\Pdo\Mysql->tryExecute(Object(Closure))
#1 /var/www/html/vendor/magento/zendframework1/library/Zend/Db/Statement.php(313): Magento\Framework\DB\Statement\Pdo\Mysql->_execute(Array)
#2 /var/www/html/vendor/magento/zendframework1/library/Zend/Db/Adapter/Abstract.php(480): Zend_Db_Statement->execute(Array)
#3 /var/www/html/vendor/magento/zendframework1/library/Zend/Db/Adapter/Pdo/Abstract.php(238): Zend_Db_Adapter_Abstract->query('SELECT `entity`...', Array)
#4 /var/www/html/vendor/magento/framework/DB/Adapter/Pdo/Mysql.php(564): Zend_Db_Adapter_Pdo_Abstract->query('SELECT `entity`...', Array)
#5 /var/www/html/vendor/magento/framework/DB/Adapter/Pdo/Mysql.php(634): Magento\Framework\DB\Adapter\Pdo\Mysql->_query('SELECT `entity`...', Array)
#6 /var/www/html/generated/code/Magento/Framework/DB/Adapter/Pdo/Mysql/Interceptor.php(95): Magento\Framework\DB\Adapter\Pdo\Mysql->query(Object(Magento\Framework\DB\Select), Array)
#7 /var/www/html/vendor/magento/zendframework1/library/Zend/Db/Adapter/Abstract.php(737): Magento\Framework\DB\Adapter\Pdo\Mysql\Interceptor->query(Object(Magento\Framework\DB\Select), Array)
#8 /var/www/html/generated/code/Magento/Framework/DB/Adapter/Pdo/Mysql/Interceptor.php(1085): Zend_Db_Adapter_Abstract->fetchAll(Object(Magento\Framework\DB\Select), Array, 2)
#9 /var/www/html/vendor/magento/module-configurable-product/Model/AttributeOptionProvider.php(57): Magento\Framework\DB\Adapter\Pdo\Mysql\Interceptor->fetchAll(Object(Magento\Framework\DB\Select))
#10 /var/www/html/generated/code/Magento/ConfigurableProduct/Model/AttributeOptionProvider/Proxy.php(95): Magento\ConfigurableProduct\Model\AttributeOptionProvider->getAttributeOptions(Object(Magento\Catalog\Model\ResourceModel\Eav\Attribute\Interceptor), '56814')
#11 /var/www/html/vendor/magento/module-configurable-product/Model/ResourceModel/Product/Type/Configurable.php(239): Magento\ConfigurableProduct\Model\AttributeOptionProvider\Proxy->getAttributeOptions(Object(Magento\Catalog\Model\ResourceModel\Eav\Attribute\Interceptor), '56814')
#12 /var/www/html/vendor/magento/module-configurable-product/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php(324): Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable->getAttributeOptions(Object(Magento\Catalog\Model\ResourceModel\Eav\Attribute\Interceptor), '56814')
#13 /var/www/html/vendor/magento/module-configurable-product/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection.php(205): Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection->loadOptions()
#14 /var/www/html/vendor/magento/framework/Data/Collection/AbstractDb.php(594): Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection->_afterLoad()
#15 /var/www/html/generated/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection/Interceptor.php(338): Magento\Framework\Data\Collection\AbstractDb->loadWithFilter(false, false)
#16 /var/www/html/vendor/magento/framework/Data/Collection/AbstractDb.php(565): Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection\Interceptor->loadWithFilter(false, false)
#17 /var/www/html/generated/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection/Interceptor.php(329): Magento\Framework\Data\Collection\AbstractDb->load(false, false)
#18 /var/www/html/vendor/magento/framework/Data/Collection.php(840): Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection\Interceptor->load()
#19 /var/www/html/generated/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute/Collection/Interceptor.php(671): Magento\Framework\Data\Collection->getIterator()
#20 /var/www/html/vendor/magento/module-configurable-product/Helper/Product/Options/Loader.php(54): Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection\Interceptor->getIterator()
#21 /var/www/html/vendor/magento/module-configurable-product/Model/Product/ReadHandler.php(48): Magento\ConfigurableProduct\Helper\Product\Options\Loader->load(Object(Magento\Catalog\Model\Product\Interceptor))
#22 /var/www/html/vendor/magento/framework/EntityManager/Operation/Read/ReadExtensions.php(48): Magento\ConfigurableProduct\Model\Product\ReadHandler->execute(Object(Magento\Catalog\Model\Product\Interceptor), Array)
#23 /var/www/html/vendor/magento/framework/EntityManager/Operation/Read.php(112): Magento\Framework\EntityManager\Operation\Read\ReadExtensions->execute(Object(Magento\Catalog\Model\Product\Interceptor), Array)
#24 /var/www/html/vendor/magento/framework/EntityManager/EntityManager.php(80): Magento\Framework\EntityManager\Operation\Read->execute(Object(Magento\Catalog\Model\Product\Interceptor), '56814', Array)
#25 /var/www/html/vendor/magento/module-catalog/Model/ResourceModel/Product.php(735): Magento\Framework\EntityManager\EntityManager->load(Object(Magento\Catalog\Model\Product\Interceptor), '56814')
#26 /var/www/html/generated/code/Magento/Catalog/Model/ResourceModel/Product/Interceptor.php(185): Magento\Catalog\Model\ResourceModel\Product->load(Object(Magento\Catalog\Model\Product\Interceptor), '56814', NULL)
#27 /var/www/html/vendor/magento/framework/Model/AbstractModel.php(543): Magento\Catalog\Model\ResourceModel\Product\Interceptor->load(Object(Magento\Catalog\Model\Product\Interceptor), '56814', NULL)
#28 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(58): Magento\Framework\Model\AbstractModel->load('56814')
#29 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Catalog\Model\Product\Interceptor->___callParent('load', Array)
#30 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(153): Magento\Catalog\Model\Product\Interceptor->Magento\Framework\Interception\{closure}('56814')
#31 /var/www/html/generated/code/Magento/Catalog/Model/Product/Interceptor.php(1661): Magento\Catalog\Model\Product\Interceptor->___callPlugins('load', Array, Array)
#32 /var/www/html/vendor/mailchimp/mc-magento2/Ui/Component/Listing/Column/Products.php(70): Magento\Catalog\Model\Product\Interceptor->load('56814')
#33 /var/www/html/vendor/magento/framework/View/Element/UiComponent/Context.php(396): Ebizmarts\MailChimp\Ui\Component\Listing\Column\Products->prepareDataSource(Array)
#34 /var/www/html/vendor/magento/framework/View/Element/UiComponent/Context.php(393): Magento\Framework\View\Element\UiComponent\Context->prepareDataSource(Array, Object(Ebizmarts\MailChimp\Ui\Component\Listing\Column\Products))
#35 /var/www/html/vendor/magento/framework/View/Element/UiComponent/Context.php(393): Magento\Framework\View\Element\UiComponent\Context->prepareDataSource(Array, Object(Amasty\Pgrid\Ui\Component\Listing\Columns))
#36 /var/www/html/vendor/magento/framework/View/Element/UiComponent/Context.php(251): Magento\Framework\View\Element\UiComponent\Context->prepareDataSource(Array, Object(Magento\Ui\Component\Listing))
#37 /var/www/html/vendor/magento/framework/View/Element/UiComponent/ContentType/Json.php(69): Magento\Framework\View\Element\UiComponent\Context->getDataSourceData(Object(Magento\Ui\Component\Listing))
#38 /var/www/html/vendor/magento/module-ui/Component/AbstractComponent.php(158): Magento\Framework\View\Element\UiComponent\ContentType\Json->render(Object(Magento\Ui\Component\Listing), 'templates/listi...')
#39 /var/www/html/vendor/magento/module-ui/Controller/Adminhtml/Index/Render.php(91): Magento\Ui\Component\AbstractComponent->render()
#40 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(58): Magento\Ui\Controller\Adminhtml\Index\Render->execute()
#41 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Ui\Controller\Adminhtml\Index\Render\Interceptor->___callParent('execute', Array)
#42 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(153): Magento\Ui\Controller\Adminhtml\Index\Render\Interceptor->Magento\Framework\Interception\{closure}()
#43 /var/www/html/generated/code/Magento/Ui/Controller/Adminhtml/Index/Render/Interceptor.php(23): Magento\Ui\Controller\Adminhtml\Index\Render\Interceptor->___callPlugins('execute', Array, Array)
#44 /var/www/html/vendor/magento/framework/App/Action/Action.php(111): Magento\Ui\Controller\Adminhtml\Index\Render\Interceptor->execute()
#45 /var/www/html/vendor/magento/module-backend/App/AbstractAction.php(151): Magento\Framework\App\Action\Action->dispatch(Object(Magento\Framework\App\Request\Http))
#46 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(58): Magento\Backend\App\AbstractAction->dispatch(Object(Magento\Framework\App\Request\Http))
#47 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Ui\Controller\Adminhtml\Index\Render\Interceptor->___callParent('dispatch', Array)
#48 /var/www/html/vendor/magento/module-backend/App/Action/Plugin/Authentication.php(145): Magento\Ui\Controller\Adminhtml\Index\Render\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http))
#49 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(135): Magento\Backend\App\Action\Plugin\Authentication->aroundDispatch(Object(Magento\Ui\Controller\Adminhtml\Index\Render\Interceptor), Object(Closure), Object(Magento\Framework\App\Request\Http))
#50 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(153): Magento\Ui\Controller\Adminhtml\Index\Render\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http))
#51 /var/www/html/generated/code/Magento/Ui/Controller/Adminhtml/Index/Render/Interceptor.php(41): Magento\Ui\Controller\Adminhtml\Index\Render\Interceptor->___callPlugins('dispatch', Array, Array)
#52 /var/www/html/vendor/magento/framework/App/FrontController.php(245): Magento\Ui\Controller\Adminhtml\Index\Render\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http))
#53 /var/www/html/vendor/magento/framework/App/FrontController.php(212): Magento\Framework\App\FrontController->getActionResponse(Object(Magento\Ui\Controller\Adminhtml\Index\Render\Interceptor), Object(Magento\Framework\App\Request\Http))
#54 /var/www/html/vendor/magento/framework/App/FrontController.php(147): Magento\Framework\App\FrontController->processRequest(Object(Magento\Framework\App\Request\Http), Object(Magento\Ui\Controller\Adminhtml\Index\Render\Interceptor))
#55 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(58): Magento\Framework\App\FrontController->dispatch(Object(Magento\Framework\App\Request\Http))
#56 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Framework\App\FrontController\Interceptor->___callParent('dispatch', Array)
#57 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(153): Magento\Framework\App\FrontController\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http))
#58 /var/www/html/generated/code/Magento/Framework/App/FrontController/Interceptor.php(23): Magento\Framework\App\FrontController\Interceptor->___callPlugins('dispatch', Array, Array)
#59 /var/www/html/vendor/magento/framework/App/Http.php(116): Magento\Framework\App\FrontController\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http))
#60 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(58): Magento\Framework\App\Http->launch()
#61 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Framework\App\Http\Interceptor->___callParent('launch', Array)
#62 /var/www/html/vendor/justbetter/magento2-sentry/Plugin/GlobalExceptionCatcher.php(57): Magento\Framework\App\Http\Interceptor->Magento\Framework\Interception\{closure}()
#63 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(135): JustBetter\Sentry\Plugin\GlobalExceptionCatcher->aroundLaunch(Object(Magento\Framework\App\Http\Interceptor), Object(Closure))
#64 /var/www/html/vendor/magento/framework/Interception/Interceptor.php(153): Magento\Framework\App\Http\Interceptor->Magento\Framework\Interception\{closure}()
#65 /var/www/html/generated/code/Magento/Framework/App/Http/Interceptor.php(23): Magento\Framework\App\Http\Interceptor->___callPlugins('launch', Array, NULL)
#66 /var/www/html/vendor/magento/framework/App/Bootstrap.php(264): Magento\Framework\App\Http\Interceptor->launch()
#67 /var/www/html/pub/index.php(30): Magento\Framework\App\Bootstrap->run(Object(Magento\Framework\App\Http\Interceptor))
#68 {main} [] []

The fix was to restore removed data from following tables:

  • eav_attribute
  • catalog_eav_attribute
  • eav_attribute_option
  • eav_attribute_option_value

eav: commands not available after installing the module

I have just installed the module using composer, but when I run bin/magento there are no eav: commands available. I am on Magento version 2.4.5-p1

I have cleared the cache after the installation by bin/magento cache:clean

Is there something additional needed to be done so these commands are registered?

Skip placeholder files

When running bin/magento eav:media:remove-unused --dry-run, I see that the tool wants to remove placeholder images:

## WOULD REMOVE: /placeholder/default/photo-coming-soon3.jpg ##
## WOULD REMOVE: /placeholder/default/photo-coming-soon3_1.jpg ##
## WOULD REMOVE: /placeholder/default/photo-coming-soon3_2.jpg ##
## WOULD REMOVE: /placeholder/default/photo-coming-soon3_3.jpg ##

I would think we'd want to skip these, correct? Since they are referenced in core_config_data? If you agree, we can modify the console command class to skip /placeholder like you do /cache, as seen in \Hackathon\EAVCleaner\Console\Command\RemoveUnusedMediaCommand::execute:

    private function isInCachePath(?string $file): bool
    {
        return strpos($file, '/cache') !== false;
    }

If this makes sense to you, I can submit a PR, if needed.

Remove orphaned tables

Maybe we should add a command that can identify which tables can be deleted from a Magento 2 install? I'm thinking it should do something like this;

  • Whitelist all core Magento tables
  • Run through the db_schema files and InstallSchema scripts of all extensions to identify table names
  • Compare that list versus the tables actually in the database
  • Interactively ask to drop that table (or generate queries to do it)

Feature Request: Add --force command to eav:media:remove-unused

I added eav:media:remove-unused command to a cron due to how my Magento site adds products, it syncs up images nightly and wipes all product images with new ones. Magento leaves the old images on the hard disk so I want it to be cleaned up daily.

I added eav:media:remove-unused to a cron but because of the prompt I don't think it runs - I amended the vendor file to do this which works for me but am scared of it being overwritten in the future - hence the feature request! Otherwise I'll make a plugin to properly extend it.

protected function configure()
    {
        $this
            ->setName('eav:media:remove-unused')
            ->setDescription('Remove unused product images')
            ->addOption('dry-run')
			->addOption('force');
    }

  public function execute(InputInterface $input, OutputInterface $output): void
   {
       $fileSize   = 0;
       $countFiles = 0;
       $isDryRun   = $input->getOption('dry-run');
       $isForce   = $input->getOption('force');

       if (!$isDryRun && $input->isInteractive() && !$isForce) {

Adding a --force command would be useful for those who want this in a cron.

Remove Unused media

Hello :)

when using eav:media:remove-unused we get an error

image

We are using s3 as remote storage

Remove orphaned attributes

  • Create a list of all product attributes from the database
  • Search through the codebase to see whether they are mentioned in InstallData/UpdateData scripts - those are fine
  • Search through phtml files to see whether they are used (also make sure to look for getAttributeName / setAttributeName instead of just attribute_name) - those are fine
  • We should whitelist all core attributes since those have names that occur a lot ('name' / 'sku')
  • The remaining product attributes might be removeable

This probably can't be done automatically since it'll most likely show too many false positives.

Unused images are not deleted, because deleted products are still contained in catalog_product_entity_media_gallery

The command "eav:attributes:remove-unused" does not show any images to be deleted. This is because Magento does not delete the deleted products from the catalog_product_entity_media_gallery table. The table now has more than 20000 entries, even though our store only has just under 4000 products.
I found a similar error description here: https://magento.stackexchange.com/questions/238244/magento2-manage-and-understand-images-of-deleted-products-behavior

I am using Magento 2.3.7p3.

Does anyone have an idea what this is due to?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.