Cümle İçerisinde Arama
// filtre.json
{
"kelimeler":[
"******",
"s....",
"g....",
"a...."
]
}
Class Filtre {
public $dosya = "filtre.json";
public function Filtre($Filtre){
$File = file_get_contents($this->dosya);
$File = json_decode($File);
$File = $File->kelimeler;
$response = [];
foreach ($File as $key => $value) {
$response[] = [$value];
}
$Result = json_encode($response);
$String = strstr($Result, $Filtre);
if($String === false):
return false;
else:
return true;
endif;
}
}
arkadaşlar böyle birşey yaptım fakat istediğim gibi çalışmıyor.
cümle içerisinde
$kelime = "Uzaylı seni yakalarsam ****** içinden geçerim";
$Filtre = new Filtre();
print_r($Filtre->Filtre($kelime));
sonuç false dönüyor true dönmesi lazım fakat
$kelime = "******";
$Filtre = new Filtre();
print_r($Filtre->Filtre($kelime));
cümle içerisinde tam bir arama yapmak istiyorum yardımcı olurmusunuz bununla ilgili.
Soru hatalı mı? 👎
Eğer sorunun kurallara aykırı olduğunu düşünüyorsanız lütfen bize bildirin!
Cevaplar (18)
Üzerinde epeyi uğraştım, son hâlini alana kadar türlü revizyondan geçti. Ama yine de yüzde yüz engellemeyebilir. Aklıma geldiği kadarını eklemeye çalıştım.
class Filter
{
protected $dosya;
const STARS = '*****';
public function __construct()
{
$this->dosya = json_decode(file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'filtre.json'), true)['kelimeler'];
}
private function explode($words)
{
$list = ['.',',',':',';','!','?','=','-','_','/','\\','%','&','(',')','{','}','[',']','\'','"','*','+','^','#','$','@','₺','€'];
$words = trim(str_replace($list, ' ', $words));
preg_match_all('/(\b\S+\b)/u', $words, $matches);
$recursive = function ($arg, $k, $v) use (&$recursive) {
static $arr;
$newArr = array_chunk($arg, $k);
$newStr = mb_strtolower(implode(' ', $newArr[0]));
$arr[$newStr] = in_array($newStr, $v);
array_shift($arg);
if (count($arg) && count($arg) >= $k) {
$recursive($arg, $k, $v, $arr);
}
return $arr;
};
$results = [];
if (count($this->dosya)) {
foreach ($this->dosya as $k => $v) {
$results = $recursive($matches[0], $k, $v);
}
}
return $results;
}
/**
* @param $username
* @return void
* - Bu metod usernameFilter metodunun test hâlidir, yasaklı kelime ile eşleştiğinde echo ile yazdırabilmek için kullan, asıl çalışan metod üstteki, testten sonra bu metodu silebilirsin
*/
public function usernameFilterForTest($username)
{
$results = $this->explode($username);
if (count($results)) {
foreach ($results as $k => $v) {
if ($v) {
echo "Yasaklı kelime bulundu. Eşleşen kelime <b>$k</b><br>";
// Kullanıcı adı yasaklı kelimeler listesinde bir şekilde var
// Kullanıcı adı bir kelime veya bir kelimeden fazla ise bile eşleşme sağlanıyor. 3 kelimeli bir ad olsa ve son iki kelimesi, yasaklı kelimeler listesinin 2 kelimelik listesinde varsa bile eşleşme sağlanır
}
}
}
}
/**
* @param $comment
* @param bool $one2oneFilter - Yorum içerisinde bulunan yasaklı kelimelerin kendi harf sayılarına göre filtrelenme seçeneği. Örneğin yasaklıKelime kelimesi bulunduğunda bu değer true ise kendi harf sayısı kadar * koyulur *************; false ise alttaki STARS sabitindek, kadar yıldız koyulur
* @param bool $forceFilter - Bu da aslında sizin 'komple bir metnin içeriğinde kelime avına çıkma' isteğiniz için bir seçenek. true verilirse yasaklı bir kelime başka bir kelimenin içinde bulunsa bile filtrelenir. false ise sadece tam olarak bir kelime şeklinde yasaklı listesinde varsa filtrelenir
* @return array|string|string[]|null
*/
public function commentFilter($comment, bool $one2oneFilter = true, bool $forceFilter = false)
{
$results = $this->explode($comment);
$filter = array_filter($results, function ($item) {
return $item;
});
$h = array_map(function ($item) use ($forceFilter) {
if ($forceFilter)
return "/$item/i";
else
return "/\b$item\b/i";
}, array_keys($filter));
if ($one2oneFilter) { // Eğer * işaretlerini filtrelenen kelimenin tam harfleri ile uyumlu şekilde koymak istiyorsak
$replacemenet = [];
for ($i = 0; $i < count($h); $i++) {
$str = '';
if ($forceFilter)
$a = substr($h[$i],1, -2);
else
$a = substr($h[$i],3, -4);
$p = explode(' ', $a);
foreach ($p as $item) {
$str .= str_repeat('*', mb_strlen($item)) . ' ';
}
$replacemenet[] = $str;
}
$response = preg_replace($h, $replacemenet, $comment);
}
else
$response = preg_replace($h, self::STARS, $comment);
return $response;
}
/**
* @param $username
* @return bool
* - Kullanıcı adında yasaklı kelimeler varsa false yoksa true döndürür
*/
public function usernameFilter($username): bool
{
$username = trim($username);
preg_match_all('/\pL+/u', $username, $matches);
$results = $this->explode($matches[0]);
if (count($results)) {
foreach ($results as $v) {
if ($v)
return false;
}
}
return true;
}
}
// Bir defa oluşturduktan sonra aşağıdaki kısmı silebilirsin
###################################
// Örnek bir yasaklı kelimeler json dosyası oluşumu. Yasaklı kelimeleri içerdikleri kelime sayılarına göre gruplandırdım. Yazdığım sınıfta buna göre bütün yasaklı kelimeleri verilen yorum veya kullanıcı adındaki kelimeleri bu listede bulunan harf sayılarına göre teker teker bölüp arıyor.
$kelimeler = [
'kelimeler' => [
1 => [
'kaybol',
'yasaklıKelime',
'sarkozy',
'sak1z',
'yani',
],
2 => [
'tuvalet terliği',
'naylon poşet',
'yasaklı kelime'
],
3 => [
'yasaklı bir kelime',
'üç kelime yasaklı',
'elli birinci bölge'
],
4 => [
'zincirleme k1üfür içeren kelimeler'
]
]
];
file_put_contents('filtre.json', json_encode($kelimeler, JSON_UNESCAPED_UNICODE));
###################################
// Biraz gereksiz kod tekrarı olmuş olabilir, olabildiğince kkısa yollarla halletmeye çalıştıkça türlü sıkıntılar çıktı. Çook uzun yorumlarda belki ufak bir gecikme sorunu yaşanabilir emin değilim. Çünkü yorumu çok fazla parçaya ayırıp kontrol etmeye çalışacak. Umarım işinize yarar.
$username = 'yasaklı kelime içeren kullanıcı adı';
$filter = new Filter();
//$filter->usernameFilterForTest($username);
/******* if ($filter->usernameFilter($username)) {
// Sonuç başarılı, yasaklı kelime çıkmamış, bu kullanıcı adıyla kayıt olabilir
echo 'başarılı';
}
else {
// Sonuç başarısız, kullanıcı adının içinde bir şekilde yasaklı kleime tespit edildi, bu kullanıcı adıyla kayıt olamaz
echo 'Başarısız';
}*******/ // Orijinal kullanıcı adı kontrolü
$comment = 'Bu yorumun içerisinde yasaklı kelimeler bulunabilir. İçinde sayı olan yasaklı kelimeler de olabilir, mesela sak1z gibi. Örneğin sarkozy kelimesi yasaklı bir kelimedir ve filtrelenecektir. Aynı şekilde naylon poşet de yasaklı kelime listesinde mevcuttur.Zincirleme k1üfür içeren kelimeler de filtrelenir :) Yani kelimesi tek başına filtrelenir ama malayani veya süryanice gibi içerisinde bulunuyorsa filtrelenmeyebilir.';
$filteredeComment = $filter->commentFilter($comment);
echo "<b>Sadece tam eşleşmeler filtrelenmiş hâli</b>: $filteredeComment";
echo '<br><br>';
$filteredeComment = $filter->commentFilter($comment, forceFilter: true); // PHP 8 sözdimizi. Eğer PHP 8 değilse senin sürüm alttki yorum satırındakini kullan
//$filteredeComment = $filter->commentFilter($comment, true, true);
echo "<b>Bütün eşleşmelerin filtrelenmiş hâli</b>: $filteredeComment";
echo '<br><br>';
echo "<b>Orijinal metin</b>: $comment";
<!doctype html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<title>Document</title>
<style>
#feedBack {
display: none;
}
.success {
color: #495057;
background-color: #fff;
border-color: #198754 !important;
outline: 0;
box-shadow: 0 0 0 0.2rem rgb(74, 185, 134) !important;
}
.error {
color: #495057;
background-color: #fff;
border-color: #dc3545 !important;
outline: 0;
box-shadow: 0 0 0 0.2rem rgb(229, 88, 102) !important;
}
</style>
</head>
<body>
<div class="container">
<div class="row mt-5">
<div class="col">
<div class="input-group">
<input type="text" class="form-control" placeholder="Arama metnini giriniz" id="searchInput">
<div class="input-group-append">
<button class="btn btn-outline-primary" type="button" id="searchButton">Ara</button>
</div>
</div>
<small id="feedBack"></small>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script>
const input = $("#searchInput")
const button = $("#searchButton")
const feedBack = $("#feedBack")
const sets = {
errorMessage: 'Kayıt yok',
successMessage: 'Kayıt var',
liveSearch: true // Canlı aramayı kapatmak için false yapın, 1000 lerce kayıt içinde canlı arama yapmak performans sorunları oluşturabilir
};
(function (opt) {
const options = { // Varsayılan değerler
liveSearch: true,
errorMessage: 'Üzgünüz kaydınız bulunamadı',
successMessage: 'Kaydınız başarılı',
...opt,
clear: () => {
feedBack.hide()
input.removeClass('success error')
},
search: inp => {
$.getJSON('filtre.json').then(response => {
let values = response.map(e => e.sw)
if (inp.value.length) {
if (values.includes(inp.value)) {
feedBack.html(options.successMessage).removeClass('text-danger').addClass('text-success').show()
input.removeClass('error').addClass('success')
}
else {
feedBack.html(options.errorMessage).removeClass('text-success').addClass('text-danger').show()
input.removeClass('success').addClass('error')
}
}
else
options.clear()
})
}
}
if (options.liveSearch) {
input.on({
input: function() {
options.search(this)
},
blur: options.clear
})
}
button.on("click", () => {
options.search(input[0])
})
})(sets)
</script>
</body>
</html>
filtre.json aynı dizinde bulunsun.
Bazı geri bildirim özellikleri istenildiği gibi çalışmayabilir. Görsel açıdan
@abdullahx hocam şöyle basit bir mantık kurdum :) Biraz oldu ama görünüp kayboluyor:) Bunu sabtlemenin bir yolu var mı hocam? Hep gözüksün istiyorum...
Bir diğer sıkıntı da arada tüm liste görünüyor. Bunun engellemenin bir yolu var mı? Yalnızca ilgili arama görünse...
//--------------------------------------------------------
// Else, if they hit escape; empty the result list and hide it
//--------------------------------------------------------
} else {
resultList.html('<span style="color: red;">NOT WHITELISTED!</span>');
resultList.animate({opacity: 'show'}, {duration: 10000, queue: true});
}
@abdullahx hocam araştırırken şu scripti buldum. 9 yıl önce yayınlanmış olsa da tam isteğimi karşıladı.
https://github.com/Mr-Martin/Search-through-json-file
Bunun üzerinden gidecek olursak tek bir sıkıntım kaldı. Search bara aranan text yazıldığında gayet başarılı listeliyor. Ancak aranan bulunamadığında örneğin "Üzgünüz! Üçerik bulunamadı!" gibi bir hata mesajı yazdırabilir miyiz? Belki de çok basit bir kod ama...
İlgili kod kısmı sanırım şöyle.
(function($) {
var doc = $(document);
//--------------------------------------------------------
// Search products
//
// This function will make an AJAX request to a php file that
// search through a json files that contains a bunch of products
//--------------------------------------------------------
function ajaxSearchProducts() {
doc.on('keyup', '.search', function(e) {
var keyCode = (window.event) ? e.which : e.keyCode;
var resultList = $('.search-results');
//--------------------------------------------------------
// Check if the user press a key with number or letters or
// backspace
//--------------------------------------------------------
if(keyCode <= 90 && keyCode >= 48 || keyCode == 8) {
var value = 's=' + $(this).val();
$.ajax({
url: 'loadProducts.php',
data: value,
type: 'POST',
dataType: 'json',
success: function(data) {
var results = [];
var oddEven;
$.each(data, function(key, info) {
if(key % 2 == 0) {
oddEven = 'even';
} else {
oddEven = 'odd';
}
results.push('<li class="'+oddEven+'" data-id="'+info.produkt_id+'">'+info.produkt_namn+' <span style="color: green;">WHITELISTED</span></li>');
});
resultList.html(results);
resultList.animate({opacity: 'show'}, {duration: 200, queue: false});
}
});
//--------------------------------------------------------
// Else, if they hit escape; empty the result list and hide it
//--------------------------------------------------------
} else if(keyCode == 27) {
$(this).val('');
resultList.animate({opacity: 'hide'}, {duration: 200}).queue(function() {
$(this).html('');
$(this).dequeue();
});
}
});
}
//--------------------------------------------------------
// Run on document ready
//--------------------------------------------------------
$(function() {
ajaxSearchProducts();
});
}(jQuery));
@abdullahx hocam benzer bir soru olduğu için -konu sahibi hocamın izniyle- buradan yazsam sanırım sorun olmaz.
Benzer bir mantıkla içinde binlerce satır veri olan bir json dosyam var. Örnek veri şu şekilde:
[{"sw":"TR2C9F8B8Ac4874C17Ff7AeA511"},{"sw":"TRc81ea4341d2c1Ffede2e5Bdaa3"},{"sw":"TR1DD1B8DFc600677eeC77016a517"},{"sw":"0x19047545FfEaad110E1B9DE3AfC623B216848355"},{"sw":"TRA0520A809A50e68bB0f43aaE2"},{"sw":"TRF843D3d612EDdc100E61560e812bA"},{"sw":"TR750CDCa9F604aed573980D196C91"}]
Basit bir bootstrap arama formum var. Kullanıcı bu verilerden birini sorguladığında örneğin arama formuna TR2C9F8B8Ac4874C17Ff7AeA511 yazıp ara butonuna bastığında bu veri json dosyasında varsa "Kaydınız başarılı vs" değilse "Üzgünüz kaydınız bulunamadı" gibi bir ifade göstermek istiyorum. Hocama verdiğiniz cevaplarla biraz uğraştım ama alanım olmadığı için maalesef başarılı olamadım. Yardımcı olur musunuz?
<?php
// bir json dosyasındaki anahtarın değerine göre arama işlemi yapan sınıf
class Filter
{
// json dosyası
private $jsonFile = 'filter_arr.json';
// json dosyasındaki anahtarın değerine göre arama işlemi
public function searchAndReturnJson($search)
{
// json dosyasını oku
$json = file_get_contents($this->jsonFile);
// json dosyasını diziye çevir
$array = json_decode($json, true);
// dizi içinde arama yap
$result = $this->search($array, $search);
// sonuç varsa json olarak döndür
if ($result) {
return json_encode($result);
}
// sonuç yoksa false döndür
return false;
}
// dizi içinde arama işlemi
private function search($array, $search)
{
// dizi içinde dolaş
foreach ($array as $key => $value) {
// anahtarın değeri aranan değerse
if ($value == $search) {
// anahtarın değerini döndür
return $value;
}
// anahtarın değeri dizi ise
if (is_array($value)) {
// dizi içinde arama yap
$result = $this->search($value, $search);
// sonuç varsa
if ($result) {
// sonucu döndür
// return $result;
return true;
}
}
}
// sonuç yoksa false döndür
return false;
}
}
// kullanım örneği:
require_once 'Filter.php'; // Filter sınıfını kullanacağın sayfaya dahil et
$filter = new Filter(); // sınıfı oluştur
$response = $filter->searchAndReturnJson('******'); // arama işlemi
if ($response) { // sonuç varsa
echo $response; // sonucu ekrana yazdır
} else { // sonuç yoksa
echo 'Sonuç bulunamadı'; // mesaj yazdır
}
bembeyaz sayfa çıktı :) tertemiz
aslında yapmak istediğim su
filtre.json daki verileri ile gelen kullanıcı adlarını eşleştiricem yasaklı ile eşleşiyorsa hata verditecem
bir diğer taraftan da
yorumlar içerik girdilerinde cümle içerisinde filtre.json içeriğinde kelimeler ile eşleşiyor ise
o eşleşen keliemeleri ***** gibi yazmasını istiyorum gibi deyim umarım anlatabilmişimdir.
@abdullahx
sanırım senin yaptığında json içeriğinden bir şey var 1 dönüyor
yoksa 0 true false yani.
peki komple bir metnin içeriğinde kelime avına çıksa
ama söyle birşey var yasaklı kelime de "am" var fakat "ama" yazınca "ama'nın " etkilenmemesi de lazım :)
Class Filtre
{
public $dosya;
public function __construct()
{
$this->dosya = json_decode(file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'filtre.json'), true);
}
public function filter($sentence): bool
{
$filtreWords = explode(' ', $sentence);
$filtered = array_filter($filtreWords, function ($item) {
return in_array($item, $this->dosya['kelimeler']);
});
return (bool) count($filtered);
}
}
$kelime = "Uzaylı seni yakalarsam ****** içinden geçerim";
$Filtre = new Filtre();
print_r($Filtre->filter($kelime));
Mesela böyle basit bir şey yaptım, eğer verilen cümlede TAM EŞLEŞEN bir kelime varsa true yoksa false döndürür
Buralardayım hocam, baktım gönderinize birazcık uğraştım da ama tam olarak ne yapmak istediğinize kanaat getiremedim :) Class a verilen cümle içerisinde filter.json dosyasında belirtilen kelimelerden TAM OLARAK uyuşanı varsa true yoksa false mı döndüreecek. Ya da daha spesifik bir şekilde; verilen cümlede kaç tane olduğunun önemi olmadan *** lı kelime olsa da mı döndürecek vs biraz detaya ihtiyacım var. Biraz kıt anlıyorum ben :)