hipsterjazzbo / laravel-multi-tenant Goto Github PK
View Code? Open in Web Editor NEWThis package has moved to https://github.com/HipsterJazzbo/Landlord
License: MIT License
This package has moved to https://github.com/HipsterJazzbo/Landlord
License: MIT License
I want to implement this package. I followed the installation instructions but when I try to set:
TenantScope::setTenantId($tenantId)
I get the following error:
Class 'TenantScope' not found
Any idea on how to resolve this problem ?
I tried installing dev-master today with the current version of the Laravel 4.2 framework, and the artisan configuration publish throws an error.
./artisan config:publish aura-is-here/laravel-multi-tenant
PHP Fatal error: Call to undefined method AuraIsHere\LaravelMultiTenant\LaravelMultiTenantServiceProvider::mergeConfigFrom() in /code/app/vendor/aura-is-here/laravel-multi-tenant/src/AuraIsHere/LaravelMultiTenant/LaravelMultiTenantServiceProvider.php on line 37
{"error":{"type":"Symfony\\Component\\Debug\\Exception\\FatalErrorException","message":"Call to undefined method AuraIsHere\\LaravelMultiTenant\\LaravelMultiTenantServiceProvider::mergeConfigFrom()","file":"\/code\/app\/vendor\/aura-is-here\/laravel-multi-tenant\/src\/AuraIsHere\/LaravelMultiTenant\/LaravelMultiTenantServiceProvider.php","line":37}}
This is because Laravel 4.2 SupportProvider does not have the mergeConfigFrom function.
I believe this error was introduced in the PR 40.
So either this package is L5 only, or there needs to be another fix to make it L4 compatible. Either way, the documentation for this package should be updated to reflect this.
Add compatibility for Laravel 5.2
In phpunit if I seed from a method it all works fine, but if I seed from the setUp method the laravel-milti-tenant gets disabled.
I don't know what to do...
AuraIsHere\LaravelMultiTenant\TenantScope: tenant column "company_id" NOT found in tenants scope "[]"
filters.php
App::before(function($request)
{
TenantScope::addTenant('company_id', 1);
});
routes.php
var_dump(TenantScope::getTenants());
results:
array (size=1)
'company_id' => int 1
In the composer file, it's requiring Laravel 5.2 and Illuminate/Support 5.2?
Should this not be lowered to account for 4.2 support?
Currently i can't update composer which is locked to this commit
"aura-is-here/laravel-multi-tenant": "dev-master#9140a72432d1ac8d1f3d4e09d0a390a98b2bc879"
To prevent earlier compatibility issues, i had to lock it.
Can you update the composer files in this repo, to make sure it's Laravel 4.2 supported?
Hey thanks for this work and your continued effort! I couldn't find your twitter handle, so instead of emailing you, I'm hitting you up here...
I'm using repos like DbRepository.php off my models and I'm wondering how this would be used in those cases?
For example, how would one access the allTenants()
method in a repo call like $this->productRepo->getById(1);
or $this->productRepo->getAll();
?
I'd like to use this package with a new L5 project and based on quick view of the src there shouldn't be any issues , but because of the 4.2.* declarations in composer.json it cannot be installed via composer since it's being viewed as a conflict. Is there a specific reason this is set only for 4.2.x?
I've written a Laravel route filter that bases the tenancy on the sub-domain.
public function filter(Route $route, Request $request)
{
$subdomain = null;
$host = $request->getHost();
$parts = explode('.', $host);
if (count($parts) > 2) {
$subdomain = $parts[0];
// Set the tenant scope.
if ($tenant = $this->partner->findBySlug($subdomain, $host)) {
TenantScopeFacade::addTenant('partner_id', $tenant->id);
} else {
// TODO: No tenant was found, so we need to return an error.
TenantScopeFacade::addTenant('partner_id', 0);
}
}
}
The problem is that before this code can even be called on my routes, the package is telling me off:
AuraIsHere\LaravelMultiTenant\TenantScope: tenant column "partner_id" NOT found in tenants scope "[]"
Even if I modify the TenantScope.php
file to disable it immediately, I get this error.
What can I do to avoid this?
Using Laravel 5 and followed instructions as they are listed except for the config file which gave me error. No scope is being set on the queries and I can access another tenants information.
\TenantScope::addTenant('company_id', \Auth::user()->company_id);
I currently have this in the login function. Not sure if docs are up to date for L5
Hey i'm attempting to install to laravel 5 but after adding service provider and facade I get:
FatalErrorException in LaravelMultiTenantServiceProvider.php line 44:
Call to undefined method Illuminate\Config\Repository::package()
in LaravelMultiTenantServiceProvider.php line 44
at HandleExceptions->fatalExceptionFromError(array('type' => '1', 'message' => 'Call to undefined method Illuminate\Config\Repository::package()', 'file' => '/home/vagrant/lv/laravel/vendor/aura-is-here/laravel-multi-tenant/src/AuraIsHere/LaravelMultiTenant/LaravelMultiTenantServiceProvider.php', 'line' => '44')) in HandleExceptions.php line 116
at HandleExceptions->handleShutdown()
Is this me or the app?
Saw the other closed ticket... ;)
Hi, I was needed the abilities to use more than one column to define a tenant, so I developed this : https://github.com/geomagilles/laravel-multi-tenant
Following changes were made :
A good side-effect of the last point is that If the queries are supposed to be scoped by default, they will necessarily fail if no scope is provided.
Tell me if you would be interested by a pull request. Best
What is the recommended way to scope the queries when no user is authenticated? Currently it gets the tenant column from the authenticated user, but I need to be able to scope the queries for some commands that run when a user isn't logged in. Possibly in the constructor of the current class?
I was wondering how do migrations work for the tenants?
Thanks
I've worked on a solution that maybe can be integrated into your package, here is the link, hope you can help make it better. This multi-db combined with the multitenancy of this package could be a great solution!.
Hi, I'm having an odd issue with scoping queries...
My User model contains:
namespace Acme\User;
use LaravelBook\Ardent\Ardent;
use AuraIsHere\LaravelMultiTenant\Traits\TenantScopedModelTrait;
class User extends Ardent {
use TenantScopedModelTrait;
...
I have a custom 'before' filter called company
, which I use in my routes file:
Route::group(array('prefix' => 'users', 'before' => 'company'), function()
{
Route::get('/', 'UsersController@index');
Route::get('create', 'UsersController@create');
Route::post('create', 'UsersController@store');
...
});
Within the company
filter, I get the current Company ID from the session and scope with:
TenantScope::addTenant('company_id', Session::get('company_id') );
My UsersController@store
method looks like:
$user = new User();
$user->name = 'Joe';
$user->save();
...and as I would expect, creates a user called 'Joe' with the company_id
value automagically set to 1
.
However, my UsersController@index
method contains:
$users = User::all();
...and it returns every user, instead of just users with a company_id
of 1
.
Curiously, if I var_dump TenantScope::getTenants()
on that same index
method, I get:
array(1) { ["company_id"]=> string(1) "1" }
...which to me would imply that the tenant has been set correctly?
Any input would be greatly appreciated. This is an awesome package and I hope I've just overlooked something very stupid!
Using this package will give the above error
Fresh install
composer.json
{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"require": {
"laravel/framework": "4.2.*",
"aura-is-here/laravel-multi-tenant": "dev-master",
"way/generators": "2.*"
},
...
}
I have the default User model, created an empty Company one
Default UsersController and CompanyController
<?php
class UsersController extends \BaseController {
/**
* Display a listing of the resource.
* GET /users
*
* @return Response
*/
public function index()
{
Auth::loginUsingId(1);
return User::all();
}
...
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateUsersTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function(Blueprint $table)
{
$table->increments('id');
$table->string('first_name')->nullable();
$table->string('last_name')->nullable();
$table->string('title')->nullable();
$table->string('email', 120)->unique();
$table->string('phone')->nullable();
$table->string('password', 60);
$table->string('remember_token')->nullable();
$table->integer('company_id')->unsigned()->nullable()->index();
$table->string('timezone')->default('UTC');
$table->boolean('active')->default(false);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('users');
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateCompaniesTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('companies', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->text('business_info')->nullable();
$table->integer('max_users')->unsigned()->nullable();
$table->string('timezone')->default('UTC');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('companies');
}
}
Any reason to why it's behaving like this?
I've tried this with other apps and I get the same error, that's why I made a new one.
When performing a query on a model like so:
Employee::where('first_name', 'John')->orWhere('last_name', 'Doe')->get();
The first where
is scoped correctly, however the orWhere
will return any match regardless of the Employee's tenant_id.
Example: I have one employee named John for tenant 1, and I have three employees with the last name Doe for tenant 2. If I run the above query, it will return all four employees.
Not sure if this is a limitation via the orWhere
method bypassing the tenant id check or a bug or whatever. I didn't see anything about this in the discussions here so I thought I'd bring it up.
Update:
Using the Employee::where(function($query)
syntax and then putting the where
conditions inside the function work. Example:
Employee::where(function($query) {
$query->where('first_name', 'John');
$query->orWhere('last_name', 'Doe');
})->get();
The above query works as expected. Is this just how we're supposed to do orWhere
logic with these queries? Apologies if this is a stupid question/issue.
Can you bump up to L5.1?
When/where/how is the $tenants property of AuraIsHere\LaravelMultiTenantTenantScope set? When I call TenantScope::addTenant('account_id', $user->account->id); I get the error AuraIsHere\LaravelMultiTenant\TenantScope: tenant column "account_id" NOT found in tenants scope "[]" And I can see why. I don't see how the $tenants is being set.
Thanks.
Items are not scoped when using route model bindings.
In RouteServiceProvider I have this binding:
$router->model('client','App\Client');
If I access a page: /client/{client} , and the Scope is NOT applied in the global middleware stack it will show data for other tenants. All queries are scoped correctly.
this package works as well with L5 or we have to do some workaraound or plannign to create somethign for it?
In the service provider, this line is failing on Laravel 5:
// Register our config
$this->app['config']->package('aura-is-here/laravel-multi-tenant', __DIR__.'/../../config');
I think ->package()
is replaced by ->publishes()
$configPath = __DIR__.'/../../config';
$this->publishes([$configPath => config_path('config.php')]);
sorry, the issue was myself.
Can you make a separate branch for 4.2 compatibility please? This is much easier than tags, plus you can accept PR's to it for the people who are writing projects and can't update to 5.
Hey! I addes this as a post on the original issue, but didn't know if this should be opened as a separate but, so am posting this as a separate issue too - sorry for the duplicate and please remove whichever one you like.
I seem to be getting the TenantColumnUnknownException issue with db:seed :( Code as below:
In app/database/seeds/DatabaseSeeder.php:
<?php
class DatabaseSeeder extends Seeder {
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Eloquent::unguard();
TenantScope::disable();
$this->call('AccountsUsersSeeder');
}
}
In app/database/seeds/AccountsUsersSeeder.php:
<?php
class AccountsUsersSeeder extends Seeder {
public function run()
{
/**
* ACCOUNTS DATA
*/
Account::create(array(
'name' => 'XXXXXX',
'abbreviation' => 'XXXXXX',
'website' => 'XXXXXX',
'email' => 'XXXXXX',
'logo' => 'XXXXXX',
'address' => array('XXXXXX','XXXXXX','XXXXXX','XXXXXXX','XXXXXX','XXXXXX')
));
/**
* USERS DATA
*/
$account_id = DB::table('accounts')
->select('id')
->where('name', 'XXXXXX')
->first()
->id;
User::create(array(
'account_id'=> $account_id,
'password' => Hash::make('xxxxxx'),
'email' => '[email protected]',
'first_name'=> 'User',
'last_name' => 'Name'
));
}
}
Running php artisan migrate:refresh --force
runs correctly, building the correct tables, etc. Running php artisan db:seed --force
returns:
php artisan db:seed --force
[AuraIsHere\LaravelMultiTenant\Exceptions\TenantColumnUnknownException]
AuraIsHere\LaravelMultiTenant\TenantScope: tenant column "account_id" NOT f
ound in tenants scope "[]"
db:seed [--class[="..."]] [--database[="..."]] [--force]
From limited testing, the line that seems to be causing the error is in AccountsUsersSeeder:
User::create(array(
'account_id'=> $account_id,
'password' => Hash::make('xxxxxx'),
'email' => '[email protected]',
'first_name'=> 'User',
'last_name' => 'Name'
));
But TenantScope::disable()
in DatabaseSeeder.php should have disabled scoping by tenant. Could someone help?
Thanks!
Ryan
Hi,
i just had a look at a forked version https://github.com/globecode/laravel-multitenant
What i don't understand (and maybe you can explain it to me) is, why they are talking about repositories and have some implementations for repositories. Is this really necessary? I don't see any advantage what they are doing. As i see, i can use your package also in repositories, because it is always model based and models are regulary used in repository, isn't it?
Hi there,
As in the previous version, it was possible for all queries to be scoped automatically, just by implementing the trait. Now that it is necessary to set the TenantScope, I am wondering what would be the best way to keep the TenantScope persistant across the session whilst the user is logged in.
To demonstrate what I am talking about, when requesting the index of a model like so:
public function index()
{
TenantScope::setTenantId($tenant_id);
$models = Model::all();
return $models;
}
The returned query will scope to the tenant id.
However if I have my login controller
if (Auth::attempt($input)
{
$tenant_id = Auth::user()->tenant_id;
TenantScope::setTenantId($tenant_id);
return Redirect::intended('admin');
}
then call the index method on a different controller:
public function index()
{
$models = Model::all();
return $models;
}
the query will not be scoped and it will simply return every row in the table.
Is it possible/what would the best implementation be to set the tenant_id once on login and then not need to set it again?
Once again, sorry if this is a more Laravel specific question, than a package specific issue :)
Any chance that we could get some kind of versioning? I.e could the previous commit could be tagged as 1.0 for Laravel 4.2+ installs and the current dev-master to be tagged as 2.0 for Laravel 5.0+ installs?
I see this was closed before but we are getting below error on upgrade to Laravel 5.
Call to undefined method Illuminate\Config\Repository::package() in
aura-is-here/laravel-multi-tenant/src/AuraIsHere/LaravelMultiTenant/LaravelMultiTenantServiceProvider.php on line 44
Hello,
Did you just update to laravel 5?
Hi Everyone,
I'm having the following error when trying to overwrite $tenantColumns in a Model (called Project):
Project and AuraIsHere\LaravelMultiTenant\Traits\TenantScopedModelTrait define the same property ($tenantColumns) in the composition of Project. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed
Should I use the method addTenant on the constructor?
Ariel
Hi,
I'm having this error when trying to create a new model.
"Non-static method AuraIsHere\LaravelMultiTenant\TenantScope::getModelTenants() should not be called statically, assuming $this from incompatible context"
AuraIsHere/LaravelMultiTenant/TenantObserver.php:20
Kind Regards
I'm running Laravel 4.2 and can't get the package to run because the latest two commits to LaravelMultiTenantServiceProvider by @AlanRezende (9508388, c0f8c3b) break support for 4.x.
Here's the first exception I get:
Call to undefined method
AuraIsHere\LaravelMultiTenant\LaravelMultiTenantServiceProvider::mergeConfigFrom()
at line 30...
* Register the service provider.
*
* @return void
*/
public function register()
{
// Merge the package config values so they don't have to have a complete configuration
$this->mergeConfigFrom(__DIR__ . '/../../config/config.php', 'tenant');
// Register our tenant scope instance
Do you all still intend to target 4.2 per the package description going forward or is this intentional?
Hi,
I use this package with laravel 5.1 but I have one problem. I added the Default authenticate of Laravel:
public function handle($request, Closure $next)
{
if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('auth/login');
}
}
// Get logged in user company id
$company = $this->auth->user()->company_id;
// Set tenant (client_id) based contex
TenantScope::addTenant('company_id', $company);
return $next($request);
}
When I Login I get the following error:
Non-static method AuraIsHere\LaravelMultiTenant\TenantScope::addTenant() should not be called statically, assuming $this from incompatible context
Can anyone help me?
Thanks.
//UPDATE:
I created a new Middleware but I get the same error. My Middleware
<?php
namespace App\Http\Middleware;
use Closure;
use Auth;
use AuraIsHere\LaravelMultiTenant\TenantScope;
class TenantMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$company = Auth::user()->company_id;
TenantScope::addTenant('company_id', $company);
return $next($request);
}
}
I followed the instructions on issue #41, commenting out the $this->app['config']->package
part of the code and replacing it with the following:
// Register our config
//$this->app['config']->package('aura-is-here/laravel-multi-tenant', __DIR__.'/../../config');
$configPath = __DIR__.'/../../config';
$this->publishes([$configPath => config_path('config.php')]);
However, this makes Laravel throw the following error:
BadMethodCallException in ServiceProvider.php line 226:
Call to undefined method [package]
Any ideas?
I am fairly new at Laravel, so I am not sure if this is a real issue or just me not being able to use it properly, but here goes.
For it to work i have to add a call to bootTenantScopedModelTrait in my boot function in my UserModel.
This may be pretty standard, but I think it should be in the presentation
I do use Sentry which my UserModel extends. Don't know if that is causing it either.
Hope it makes sense
In laravel 5 the Serviceprovider is throwing this error
Call to undefined method Illuminate\Config\Repository::package() in
aura-is-here/laravel-multi-tenant/src/AuraIsHere/LaravelMultiTenant/LaravelMultiTenantServiceProvider.php on line 44
This is related to
https://laracasts.com/discuss/channels/general-discussion/l5-latest-commit-breaks-if-using-waygenerators-or-image-internvention?page=1
Is there a basic demo working on L5 for this?
Getting this error when trying t publish config file:
[InvalidArgumentException]
Command "config:publish" is not defined.
Did you mean one of these?
vendor:publish
config:clear
config:cache
Any workaround known?
Hi,
I add Tenant in doLogin method and after that redirect user to dashboard view.
public function doLogin()
{
// process the form
// validate the info, create rules for the inputs
$rules = array(
'email' => 'required|email', // make sure the email is an actual email
'password' => 'required|alphaNum|min:3' // password can only be alphanumeric and has to be greater than 3 characters
);
// run the validation rules on the inputs from the form
$validator = Validator::make(Input::all(), $rules);
// if the validator fails, redirect back to the form
if ($validator->fails()) {
return Redirect::to('login')
->with('message', 'The following errors occurred')
->withErrors($validator)// send back all errors to the login form
->withInput(Input::except('password')); // send back the input (not the password) so that we can repopulate the form
} else {
// create our user data for the authentication
$userdata = array(
'email' => Input::get('email'),
'password' => Input::get('password')
);
// attempt to do the login
if (Auth::attempt($userdata)) {
$tenantColumn = 'company_id';
$tenantId = '1';
TenantScope::addTenant($tenantColumn, $tenantId);
return Redirect::to('dashboard');
} else {
// validation not successful, send back to form
return Redirect::to('login')->with('message', 'Your username/password combination was incorrect')->withInput();
}
}
}
Then in dashboard I want to show all users for tenant (1). But it doesn't work (all users shows).
public function showDashboard()
{
$users = User::all();
return View::make('dashboards.index')->with('users', $users);
}
But when I add tenant in showDashboard everything works ok:
public function showDashboard()
{
$tenantColumn = 'company_id';
$tenantId = '1';
TenantScope::addTenant($tenantColumn, $tenantId);
$users = User::all();
return View::make('dashboards.index')->with('users', $users);
}
Do I need addTenant in every method?
I was wondering how do you go about associating the tenant to say a sub.domain?
Thanks!
I'm doing that one most of the time:
$this->tenantScope->addTenant(config('tenant.default_tenant_columns')[0], $this->instance_id);
Just wondered, why addTenant() needs the tenantColumn parameter again.
Thanks & Cheers
Hi,
when do you plan to merge the L5 PR? Or provide different ServiceProviders? Any news to that?
This is for the Laravel 4.2 release of this package.
In the TenantScopedModelTrait in the Boot-method, the "static::creating" can sometimes throw strange errors, about models not getting the proper Model.
Example of error;
Argument 1 passed to XX\Models\LogEntry::__invoke() must be an instance of Illuminate\Database\Eloquent\Model, XX\Models\CourseCategory given
The Models are extended correctly from the right Model in Eloquent, however this error is still thrown on random occasions when using the compiled.php version of classes in Laravel.
As a fix for this, i changed the following line:
use Illuminate\Database\Eloquent\Model;
into:
use Illuminate\Database\Eloquent\Model as BaseModelType;
And this line:
static::creating(function (Model $model) use ($tenantScope) {
into:
static::creating(function (BaseModelType $model) use ($tenantScope) {
And i haven't seen the exception since, even with the compiled classes in Laravel.
I'm not entirely sure why the issue exists, but must be something related to namespaces and them being relative to each other?
I'm developing a multi-tenant application and my design allows for multiple tenants per user.
For this I have a many-to-many relation between the users table and the sites table (sites is where the different tenants are configured).
I created a middleware to set the tenant on each request, which basically does this:
$tenantColumn = 'site_id';
$sites = Auth::user()->sites()->get();
foreach($sites as $site) {
TenantScope::addTenant($tenantColumn, $site->id);
}
I then associated 2 site IDs to the same user, but after testing, I only got the records related to the last site id associated to the user.
I later found this while digging in TenantScope.php (line 42)
$this->tenants[$tenantColumn] = $tenantId;
I didn't have to dig further, since this made clear that only one tenant scope is allowed at the same time, the tenant id value is overwritten after each addTenant call.
Are there any plans to support multiple scopes simultaneously?
Regards.
Hi i was trying to use the laravel-multi-tenant in Laravel 5 most of thing works fine, but the findOrFail in the trait that calls the parent::findOrFail does not work anymore because theres no FindOrFail in the eloquent model anymore, just in the builder. Anyone knows how can i have a workaround it?
/**
* Override the default findOrFail method so that we can rethrow a more useful exception.
* Otherwise it can be very confusing why queries don't work because of tenant scoping issues.
*
* @param $id
* @param array $columns
*
* @throws TenantModelNotFoundException
*/
public static function findOrFail($id, $columns = ['*'])
{
try {
return parent::findOrFail($id, $columns);
} catch (ModelNotFoundException $e) {
throw with(new TenantModelNotFoundException())->setModel(get_called_class());
}
}
Let's say I only use one tenant column:
tenant
But I may want to get 2 different companies at once (without getting all companies)
tenant = A OR tenant = B
It seems you can add multiple tenant fields:
TenantScope::addTenant($tenantColumn, $tenantId)
but not multiple values per one tenant field or am I wrong? If such a change should be made, maybe you can point out the place to extend your code.
Today i've updated the package with Laravel 4.2.8 and got the Exception on every route i hit:
AuraIsHere \ LaravelMultiTenant \ Exceptions \ TenantIdNotSetException
If i'm using the commit 7d9f151 it works.
Hi there, first of all, huge thanks for putting together this package!
One inconvenience is I have come across is that it breaks my seed files. (Everything else works a charm!)
In particular,when using: ModelName::create
and php artisan db:seed --class"ModelName"
I receive the error: [ErrorException] Trying to get property of non-object
Do you have any ideas on how to bypass the tenant scope whilst seeding a database?
Cheers
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.