I have a model that implements NestedSet behaviour:
Page:
actAs:
NestedSet:
hasManyRoots: true
rootColumnName: root_id
columns:
slug: string(255)
name: string(255)
Example fixtures:
Page:
NestedSet: true
Page_1:
slug: slug1
name: name1
Page_2:
slug: slug2
name: name2
children:
Page_3:
slug: page3
name: name3
I am looking for the easiest way to implement breadcrumb navigation (trail). For example, for Page_3 navigation will look like this:
name2 > <a href="page2/page3>name3</a>
Since I hate having any kind of logic in templates (and partials), here's my slightly improved version.
//module/templates/_breadcrumbElement.php
<?php foreach ($node as $child): ?>
<li>
<?php echo $child->getName() ?>
<?php if (count($child->get('__children')) > 0): ?>
<ul>
<?php include_partial('node', array('node' => $child->get('__children'), 'parent' => $child)) ?>
</ul>
<?php endif; ?>
</li>
<?php endforeach; ?>
So, all the logic for building a url is now in Page::getPath() method.
class Page extends BasePage
{
/**
* Full path to node from root
*
*/
protected $path = false;
public function __toString()
{
return $this->getSlug();
}
public function getPath($parent = null)
{
if (!$this->path)
{
$this->path = join('/', null !== $parent ? array($parent->getPath(), $this) : array($this));
}
return $this->path;
}
}
What I don't like it having to pass $parent to Page::getPath(). It just doesn't make any semantical sense.
Almost the same as in the other question, but you have to add a 'parentUrl' variable :
//module/templates/_breadcrumbElement.php
foreach ($node->get('__children') as $child) :
if ($child->isAncestorOf($pageNode)):
$currentNodeUrl = $parentUrl . $child->getSlug() . '/';
echo link_to($child->getName(), $currentNodeUrl) . ' > ' ;
include_partial('module/breadcrumbElement', array('node' => $child, 'pageNode' => $pageNode, 'parentUrl' => $currentNodeUrl));
endif;
endforeach;
Feed it the root of your tree as $node (hydrate it hierarchically), the node of the current page as $pageNode, and '' as $currentNodeUrl and add ' > ' and the link to the current page.
Why does this solution use recursion and not getAncestors()? Because your urls seem to imply recursion.
Another answer, more simple (and perhaps more efficient), with getAncestors() and recursion:
//module/templates/_breadcrumbElement.php
if ($node = array_pop($nodes)) // stop condition
{
$currentNodeUrl = $parentUrl . $node->getSlug() . '/';
echo link_to($node->getName(), $currentNodeUrl) . ' > ' ;
include_partial('module/breadcrumbElement', array(
'nodes' => $nodes, 'parentUrl' => $currentNodeUrl));
}
Call this with an array of ancestor nodes or find a way to pop a Doctrine_Collection if you want to use it with getAncestors() directly.
Again, all your problem comes from the fact that your urls are recursively computed, it would be simpler and faster to display if you had a colum path with the current url (but then you would have to compute, update it), etc... consider doing this if you have more reads than writes (if your tree does not change often).
Related
I'm developing a theme on a local development server. But when I try to get the featured image of posts into my home page, I get a 404 error due to the url appearing like this:
http://localhost:8888/crystal/%E2%80%9Dhttp:/localhost:8888/crystal/wp-
content/uploads/2018/04/restaurant-kitchen-inspired-design-ideas.png
See how the domain repeats itself?
I've checked my wp_options table in the database and it looks correct. Both "siteurl" and "home" does have the "http://" already and does not have a "/" after the url. I also already tried adding this script to my wp-config.php:
define('WP_HOME','http://localhost:8888/crystal');
define('WP_SITEURL','http://localhost:8888/crystal');
and this to my functions.php file:
update_option( 'siteurl', 'http://localhost:8888/crystal' );
update_option( 'home', 'http://localhost:8888/crystal' );
but that didn't fix it.
So far, it seems to be only happening when I try to use "wp_get_attachment_image_src( get_post_thumbnail_id()" to get the featured image.
Here is my code:
<?php
$args = array(
'post_type' => 'tournament',
'post_status' => 'publish',
'posts_per_page' => '10'
);
$tournaments_loop = new WP_Query( $args );
if ( $tournaments_loop->have_posts() ) :
while ( $tournaments_loop->have_posts() ) : $tournaments_loop
>the_post();
// Set variables
$title = get_the_title();
$description = get_the_content();
$tournament_date_time = get_field('tournament_date_time');
$location = get_field('location');
$featured_image = wp_get_attachment_image_src(
get_post_thumbnail_id(), 'full' );
$tournament_image = $featured_image[0];
// Output
?>
<div class=”tournament”>
<h3><?php echo $title; ?></h3>
<p><?php echo $tournament_date_time; ?></p>
<p><?php echo $location; ?></p>
<img src=”<?php echo $tournament_image; ?>” alt=”<?php echo
$title; ?>”>
</div>
<?php
endwhile;
wp_reset_postdata();
endif; ?>
Thank you.
Am creating a custom page using Opencart. Here am using foreach for displaying customer details.
But customer details not showing.
Following codes:
.tpl
<?php foreach($dealerData as $invoice){ ?>
<label> <b>Dealer Name:</b> <?php echo $invoice['name']; ?></label><br>
<label><b>Dealer TIN Number:</b> <?php echo $invoice['tin_number'];?></label><br>
<?php } ?>
Controller
$query13 = $this->db->query("select concat(firstname, ' ', lastname) as name, tin_number from ".DB_PREFIX."customer where customer_id='".$customer_id."'");
$dataDelar = $query13->rows;
foreach ($dataDelar as $dealer) {
$data['dealerData'][] = array(
'name' => $dealer['name'],
'tin_number' => $dealer['tin_number']
);
}
Why are you putting queries in your controller? You have models van database related functions. An foreach on the variable $invoiceData1 should work, you can see in the print_r that there is 1 array in the array. Did you put the print_r in your controller? So yes, look bellow that, maybe you are overriding $invoiceData1.
EDIT
You are not creating an empty array to put your values in:
$query13 = $this->db->query("select concat(firstname, ' ', lastname) as name, tin_number from ".DB_PREFIX."customer where customer_id='".$customer_id."'");
$dataDelar = $query13->rows;
$data['dealerData'] = [];
foreach ($dataDelar as $dealer) {
$data['dealerData'][] = array(
'name' => $dealer['name'],
'tin_number' => $dealer['tin_number']
);
}
I meet a trouble with string.
I use file_get_contents($url) to get content of a website.
$content = tile_get_contents($url);
$arrTmp = explode('>',$content);
var_dump (trim( $arrTmp[100]) ) => result is: string '<td width="33.3333333333%" valign="top"'
echo trim( $arrTmp[100]); => nothing.
Thanks in advance!
your sample seems to be incomplete
you define $arr
where does $arrTmp comes from?
what is $i? is it defined?
whats between the var_dump and echo?
and whats the purpose of this Action?
EDIT:
just tested:
$url = 'http://w3schools.com/tags/ref_standardattributes.asp';
$ctx = stream_context_create(array('http'=> array( 'timeout' => 60 ) ));
$content = file_get_contents($url, false, $ctx);
$arrTmp = explode('>',$content);
for($i = 0; $i < count($arrTmp); $i++)
{
echo '<br />';
echo 'Res->'.htmlspecialchars(trim($arrTmp[$i]));
}
result:
Res-><!DOCTYPE html
Res-><html lang="en-US"
Res-><head
Res-><title
and so on ...
maybe a server-setup-issue? but i have no idea what it could be at your side ...
I am trying to save the order of a list of images to the database when using jquery sortable.
I feel i am very close, but cant get my head around the final details.
I am working with CI 2.1.3 and jquery-ui 1.10.3.
I have a dynamicaly generated list with an image:
<ul id="order">
<li id="item-1"><img src="abc.jpg" /></li>
<li id="item-2"><img src="def.jpg" /></li>
<li id="item-3"><img src="ghi.jpg" /></li>
</ul>
And the following Jquery:
<script>
$(document).ready(function() {
$( "#order" ).sortable({
opacity: 0.6,
cursor: 'move',
update: function(event, ui){
var order = $(this).sortable("serialize");
console.log(order);
$.ajax({
url: "http://localhost/gridrobin/home/save_order",
type: 'POST',
data: order,
success: function (data) {
$("#test").html(data);
}
});
}
});
});
</script>
This works fine and i can reorder my list. Now i want to save the new order to the database. I send the ajax post to the controller and it comes through. I checked with a var_dump.
//var_dump($_POST);
$items = $this->input->post('item');
$total_items = count($this->input->post('item'));
echo '<h3>Debugging</h3>';
echo "<p>Total items sent: $total_items</p>";
$this->rd_model->update_order($total_items, $items);
Then I send this data to my model:
for($item = 0; $item < $total_items; $item++ )
{
$data = array(
'id' => $items[$item],
'order' => $order = $item
);
$this->db->where('id', $data['id']);
$this->db->update('portfolio_items', $data);
echo '<br />'.$this->db->last_query();
}
And echo out the last db-query for debugging.
Now when i switch item 1 and item 2, i get a 500 internal error. When i switch them back, i receive the echo of the last query executed, which seems fine.
UPDATE `portfolio_items` SET `order` = 1 WHERE `id` = '1'
UPDATE `portfolio_items` SET `order` = 2 WHERE `id` = '2'
UPDATE `portfolio_items` SET `order` = 3 WHERE `id` = '3'
I dont quite understand why the database updates when th list is switched back to its orignial state, but not otherwise.
UPDATE
For people with the same problem, sakibmoon answer helped me a lot, but the main problem was a duplicate entry error, because apparently i had set the order table as a unique index...
The problem is within your data array in the model. Change that with this -
$data = array(
'id' => $items[$item],
'order' => $item+1
);
Also change the update line -
$this->db->update('portfolio_items', $data['order']);
UPDATE:
Couple of changes. Change the update to this-
$this->db->update('portfolio_items', array('order' => $data['order']));
The code is working now if I set $config['csrf_protection'] = FALSE in config.php. But you should set it to TRUE. I don't know how to make that work. All I know is that you have to send csrf_token with your ajax call. You should create a separate question for that. This question title means something entirely different.
Please see my question in the template section below:
Form (showSuccess):
<?php echo form_tag('job/salarySubmit') ?>
<input type="hidden" name="job_id" value="<?php echo $job->getId(); ?>">
<input type="submit" value="View Salary">
</form>
Action:
public function executeSalarySubmit(sfWebRequest $request)
{
$this->forward404Unless($request->isMethod('post'));
$param = array('job_id' => $request->getParameter('job_id'), );
$this->redirect('job/salary?'.http_build_query($param));
}
public function executeSalary(sfWebRequest $request)
{
$this->object_id = $request->getParameter('job_id');
$this->salary = $this->getRoute()->getObject();
}
Template (salarySuccess.php):
<?php echo $object_id; ?> // returns correct job_id: 6100, but when I try to access the object's other getters (example: echo $object_id->getName(), I get "Fatal error: Call to a member function getName() on a non-object"
<?php echo $salary->getName(); ?> //works, but it gets the wrong name. It's returning the first job in my DB with an ID of "1" which is not correct... it needs to be 6100
Routing:
job_salary:
url: /job/salary/:job_id
param: { module: job, action: salary }
class: sfDoctrineRoute
options: { model: Job, type: object }
requirements:
id: \d+
sf_method: [GET]
use var_dump() on your template variables.
You'll see that $object_id is not an object (it is a non-object, like the error message says). $object_id is most likely a string or an integer and its value must be "6100".
$salary is not the object you're looking for, because sfDoctrineRoute looks for a parameter called id, and you named it job_id in your routing.yml (which is strange, because you name it id in this route's requirements.