meilisearch / meilisearch-php

PHP wrapper for the Meilisearch API
https://meilisearch.com
MIT License
610 stars 97 forks source link

How do you install MeiliSearch without composer #107

Closed bidoubiwa closed 3 years ago

bidoubiwa commented 4 years ago

Problem

Given this stackoverflow question where the user is is stuck because he does not use composer (still too hard for him to grasp), I would like to know if there is a way we can install MeiliSearch without composer?

I understand the problem lies with the http-client, so the guy in the stackoverflow tried to install it like this:

include './search/guzzle7/src/Client.php';
include './search/guzzle7/src/Promise.php';
include './search/meilisearchPhp/src/MeiliSearch.php';
include './search/meilisearchPhp/src/Client.php';

But it did not work.

Finding a solution

Is there a way to make it work?

Also, alternatively, stripe suggests a manual installation on their README of their PHP client. Would we be able to reproduce something like this?

Motivations

PHP is commonly used in the very beginner js-php-mysql stack and I would like for us to be usable by developers of every level.

Why Stripe allows not to use composer: https://github.com/stripe/stripe-php/issues/138

ppshobi commented 4 years ago

I think people who avoid composer should be directed to use composer. Mostly it's because they don't know what it is. the manual installation instructions tend to be error prone over time due to changes in the dependencies

bidoubiwa commented 4 years ago

I totally agree on my developer side but when you start coding you can not learn everything at once. You tend to first play around before starting to learn the important tools. I would not want a starter to abandon trying out MeiliSearch because we do not offer a simple trying experience. Composer is a hard thing to grasp at the start, it can take some time before you feel confident to dive into it.

Just out of curiosity, is this something hard to do?

ppshobi commented 4 years ago

Installing dependency manually is really hard, compared to using composer. For example, it's like avoid using cargo in rust, or downloading npm modules manually and require it without using npm.

jdreesen commented 4 years ago

You would have to write your own autoloader, I think, which would probably be way harder than understanding how to use composer. There's no way around composer when using PHP nowadays, imho.

bidoubiwa commented 4 years ago

I looked into stripe-php and they let you do that instead of composer:

require_once('/path/to/stripe-php/init.php');

which seems very simple for a user.

When you look inside the init.php file you have all the dependencies listed:


<?php

// File generated from our OpenAPI spec

// Stripe singleton
require __DIR__ . '/lib/Stripe.php';

// Utilities
require __DIR__ . '/lib/Util/CaseInsensitiveArray.php';
require __DIR__ . '/lib/Util/LoggerInterface.php';
require __DIR__ . '/lib/Util/DefaultLogger.php';
require __DIR__ . '/lib/Util/RandomGenerator.php';
require __DIR__ . '/lib/Util/RequestOptions.php';
require __DIR__ . '/lib/Util/Set.php';
....etc

I get this is not a best practice and is maybe not a production-ready code nor easy to maintain, but the objective is to not gatekeep for beginners. They will mostly not use this in production but in development.

For the npm example you made, we made no npm samples for our javascript users which work by copy pasting the following code in a html file. Which was asked by some beginners.

<!DOCTYPE html>
<html>
<body>
    Indexes:
    <div id="indexes"></div>
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/meilisearch@latest/dist/bundles/meilisearch.umd.js"></script>
<script>
  const client = new window.MeiliSearch({
    host: 'http://127.0.0.1:7700',
    apiKey: 'masterKey',
  })
  client.listIndexes().then(res => {
    res.map(index => document.querySelector('#indexes').innerHTML = `<div>${index.name}</div>`)
  })
</script>

It's about having the choice without impacting developers' experiences. I don't think having an init.php would impact a user that uses composer.

jdreesen commented 4 years ago

It's easier for stripe because they don't have any external composer dependencies.

But you currently have three php-http dependencies, which themselves have a bunch of dependencies, which have dependencies, too, ...

This is why you need an autoloader to properly load all those classes. And the users needs to somehow fetch all those dependencies manually, putting them into the correct folders, ...

All this does composer behind the scenes for you.


In the JavaScript world this is easier, because they have the concept of "bundles" which contain everything that's needed in one file and can be included from a CDN easily.

PHP doesn't really have this... except from maybe .phar files. Not sure if the maintenance overhead for creating those would be worth it.

curquiza commented 4 years ago

I understand PHP tends to be used only with Composer. But as @bidoubiwa says that's not always the case for everyone. See the link I've just added in the issue description:

Why Stripe allows not to use composer: https://github.com/stripe/stripe-php/issues/138

I don't ask this issue to be a priority, I understand a lot of users are ok with composer, but I want to clarify what we can do so that someone who would be interested in this issue could solve it 👍

I accept we implement a kind of solution/tutorial for non-composer users if:

  1. It does not impact the user-experience of composer users
  2. It does not bring any inconvenient maintenance

If a big tutorial is needed (many steps to do, or a long step with many lines) it will be done in a Wiki section and we will add the link on the README, but the big tutorial will be not present on the README, to respect the point 1.

If a file like init.php is needed, containing all the file names of our SDK, it will be a pain to maintain (and contradicts the point 2). But, a bash script could be added to the PHP to generate the file. I would add a check to the CI.

As @jdreesen said, we still have 3 php-http dependencies that make the work harder.

bidoubiwa commented 4 years ago

