PDA

View Full Version : سوال: مشکل در نمایش قسمتی از متن با substr



.fatemeh
پنج شنبه 10 اسفند 1391, 09:49 صبح
سلام.
برای نمایش اخبار قسمتی از متن اصلی (نزدیک به 300 کارکتر) رو با substr انتخاب می کنم.
درج خبر با استفاده از ادیتور tinymce انجام می شه.
حالا در بعضی از خبرها که انتهای div بسته نمی شه و بعد از 300 کارکتر قرار میگیره،با divهای قالب سایت
تداخل پیدا می کنن و سایت به هم ریخته می شه.
با strip_tag کدهای html رو حذف کردم ، ولی ظاهرش خراب شد(یه متن پشت سرهم بدون رنگ و لینکها)!!!
چه کارش کنم؟؟

MMSHFE
پنج شنبه 10 اسفند 1391, 10:52 صبح
دو راه دارین:
1- فعال کردن اکستنشن php_tidy و استفاده از کدی شبیه کد زیر:


<?php
$fragment = '<p>What a mighty fine <a href="blah">da';
$tidy = new tidy();
$tidy->parseString($fragment,array('show-body-only'=>true),'utf8');
$tidy->cleanRepair();
echo $tidy;
?>
منبع (http://stackoverflow.com/questions/4296671/how-to-close-open-html-tags-automatically-with-php)
2- استفاده از این تابع:


<?php
/**
* Close all open xhtml tags at the end of the string
* @param string $html The source HTML
* @return string The corrected HTML
* @author Milian <mail@mili.de>
*/
function closetags($html) {
# Put all opened tags into an array
preg_match_all('#<([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result);
$openedtags = $result[1];

# Put all closed tags into an array
preg_match_all('#</([a-z]+)>#iU', $html, $result);
$closedtags = $result[1];

$len_opened = count($openedtags);
# all tags are closed
if (count($closedtags) == $len_opened) {
return $html;
}
$openedtags = array_reverse($openedtags);
# close tags
for ($i = 0; $i < $len_opened; $i++) {
if (!in_array($openedtags[$i], $closedtags)) {
$html .= '</' . $openedtags[$i] . '>';
}
else {
unset($closedtags[array_search($openedtags[$i], $closedtags)]);
}
}
return $html;
}
?>

منبع (http://www.kirupa.com/forum/showthread.php?343478-Close-all-open-HTML-tags&p=2537201#post2537201)

.fatemeh
شنبه 31 فروردین 1392, 10:53 صبح
سلام.
بار اول از روش اول استفاده کردم و خوشبختانه جواب داد.
همین مشکل رو توی یه سایت دیگه داشتم و از کد اول استفاده کردم که تابع tidy فعال نبود
از کلاس دوم استفاده کردم .متاسفانه جواب نداد
ابنجا رو ببینید (http://mbhasia.com/page.php?p=6)

MMSHFE
شنبه 31 فروردین 1392, 11:00 صبح
میتونید با پشتیبانی تماس بگیرین و بگین براتون tidy رو فعال کنن. اگه نشد بگین و دیتای نمونه که میگیرین و با substr ناقص میشه رو هم بگذارین تا کد رو بررسی و اصلاح کنم.

.fatemeh
شنبه 31 فروردین 1392, 11:02 صبح
بله تماس گرفتم گفتن امکانش نیست.

MMSHFE
شنبه 31 فروردین 1392, 12:20 عصر
پس نمونه کدی که با substr ناقص میشه رو برام همینجا بگذارین (توی تگ HTML که درست ظاهر بشه) تا روش کار کنم.

.fatemeh
شنبه 31 فروردین 1392, 12:59 عصر
<?php $q=mysql_query("SELECT * FROM `news` WHERE `lang`='$lan'");
if(mysql_num_rows($q)==0){echo'*** موردی یافت نشد ***';}
else{
for($i=0;$i<mysql_num_rows($q);$i++){
$f=mysql_fetch_assoc($q);
$mt=$f['matn'];
$nw=(substr($mt,0,650));
include_once('pages/function.php');
$tidy=closetags($nw);
echo'<div class="title_news"><div class="title_tit">'.$f[title].'</div></div><div class="matn_news">'.$tidy.'<a href="'.$lan.'/7/'.$f[id_n].'"><div class="more"></div></a></div>';
}}?>

MMSHFE
شنبه 31 فروردین 1392, 23:59 عصر
دوست گرامی، گفتم یک نمونه متن که با substr ناقص میشه رو بگذارین. یعنی متن اصلی رو نه سورس کدتون رو. میخوام یک متن که با substr تگهای بستنش حذف میشن داشته باشم و روی همون متن کار کنم و کد رو براتون بگذارم. با تشکر

.fatemeh
یک شنبه 01 اردیبهشت 1392, 10:03 صبح
کد متن

<div class="DetNewsTopText " style="text-align: right;">
<h1 style="text-align: justify;" dir="rtl"><span style="font-size: small;"><span class="NavigationSoti">پزشکی -&nbsp;</span>غیر از ورزش و تغذیه مناسب و ترک سیگار، راه&zwnj;های جالب و موثری برای پیشگیری از حمله قلبی وجود دارد،&zwnj; راه&zwnj;هایی که شاید کمی هم عجیب باشند، مثل خوردن شکلات تلخ و به </span><span style="font-size: small;">اندازه </span><span style="font-size: small;">خوابیدن، نه زیاد و نه کم!</span></h1>
<p style="text-align: justify;"><span style="font-size: small;"><br /></span></p>
</div>
متنی که با substr انتخاب شده

<div class="DetNewsTopText " style="text-align: right;">
<h1 style="text-align: justify;" dir="rtl"><span style="font-size: small;"><span class="NavigationSoti">پزشکی -&nbsp;</span>غیر از ورزش و تغذیه مناسب و ترک سیگار، راه&zwnj;های جالب و موثری برای پیشگیری از حمله قلبی وجود دارد،&zwnj; راه&zwnj;هایی که شاید کمی هم عجیب باشند، مثل خوردن شکلات تلخ و به </span><span style="font-size: small;">اندازه </span><span style="font-size: small;">خوابیدن، نه زیاد و نه کم!</span></h1>

MMSHFE
یک شنبه 01 اردیبهشت 1392, 12:03 عصر
از این تابع SafeClip که براتون نوشتم استفاده کنید. مثالش هم همراهش گذاشتم. یعنی هر متنی میخواین کوتاهش کنید، به این تابع بدین و خروجی این تابع رو نشون بدین.


<?php

/**
* @author M-L-F
* @copyright 2013
*/

$str = <<<EOT
<div class="DetNewsTopText " style="text-align: right;">
<h1 style="text-align: justify;" dir="rtl"><span style="font-size: small;"><span class="NavigationSoti">پزشکی -&nbsp;</span>غیر از ورزش و تغذیه مناسب و ترک سیگار، راه&zwnj;های جالب و موثری برای پیشگیری از حمله قلبی وجود دارد،&zwnj; راه&zwnj;هایی که شاید کمی هم عجیب باشند، مثل خوردن شکلات تلخ و به </span><span style="font-size: small;">اندازه </span><span style="font-size: small;">خوابیدن، نه زیاد و نه کم!</span></h1>
<p style="text-align: justify;"><span style="font-size: small;"><br /></span></p>
</div>

EOT;

function SafeClip($str, $length = 500) {
$newStr = $str;
$newStr = mb_substr($newStr, 0, $length, 'utf-8');
// Remove incomplete tags from the end of the string
$newStr = preg_replace('#<[^>]*$#', '', $newStr);
if(trim(strip_tags($newStr)) != trim(strip_tags($str))) {
$newStr .= '<span style="font-size: small;">...</span>';
}
// Put all opened tags into an array
$result = array();
if(preg_match_all('#<([a-z0-9]+)[^/>]*?>#i', $newStr, $result)) {
$openedTags = $result[1];
$lenOpened = count($openedTags);
// Tag closing must be done in reverse order
$openedTags = array_reverse($openedTags);
$closedTags = array();
$result = array();
// Put all closed tags into an array
if(preg_match_all('#</([a-z0-9]+)>#i', $newStr, $result)) {
$closedTags = $result[1];
}
for($i = 0; $i < $lenOpened; $i++) {
if(!isset($closedTags[$i]) || $openedTags[$i] != $closedTags[$i]) {
$newStr .= "</{$openedTags[$i]}>";
}
}
}
return $newStr;
}

echo SafeClip($str);

?>

.fatemeh
یک شنبه 01 اردیبهشت 1392, 12:43 عصر
ممنون درست شد

masiha68
دوشنبه 20 آبان 1392, 11:02 صبح
اقای شهرکی نشد
یه سری از تگ ها بسته نمی شن و کل صفحه بهم می ریزه

masiha68
دوشنبه 20 آبان 1392, 11:04 صبح
به نظرم اگه به جای mb_substr از یه تابعی استفاده بشه که تعداد کلمه ها رو برداره دیگه همیچن مشکلی پیش نیاد ...

ابوذر محمودی
دوشنبه 20 آبان 1392, 13:51 عصر
تابع شما جناب شهرکی بعضی اوقات تگ اضافی تولید میکنه ، مثلا برای این رشته :

<div>Taking a website <b>mock-up</b> designed in <b>Photoshop</b> (PSD) and converting it into a working </div>
با فراخوانی تابع و طول 50 خروجی زیرو نشون میده


<div>Taking a website <b>mock-up</b> designed in <span style="font-size: small;">...</span></span></b></div>
قبل دایو این دو تگ رو اضافه تولید کرده :

</span></b>
تصحیحش کنید

ابوذر محمودی
دوشنبه 20 آبان 1392, 14:03 عصر
این تابع رو برای بستن تگ های html چک کنید ، من با ورودی ها مختلف بررسی کردم ، با ورودی های من جواب داد ، نمیدونم دوستمون با چه ورودی تست کردن که براشون جواب نداده.
دوستان هم بررسی کنند


function closetags ( $html )
{
#put all opened tags into an array
preg_match_all ( "#<([a-z]+)( .*)?(?!/)>#iU", $html, $result );
$openedtags = $result[1];
#put all closed tags into an array
preg_match_all ( "#</([a-z]+)>#iU", $html, $result );
$closedtags = $result[1];
$len_opened = count ( $openedtags );
# all tags are closed
if( count ( $closedtags ) == $len_opened )
{
return $html;
}
$openedtags = array_reverse ( $openedtags );
# close tags
for( $i = 0; $i < $len_opened; $i++ )
{
if ( !in_array ( $openedtags[$i], $closedtags ) )
{
$html .= "</" . $openedtags[$i] . ">";
}
else
{
unset ( $closedtags[array_search ( $openedtags[$i], $closedtags)] );
}
}
return $html;
}

ابوذر محمودی
دوشنبه 20 آبان 1392, 14:11 عصر
اینم من تست کردم ، منتهی تو بعضی موارد خروجی درست نمیده ، یعنی تعداد کاراکتر هارو کم نشون میده و ممکنه تگ هارو کامل نبنده، اگه تابع closetag رو با این تابع بکار ببریم خروجی بهتری میده .


/**
* This function extracts the non-tags string and returns a correctly formatted string
* It can handle all html entities e.g. &amp;, &quot;, etc..
*
* @param string $s
* @param integer $srt
* @param integer $len
* @param bool/integer Strict if this is defined, then the last word will be complete. If this is set to 2 then the last sentence will be completed.
* @param string A string to suffix the value, only if it has been chopped.
*/
function html_substr( $s, $srt, $len = NULL, $strict=false, $suffix = NULL )
{
if ( is_null($len) ){ $len = strlen( $s ); }

$f = 'static $strlen=0;
if ( $strlen >= ' . $len . ' ) { return "><"; }
$html_str = html_entity_decode( $a[1] );
$subsrt = max(0, ('.$srt.'-$strlen));
$sublen = ' . ( empty($strict)? '(' . $len . '-$strlen)' : 'max(@strpos( $html_str, "' . ($strict===2?'.':' ') . '", (' . $len . ' - $strlen + $subsrt - 1 )), ' . $len . ' - $strlen)' ) . ';
$new_str = substr( $html_str, $subsrt,$sublen);
$strlen += $new_str_len = strlen( $new_str );
$suffix = ' . (!empty( $suffix ) ? '($new_str_len===$sublen?"'.$suffix.'":"")' : '""' ) . ';
return ">" . htmlentities($new_str, ENT_QUOTES, "UTF-8") . "$suffix<";';

return preg_replace( array( "#<[^/][^>]+>(?R)*</[^>]+>#", "#(<(b|h)r\s?/?>){2,}$#is"), "", trim( rtrim( ltrim( preg_replace_callback( "#>([^<]+)<#", create_function(
'$a',
$f
), ">$s<" ), ">"), "<" ) ) );
}

اینطوری :

echo closetags(html_substr($s,0,300));

ابوذر محمودی
دوشنبه 20 آبان 1392, 14:59 عصر
سلام.
برای نمایش اخبار قسمتی از متن اصلی (نزدیک به 300 کارکتر) رو با substr انتخاب می کنم.
با strip_tag کدهای html رو حذف کردم ، ولی ظاهرش خراب شد(یه متن پشت سرهم بدون رنگ و لینکها)!!!

البته این مطلبی که میخوام بگم به طراحی سایت برمیگیرده و سلیقه ای هست ، اما به نظر من بهتره خلاصه مطلب رو بدون تگ نمایش بدین ، و رنگبندی و نوع فونت عنوان و متن رو با CSS انجام بدین. اینطوری صفحه یک دست و مرتب تری دارین تا اینکه هر گزیده مطلبتون یک رنگ و با یک اندازه باشه.
اگرم میخوان تو خلاصه لینک داشته باشه میتونین به تابع strip_tag بگین که تگ های a رو حذف نکنه.

masiha68
دوشنبه 20 آبان 1392, 16:02 عصر
مجبور شدم قضیه رو دور بزنم ... الان واسه سایت یه قسمت توضیحات کوتاه گذاشتم که مدیر باید دستی اونو پر کنه :)این کاری که من کردم بهتره این توابعه ... حداقل فشار روی سرور میاد پایین (خود کرده را تدبیر نیست :()