PHP How to get value using the Class - php

I have made a form with a description and inside that description there's a list called "services-list" and I need to get the value with the class "services-list"
here is the code on how I get the whole description section
<p class="card"><?php echo substr(strip_tags($row->description), 0, 200); ?>...</p>
description came from a form for="description", and saved to the database.
in that code there is a section which has class "services-list" and listed all the services, how can I call that specific section to print?
I am referring to code something like this
<?php echo substr(strip_tags($row->description .'.services-list'), 0, 200); ?>
but not sure with this code.

Assuming you have a $row->description object contains this text :
$row = (object) [ 'description' => '
<div>
<li class="other-class">Service A</li>
<li class="services-list">Service B</li>
<li class="services-list">Service C</li>
<li class="services-list">Service D</li>
</div>
'];
You could use DOMDocument to get all of the services-list class element by :
$doc = new DOMDocument();
$doc->loadHTML($row->description);
$xpath = new DomXPath($doc);
$nodeList = $xpath->query("//li[#class='services-list']");
$node = $nodeList->item(1);
$service_list = [];
foreach ($nodeList as $i => $val){
if (!empty($val->nodeValue)) {
array_push($service_list, $val->nodeValue);
}
}
$service_list = implode($service_list, ', '); // separate each item by comma
// To check the result:
echo "<p>" . $service_list . "</p>";
The output will be :
<p>Service B, Service C, Service D</p>

Related

PHP string search and replace - possible use of DOM Needed

I cant seem to figure out how to achieve my goal.
I want to find and replace a specific class link based off of a generated RSS feed (need the option to replace later no matter what link is there)
Example HTML:
<a class="epclean1" href="#">
WHAT IT SHOULD LOOK LIKE:
<a class="epclean1" href="google.com">
May need to incorporate get element using DOM as the Full php has a created document. If that is the case I would need to know how to find by class and add the href url that way.
FULL PHP:
<?php
$rss = new DOMDocument();
$feed = array();
$urlArray = array(array('url' => 'https://feeds.megaphone.fm')
);
foreach ($urlArray as $url) {
$rss->load($url['url']);
foreach ($rss->getElementsByTagName('item') as $node) {
$item = array (
'title' => $node->getElementsByTagName('title')->item(0)->nodeValue
);
array_push($feed, $item);
}
}
usort( $feed, function ( $a, $b ) {
return strcmp($a['title'], $b['title']);
});
$limit = sizeof($feed);
$previous = null;
$count_firstletters = 0;
for ($x = 0; $x < $limit; $x++) {
$firstLetter = substr($feed[$x]['title'], 0, 1); // Getting the first letter from the Title you're going to print
if($previous !== $firstLetter) { // If the first letter is different from the previous one then output the letter and start the UL
if($count_firstletters != 0) {
echo '</ul>'; // Closing the previously open UL only if it's not the first time
echo '</div>';
}
echo '<button class="glanvillecleancollapsible">'.$firstLetter.'</button>';
echo '<div class="glanvillecleancontent">';
echo '<ul style="list-style-type: none">';
$previous = $firstLetter;
$count_firstletters ++;
}
$title = str_replace(' & ', ' & ', $feed[$x]['title']);
echo '<li>';
echo '<a class="epclean'.$i++.'" href="#" target="_blank">'.$title.'</a>';
echo '</li>';
}
echo '</ul>'; // Close the last UL
echo '</div>';
?>
</div>
</div>
The above fullphp shows on site like so (this is shortened as there is 200+):
<div class="modal-glanvillecleancontent">
<span class="glanvillecleanclose">×</span>
<p id="glanvillecleaninstruct">Select the first letter of the episode that you wish to get clean version for:</p>
<br>
<button class="glanvillecleancollapsible">8</button>
<div class="glanvillecleancontent">
<ul style="list-style-type: none">
<li><a class="epclean1" href="#" target="_blank">80's Video Vixen Tawny Kitaen 044</a></li>
</ul>
</div>
<button class="glanvillecleancollapsible">A</button>
<div class="glanvillecleancontent">
<ul style="list-style-type: none">
<li><a class="epclean2" href="#" target="_blank">Abby Stern</a></li>
<li><a class="epclean3" href="#" target="_blank">Actor Nick Hounslow 104</a></li>
<li><a class="epclean4" href="#" target="_blank">Adam Carolla</a></li>
<li><a class="epclean5" href="#" target="_blank">Adrienne Janic</a></li>
</ul>
</div>
You're not very clear about how your question relates to the code shown, but I don't see any attempt to replace the attribute within the DOM code. You'd want to look at XPath to find the desired elements:
function change_clean($content) {
$dom = new DomDocument;
$dom->loadXML($content);
$xpath = new DomXpath($dom);
$nodes = $xpath->query("//a[#class='epclean1']");
foreach ($nodes as $node) {
if ($node->getAttribute("href") === "#") {
$node->setAttribute("href", "https://google.com/");
}
}
return $dom->saveXML();
}
$xml = '<?xml version="1.0"?><foo><bar><a class="epclean1" href="#">test1</a></bar><bar><a class="epclean1" href="https://example.com">test2</a></bar></foo>';
echo change_clean($xml);
Output:
<foo><bar><a class="epclean1" href="https://google.com/">test1</a></bar><bar><a class="epclean1" href="https://example.com">test2</a></bar></foo>
Hmm. I think your pattern and replacement might be your problem.
What you have
$pattern = 'class="epclean1 href="(.*?)"';
$replacement = 'class="epclean1 href="google.com"';
Fix
$pattern = '/class="epclean1" href=".*"/';
$replacement = 'class="epclean1" href="google.com"';

DOMDocument: problems with replaceChild()

I'm attempting to find the first <p> in a <div>:
<div class="embed-left">
<h4>Bookmarks</h4>
<p>Something goes here.</p>
<p>Read more...</p>
</div>
Which I've done.
Now, however, I need to replace the found text with a link, as assigned to the <span> before then being used in the $url createElement() method:
$results_links = $this->data_migration->process_embed_find_links();
$dom = new DOMDocument();
foreach ($results_links as $notes):
$dom->loadHTML($notes['note']);
$x = $dom->getElementsByTagName('div')->length;
// Loop through the <div> elements found in the HTML...
for ($i = 0; $i < $x; $i++):
$parentNode = $dom->getElementsByTagName('div')->item($i);
// Here's a <h4> element.
$childNodeHeading = $dom->getElementsByTagName('div')->item($i)->childNodes->item(1);
// If the <h4> element is "Bookmarks"...
if ( $childNodeHeading->nodeValue == "Bookmarks" ):
// ... then grab the first <p> element.
$childNodeTitle = $dom->getElementsByTagName('div')->item($i)->childNodes->item(3);
// Create the appropriate <p> element.
$title = $dom->createElement('p', $childNodeTitle->nodeValue);
echo "<p>" . $title->nodeValue . "</p>";
// Find the `notes_links.from-asset` rows.
$results_bookmarks_links = $this->data_migration->process_embed_find_links_bookmarks_links(array(
'note_id' => $notes['note_id'],
// Send the first <p> tag in the <div> element.
'title' => htmlentities($childNodeTitle->nodeValue)
));
// Loop through the data (one row returned, but it's more neat to run it through a foreach() function)...
foreach ($results_bookmarks_links as $index => $link):
// Assuming there are values (which there has to be, by virtue of the fact that we found the <div> elements in the first place...
if ( isset($results_bookmarks_links) && ( count($results_bookmarks_links) > 0 ) ):
// Create the <span> element for the link item, according to Sina's design.
$span = '<span>[#' . $notes['note_id'] . ']</span>';
**$url = $dom->createElement('span', $span);**
**$parentNode->replaceChild(
$url,
$title
);**
endif;
endforeach;
endif;
endfor;
endforeach;
Which I've had no success with.
I'm unable to figure out either the parent element, or the proper parameters to use in the replaceChild() method.
I've emboldened the main bits that I'm having trouble with, if that helps.
The important thing is to replace the existing p with a newly-created p that contains the child nodes.
Here's an example, using XPath to select the nodes to be replaced:
<?php
$html = <<<END
<div class="embed-left">
<h4>Bookmarks</h4>
<p>Something goes here.</p>
<p>Read more...</p>
</div>
END;
$doc = new DOMDocument;
$doc->loadHTML($html, LIBXML_HTML_NOIMPLIED);
$xpath = new DOMXPath($doc);
$nodes = $xpath->query('//div[h4[text()="Bookmarks"]]/p[1]');
foreach ($nodes as $oldnode) {
$note = 'TODO'; // build `$note` somewhere
$link = $doc->createElement('a');
$link->setAttribute('href', '#');
$link->textContent = sprintf('[#%s]', $note);
$span = $doc->createElement('span');
$span->appendChild($link);
$newnode = $doc->createElement('p');
$newnode->appendChild($span);
$oldnode->parentNode->replaceChild($newnode, $oldnode);
}
print $doc->saveHTML($doc->documentElement);

How get list subItens nodes separateds using PHP DOM

I was seeing this tip
PHP DOM get items from first ul element
But in this case:
<li>First item
<ul>
<li>
First SubItem
</li>
<li>
Second SubItem
</li>
</ul>
</li>
PHP Code:
$DOM = new DOMDocument;
libxml_use_internal_errors(true);
$DOM->loadHTML( $output);
$items = $DOM->getElementsByTagName('ul');
echo '<ul>';
foreach ($items->item(3)->getElementsByTagName('li') as $li) {
var_dump($li);die();
echo '<li>'.$li->nodeValue;
$ul = $li->getElementsByTagName('ul');
echo '<ul>';
echo '--->'.$ul->length.'<br>';
for($u=0;$u<$ul->length;$u++){
foreach ($ul->item($u)->getElementsByTagName('li') as $lii) {
echo '<li>'.$lii->nodeValue.'</li>';
}
}
echo '</ul>';
echo '</li>';
}
echo '</ul>';
The Problem is:
Im getting in //$li->nodeValue;// "First itemFirst SubItemSecond SubItem" as the Fist node;
I need get this items separated (subItems)
I'm assuming you just want to retrieve the text values from those <li> tags.
You can greatly simplify the query with DOMXPath as ->query('//li') will fetch all <li> tags in your code snippet.
$DOM = new DOMDocument();
$DOM->loadHTML($output);
$xPath = new DOMXPath($DOM);
if($xpResponse = $xPath->query('//li/text()')) {
echo "<ul>\n";
foreach($xpResponse as $xNode) {
echo "<li>" . trim($xNode->nodeValue) . "</li>\n";
}
echo "</ul>\n";
}
This will simply output (as HTML):
First item
First SubItem
Second SubItem

Want to get specific data from a webpage

I am trying hard to get data from following portion of a webpage
<div id="menu_pannel">
<ul class="sf-menu" id="nav">
<li class="current"><a href="/" class="current" >Home</a></li>
<li class="">Schedule</li>
<li class="">All Channels</li>
<li class="">Sports Channels
<ul id="submenu">
<li>Sky Sports 1</li>
<li>Sky Sports 2</li>
<li><a href="http://www.time4tv.com/2011/03/sky-sports-3.php">Sky Sports
I want to get data from for that i am using
$pattern = '|<ul id="nav" class="sf-menu">(.*?)</ul>|';
preg_match($pattern, $html, $data);
but getting emty array .
if strip_tags($html) doesn't returns what you want, you can use this example to get an array of text:
function getTextBetweenTags($string, $tagname) {
preg_match_all("#<$tagname.*?>([^<]+)</$tagname>#", $string, $matches);
return $matches[1];
}
$values = getTextBetweenTags ($html, 'a' );
foreach($values as $value) {
echo $value . '<br>';
}
where $html is a var containing your html.
If you decide to use dom parser
$doc = new DOMDocument();
$doc->loadHTML($str);
$x = new DomXpath($doc);
$ul = $x->query('//ul[#id="nav"]'); // 'id' is a unique identifier!
// Echo outerHTML of ul[#id="nav"]
echo $doc->saveHTML($ul->item(0));
demo
Use DOMDocument class for manipulating HTML content:
// $html_str is your html fragment
$doc = new DOMDocument();
$doc->loadHTML($html_str);
$ul_content = "";
$ul = $doc->getElementsByTagName("ul")->item(0);
if ($ul && $ul->getAttribute('class') == 'sf-menu') {
foreach ($ul->childNodes as $n) {
$ul_content .= $doc->saveHTML($n);
}
}
echo $ul_content;

PHP - Get links from within an element after element has been found

I have the following code....
<div class="outer">
<div>
<h1>Christmas</h1>
<ul>
<li>Holiday</li>
<li>Fun</li>
<li>Joy</li>
</ul>
<h1>4th July</h1>
<ul>
<li>Fireworks</li>
<li>Happy</li>
<li>Spectral</li>
</ul>
</div>
</div>
<div class="outer">
<div>
<h1>Christmas2</h1>
<ul>
<li>Holiday</li>
<li>Fun</li>
<li>Joy</li>
</ul>
<h1>4th July</h1>
<ul>
<li>Fireworks2</li>
<li>Happy</li>
<li>Spectral</li>
</ul>
</div>
</div>
I already know that I can find the DIV and then look inside the DIV for the elements etc by doing...
$doc->loadHTML($output); //$output being the text above
$xpath = new DOMXpath($doc);
$elements = $xpath->query('//div[#class="outer"]'); //Check outer
I know this above 3 lines will get the elements from within the DIV listed, but what I really want to be able to do is get the text of the [H1], then display the [li] values next to each H1..
the output i'm looking for is...
Christmas - Holiday, Fun, Joy
4th July - Fireworks, Happy, Spectral
Christmas2 - Holiday, Fun, Joy
4th July2 - Fireworks, Happy, Spectral
Yes you can continue to use xpath to traverse the elements on the header and get its following sibling, the list. Example:
$doc = new DOMDocument();
$doc->loadHTML($output);
$xpath = new DOMXpath($doc);
$elements = $xpath->query('//div[#class="outer"]/div');
if($elements->length > 0) {
foreach($elements as $div) {
foreach ($xpath->query('./h1', $div) as $e) {
$header = $e->nodeValue;
$list = array();
foreach ($xpath->query('./following-sibling::ul/li', $e) as $li) {
$list[] = $li->nodeValue;
}
echo $header . ' - ' . implode(', ', $list) . '<br/>';
}
echo '<hr/>';
}
}
Sample Output
I've used phpQuery for this type of issue in the past:
// include phpquery
require('phpQuery/phpQuery.php');
// initialize
$doc = phpQuery::newDocumentHTML($markup);
// get the text from the various elements
$h1Value = $doc['h1:first']->text(); // Christmas
// ... etc.
(untested)

Categories