I didn't realize the pain it would be thanks @jdreesen.

Like @curquiza said if we can find a way to create a bash script that generates ainit.php that would be great. If that is not possible, we can make a tutorial on how to run meilisearch-php without composer, if even that is to hard to maintain, then, as the last solution would be to create a tutorial to use composer and meilisearch-php together where composer is explained as simply as possible.

shokme commented 4 years ago

To show you a little sample of the work required (still not working and vendor lock to guzzle) and I'm far from the end and I will not continue. I don't see anything on internet able to load guzzle without composer, there was a way in the past of guzzle3 but not the case today.

Don't forget the issue you have link is five year old ! this is huge in dev world.

<?php

include 'meilisearch-php/src/MeiliSearch.php';

# PSR
include 'http-message/src/MessageInterface.php';
include 'http-message/src/RequestInterface.php';
include 'http-message/src/StreamInterface.php';
include 'http-message/src/UriInterface.php';
include 'psr7/src/Utils.php';
include 'psr7/src/Stream.php';
include 'psr7/src/functions.php';
include 'psr7/src/Uri.php';
include 'psr7/src/MessageTrait.php';
include 'psr7/src/Request.php';
include 'http-factory/src/RequestFactoryInterface.php';
include 'http-factory/src/ResponseFactoryInterface.php';
include 'http-factory/src/UriFactoryInterface.php';
include 'http-factory/src/StreamFactoryInterface.php';
include 'http-client/src/ClientInterface.php';

# Discovery
include 'discovery/src/Exception.php';
include 'discovery/src/Exception/NotFoundException.php';
include 'discovery/src/Exception/DiscoveryFailedException.php';
include 'discovery/src/Exception/NoCandidateFoundException.php';
include 'discovery/src/Exception/StrategyUnavailableException.php';
include 'discovery/src/Exception/PuliUnavailableException.php';
include 'discovery/src/Strategy/DiscoveryStrategy.php';
include 'discovery/src/Strategy/PuliBetaStrategy.php';
include 'discovery/src/Strategy/CommonClassesStrategy.php';
include 'discovery/src/Strategy/CommonPsr17ClassesStrategy.php';
include 'discovery/src/ClassDiscovery.php';
include 'discovery/src/Psr18ClientDiscovery.php';
include 'discovery/src/Psr17FactoryDiscovery.php';

# Guzzle
include 'guzzle/src/Exception/GuzzleException.php';
include 'guzzle/src/Exception/TransferException.php';
include 'guzzle/src/Exception/ConnectException.php';
include 'guzzle/src/Handler/EasyHandle.php';
include 'guzzle/src/PrepareBodyMiddleware.php';
include 'promises/src/Create.php';
include 'guzzle/src/Utils.php';
include 'guzzle/src/RequestOptions.php';
include 'guzzle/src/RedirectMiddleware.php';
include 'guzzle/src/Middleware.php';
include 'guzzle/src/Handler/StreamHandler.php';
include 'guzzle/src/Handler/CurlHandler.php';
include 'guzzle/src/Handler/CurlFactoryInterface.php';
include 'guzzle/src/Handler/CurlFactory.php';
include 'guzzle/src/Handler/CurlMultiHandler.php';
include 'guzzle/src/Handler/Proxy.php';
include 'guzzle/src/HandlerStack.php';
include 'guzzle/src/ClientTrait.php';
include 'guzzle/src/ClientInterface.php';
include 'guzzle/src/Client.php';

# Factory

include 'http-factory-guzzle/src/RequestFactory.php';
include 'http-factory-guzzle/src/ResponseFactory.php';
include 'http-factory-guzzle/src/StreamFactory.php';
include 'http-factory-guzzle/src/UriFactory.php';

# Meilisearch

include 'meilisearch-php/src/Contracts/Http.php';
include 'meilisearch-php/src/Contracts/Endpoint.php';
include 'meilisearch-php/src/Delegates/HandlesIndex.php';
include 'meilisearch-php/src/Delegates/HandlesSystem.php';
include 'meilisearch-php/src/Endpoints/Delegates/HandlesDocuments.php';
include 'meilisearch-php/src/Endpoints/Delegates/HandlesSettings.php';
include 'meilisearch-php/src/Endpoints/Delegates/HandlesDumps.php';
include 'meilisearch-php/src/Endpoints/Health.php';
include 'meilisearch-php/src/Endpoints/Version.php';
include 'meilisearch-php/src/Endpoints/Stats.php';
include 'meilisearch-php/src/Endpoints/Keys.php';
include 'meilisearch-php/src/Endpoints/Dumps.php';
include 'meilisearch-php/src/Http/Client.php';
include 'meilisearch-php/src/Client.php';
include 'meilisearch-php/src/Endpoints/Indexes.php';

function run()
{
    $client = new \MeiliSearch\Client('http://localhost:7700');
    $index = $client->getOrCreateIndex('foo');

    var_dump($index);
}

run();
curquiza commented 4 years ago

Haha thanks @shokme for this piece of example 😁 The work looks indeed almost impossible...

Don't forget the issue you have link is five year old ! this is huge in dev world.

I know, just a potential help for someone who would be brave enough to try to solve this issue 😉

ppshobi commented 3 years ago

maybe we can close this?

curquiza commented 3 years ago

Let's close this then! Feel free to ask a re open if it's needed for someone.