davmixcool/php-sentiment-analyzer

PHP Sentiment Analyzer is a lexicon and rule-based sentiment analysis tool that is used to understand sentiments in a sentence using VADER (Valence Aware Dictionary and sentiment Reasoner).

Maintainers

Package info

github.com/davmixcool/php-sentiment-analyzer

pkg:composer/davmixcool/php-sentiment-analyzer

Transparency log

Fund package maintenance!

www.buymeacoffee.com/iamdavidoti

Statistics

Installs: 184 176

Dependents: 2

Suggesters: 0

Stars: 135

Open Issues: 0

2.0.0 2026-08-19 13:36 UTC

This package is auto-updated.

Last update: 2026-08-19 14:00:25 UTC


README

PHP Sentiment Analyzer is a lexicon and rule-based sentiment analysis tool that is used to understand sentiments in a sentence using VADER (Valence Aware Dictionary and sentiment Reasoner).

CI Latest Version PHP Version Total Downloads License Stars Forks

Features

  • Text
  • Emoticon
  • Emoji

Requirements

  • PHP 8.1 and above

Using PHP below 8.1? Install the 1.x line instead — it is maintained and produces the same scores: composer require davmixcool/php-sentiment-analyzer:^1.3

Contents

Documentation

Install

Composer

Run the following to include this via Composer

composer require davmixcool/php-sentiment-analyzer

Modern API

Available from 2.0. Returns an immutable result object instead of a bare array.

use Sentiment\Analyzer;

$analyzer = new Analyzer();
$result   = $analyzer->analyze('This update is really good!');

$result->compound();    // 0.5355
$result->label();       // 'positive'
$result->isPositive();  // true
$result->positive();    // 0.463
$result->toArray();     // ['positive' => 0.463, 'negative' => 0.0, 'neutral' => 0.537, 'compound' => 0.5355, 'label' => 'positive']

Labels follow the VADER convention and are exposed as constants, so you can reclassify without hardcoding: compound >= 0.05 is positive, <= -0.05 is negative, and anything between is neutral.

Batch analysis preserves your input keys, so results line up with their source rows:

$results = $analyzer->analyzeMany([
    'ticket-1' => 'This update is really good!',
    'ticket-2' => 'This product is terrible.',
    'ticket-3' => 'It works fine.',
]);

$results['ticket-2']->label();     // 'negative'
$results['ticket-2']->compound();  // -0.4767

Custom lexicons return a new analyzer — the original is untouched:

$slang = $analyzer->withLexicon([
    'slaps' => 2.2,
    'mid'   => -1.7,
]);

$slang->analyze('that beat slaps')->compound();    //  0.4939
$slang->analyze('the update is mid')->compound();  // -0.4019
$analyzer->analyze('that beat slaps')->compound(); //  0.0 — unchanged

withLexicon() rejects multi-word terms and non-numeric values rather than coercing them. The older updateLexicon() below stays lenient and unchanged.

Simple Usage

Use Sentiment\Analyzer;
$analyzer = new Analyzer(); 

$output_text = $analyzer->getSentiment("David is smart, handsome, and funny.");

$output_emoji = $analyzer->getSentiment("😁");

$output_text_with_emoji = $analyzer->getSentiment("Aproko doctor made me 🤣.");

print_r($output_text);
print_r($output_emoji);
print_r($output_text_with_emoji);

Simple Outputs

David is smart, handsome, and funny. ---------------- ['neg'=> 0.0, 'neu'=> 0.254, 'pos'=> 0.746, 'compound'=> 0.8316]

😁 ------------------- ['neg' => 0, 'neu' => 0.5, 'pos' => 0.5, 'compound' => 0.4588]

Aproko doctor made me 🤣 ------------- ['neg' => 0, 'neu' => 0.714, 'pos' =>  0.286, 'compound' => 0.4939]

Advanced Usage

You can now dynamically update the VADER (Valence) lexicon on the fly for words that are not in the dictionary. See the Example below:

Use Sentiment\Analyzer;

$sentiment = new Sentiment\Analyzer();

$strings = [
    'Weather today is rubbish',
    'This cake looks amazing',
    'His skills are mediocre',
    'He is very talented',
    'She is seemingly very agressive',
    'Marie was enthusiastic about the upcoming trip. Her brother was also passionate about her leaving - he would finally have the house for himself.',
    'To be or not to be?',
];

//new words not in the dictionary
$newWords = [
    'rubbish'=> '-1.5',
    'mediocre' => '-1.0',
    'agressive' => '-0.5'
];

//Dynamically update the dictionary with the new words
$sentiment->updateLexicon($newWords);

//Print results
foreach ($strings as $string) {
    // calculations:
    $scores = $sentiment->getSentiment($string);
    // output:
    echo "String: $string\n";
    print_r(json_encode($scores));
    echo "<br>";
}

Advanced Outputs

Weather today is rubbish  ------------- {"neg":0.455,"neu":0.545,"pos":0,"compound":-0.3612} 

This cake looks amazing  ------------- {"neg":0,"neu":0.441,"pos":0.559,"compound":0.5859}

His skills are mediocre  ------------- {"neg":0.4,"neu":0.6,"pos":0,"compound":-0.25}

He is very talented  ------------- {"neg":0,"neu":0.457,"pos":0.543,"compound":0.552}

She is seemingly very agressive  ------------- {"neg":0.338,"neu":0.662,"pos":0,"compound":-0.2598}

Marie was enthusiastic about the upcoming trip. Her brother was also passionate about her leaving - he would finally have the house for himself.  ------------- {"neg":0,"neu":0.761,"pos":0.239,"compound":0.765}

String: To be or not to be?  ------------- {"neg":0,"neu":1,"pos":0,"compound":0}

Upgrading

1.3.0 changes scores for some text. _never_check() previously zeroed the sentiment of any word within two tokens of "so" or "this", so ordinary phrasing returned neutral. That is fixed:

Input Before After
this is good 0.0000 +0.4404
this is bad 0.0000 -0.5423
so good 0.0000 +0.4877

The genuine "never" behaviour is unchanged: never so good still scores -0.2385.

If you store sentiment scores or compare them against thresholds, re-score any affected text after upgrading. Full details in the changelog.

License

The package's source code is licensed under the MIT license.

The bundled sentiment and emoji lexicons in src/Lexicons/ are third-party data, redistributed from cjhutto/vaderSentiment under its own MIT license (Copyright (c) 2016 C.J. Hutto). Full attribution and license text are in NOTICE.md.

Reference

Hutto, C.J. & Gilbert, E.E. (2014). VADER: A Parsimonious Rule-based Model for Sentiment Analysis of Social Media Text. Eighth International Conference on Weblogs and Social Media (ICWSM-14). Ann Arbor, MI, June 2014.