I am a coding beginner and have my PHP/HTML web project in German. Now I want to make it available in English in the easiest way. I don't want to add other languages in the future, so I want to try it in the easiest (and maybe not the most proper) way.
I have PHP files with HTML content and the selected language available in a var, i.e.:
<?php
$lang = "en";
?>
<h1>Title in German</h1>
So all the German words are inline HTML. My idea was to create something like:
<h1>[de]Title in German[/de][en]Title in English[/en]</h1>
But I have no idea how to replace it on every load in a smart way. So it is more a topic on "live replacement".
Working with constants in an external language file is of course also an option, like all the other options to make a multilingual site I found on Stackoverflow.
But maybe there is a "quick and dirty" possibility option like the one I mentioned?
Thank you for every hint!
You could try and do this will almost only HTML and CSS. You would need to add this at the top of your page:
<?php
$pageLanguage = "en";
function getLanguageStyle($showLanguage)
{
global $pageLanguage;
$display = ($showLanguage == $pageLanguage ? 'inline' : 'none');
return " span.$showLanguage { display: $display }\n";
}
echo "<style>\n".
getLanguageStyle('en').
getLanguageStyle('de').
"</style>\n";
?>
It sets up a style for each language, which you can then use like this:
<h1><span class="de">Title in German</span><span class="en">Title in English</span></h1>
The advantage here is that you don't need to mix HTML and PHP. This is not a normal way of doing this, but it will work. On very complex pages, where these styles are applied after the first render, this might not be pleasant for your visitors.
Usually translations are made that way:
You have key to translation map for each language, then you request some function that takes proper map for that language and returns translation:
function translate(string $lang, string $key) {
/*
* This usually sits in some file in dir like `/src/i18n/en.json`
* And you do then `$translations = json_decode(require "/src/i18n/{$lang}.json")`
*/
$translations = [
'en' => [
'page.title' => 'Page Title',
...
],
'de' => [
'page.title' => 'Page Title In German',
...
],
];
return $translations[$lang][$key] ?? $key;
}
<h1><?= translate($lang, 'page.title'); ?></h1>
I need some help with my 2 WordPress function that I use inside my functions.php file to push ad codes within the blog article based on paragraph count.
What code do you currently use?
Here is the code that I currently using inside my functions.php file:
/*Add ad after 20 paragraph of post if there is more than 21 paragraph*/
add_filter( 'the_content', 'ad_20', 15 );
function ad_20( $content ) {
global $post;
if( check_paragraph_count_blog( $content ) > 21 ) {
$ad_code = '...ad code goes here...';
if ( $post->post_type == 'post' ) {
return prefix_insert_after_paragraph( $ad_code, 20, $content );
}
}
return $content;
}
// Parent Function that makes the magic happen
function prefix_insert_after_paragraph( $insertion, $paragraph_id, $content ) {
$closing_p = '</p>';
$paragraphs = explode( $closing_p, $content );
foreach ($paragraphs as $index => $paragraph) {
if ( trim( $paragraph ) ) {
$paragraphs[$index] .= $closing_p;
}
if ( $paragraph_id == $index + 1 ) {
$paragraphs[$index] .= $insertion;
}
}
return implode( '', $paragraphs );
}
//Check paragraph count on a blog post
function check_paragraph_count_blog( $content ) {
global $post;
if ( $post->post_type == 'post' ) {
$count = substr_count( $content, '</p>' );
return $count;
} else {
return 0;
}
}
What's the problem with your code?
Well, my code works fine without any error but it doesn't follow the full purpose that I want from this code.
What do you want your code to do?
The main problem with the code that I'm currently using and posted above is that both the prefix_insert_after_paragraph() function & check_paragraph_count_blog() function check for all p tags regardless of where they are located. But this is not what I want, I want the following:
Don't consider the p tags present within <code>, <pre>, <code class="some-language-name">, <pre class="some-language-name>.
Also don't consider p tags present within certain div tags, like for example <div class="callout some-class some-other-class">.
What's the problem with those certain div tags?
Well, I use several shortcode inside my article to show up some well designed note, callouts etc. Now if the counter consider those divs for counting then it may show up the ads within the shortcode design making the entire look and feel bad.
Sample Paragraph Input
<p>At the time of creating any blog or news based websites most webmasters gives the least amount of importance to the commenting system of their website, without even understanding the importance of it. Eventually comment section of a website is the only place where people interact with the author when they are exited or happy with the article and helps to grow the whole website community. In most cases they end up using some third party commenting system like Disqus or Spot.im etc. without even realizing what a blunder they are making. I’ve seen many websites (both big & popular as well as small websites) using Disqus commenting system, without even realizing the consequences. And by the time you will realize it, your site would have become so big & popular they you can’t take the risk of changing your commenting system. If you are thinking why, keep reading.</p>
<p><img src="I want to omit this p from counting"></p>
<p>As creating websites has become very easy now-a-days many non-techy people can make a websites too, but they don’t get the insights of an experienced personal. Before writing this article I’ve used disqus for months to research it thoroughly and at the same time I’ve also tried Spot.im (a new player in this arena) but in both cases I’ve come up with the same conclusion. Never ever use these third party commenting system on your website. Here are the 7 facts about Disqus and similar commenting system for which I will suggest you to stay away from them.</p>
What do you want from us?
I need your help guys. It would be really helpful if someone can provide me a rewritten version of the prefix_insert_after_paragraph() and check_paragraph_count_blog() function which will do the p tag counting and checking by omitting the condition I've described above.
Thank you in advance, looking forward to your help.
Some Update About the Answer Posted Below
The answer posted below works just fine without any problem but please note that it can only be used once. For example if you want to push 3 ads within your blog post and hence created 3 functions like ad_10(), ad_20() and ad_30(), the below code will only work in any one of them. If you put it in more than 1 function within your WordPress functions.php you might get blank content. Something to keep in mind.
Using DOMDocument - and not regexes - you can easily handle the job. The idea is to selecting all p tags that are not within those specific elements or in other words all p tags that doesn't belong to such a parent.
It's all done by a XPath query:
//p[
not(
ancestor::div[contains(#class, 'callout') or contains(#class, 'callin')]
or ancestor::pre
or ancestor::code
or a/img # As per comments
)
]
If you see you can find that it's a negated query which will look for all p elements which aren't a child of divs with callout or callin classes (you may add more classes following similar syntax), pre or code elements (Note: all pre and code elements)
By the way you don't need any other functions, all things are done in ad_20()
Regexes are not a tool made for this kind of complex situations (HTML parsing). I don't say you can't parse HTML with that. You can but unless you know perfectly what you are doing.
Live demo
add_filter('the_content', 'ad_20', 15);
function ad_20($content) {
global $post;
$adCode = '...ad code goes here...';
// Ad code will be added right after 20th paragraph
$paragraphNumber = 20;
// Convert to HTML entities
$content = mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8');
if ($post->post_type == 'post') {
libxml_use_internal_errors(true);
// Initializing a new DOM object
$dom = new DOMDocument;
// Load HTML content
$dom->loadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
// Initializing a new XPath object
$xpath = new DOMXPath($dom);
// Query all `p` tags that their parent is not those specific elements
$paragraphs = $xpath->query('//p[not(ancestor::div[contains(#class, \'callout\') or contains(#class, \'callin\')] or ancestor::pre or ancestor::code or a/img)]');
// If we have a number of satisfying paragraphs
if ($paragraphs->length > $paragraphNumber) {
// Loading and importing javascript code
// <span> is important
$script = '<span>.........code.........</span>';
$newDom = new DOMDocument;
$newDom->loadHTML($script, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$node = $newDom->getElementsByTagName('span')->item(0);
$adNode = $dom->importNode($node, true);
// Add our ad node after `$paragraphNumber`th paragraph
$paragraphs->item($paragraphNumber)->parentNode->insertBefore($adNode, $paragraphs->item($paragraphNumber));
}
libxml_use_internal_errors(false);
return $dom->saveHTML();
}
return $content;
}
I am trying to create a short submenu for CakePHP with a Database Table.
First I tried this solution how to create dynamic navigation menu cakephp which seemed outdated (because its two years old) and since I don´d need to add menus over the add function, its to big anyways.
So can I solve this with just the table in my DB, the model in Cake and an element?
Thats what I got so far:
src/template/element/main.ctp
<ul class="header main-menu">
foreach($something as $something ) :
?>
<li>
somethine
</li>
<? endforeach; ?>
</ul>
my view
<?= $this->element('main'); ?>
My Model
class Menu extends Entity
{
var $name = 'Menu';
}
Is this the way to go?
your question is a little generic, but here's something you want to consider:Html helper class
and in particular Html helper lists. That way you can do in your main.ctp:
$list = [];
foreach ($menu as $menuItem) {
$list[] = $menuItem;
}
echo $this->Html->nestedList($list);
I'm making several HTML popups that always follows a defined template.
Since there is a template (header,content,example table,more button),
I thought I can save a lot of recurring html by passing the data to a wrapper function like so:
$device_popup_data = array(
'header' => 'Header text',
'content' => 'some text<span style ="bold"> Some more text</span>',
'example' => '<table><tbody><tr><td> A lot of text here, multi lined and messy',
'more' => '',
);
echo theme_uxt_expanded_popup($device_popup_data);
function theme_uxt_expanded_popup($data){
$head = isset($data['head'])?$data['head']:'';
$content = isset($data['content'])?$data['content']:'';
$example = isset($data['example'])?$data['example']:'';
$more_html = isset($data['more'])?$data['more']:'';
$output= '<div class = "expandedTooltip">';
$output.= '<h1>'.$head.'</h1>';
$output.= '<p>'.$content.'</p>';
if(!empty($more)){
$output.= '<a class = "popupShowMore"><p>'.$more.'</p></a>';
}
$output .= '</div>';
return $output;
}
This seemed like a great idea, until I have seen that some of these fields, like the example field, may contain around 100 lines of HTML.
Pushing these long strings into the example variable seems to make very unreadable code. Something like this :
$device_popup_data = array(
'header' => 'Header text',
'content' => 'some text<span style ="bold"> Some more text</span>',
'example' => '<table><tbody><tr><td> A lot of text here</td>,<td> multi lined and
messy, and if any one</td>
<td>wants to change this string it will be very hard</td>
Real string is much longer ... </table>',
'more' => '',
);
Do you know of an efficient and readable way of doing something like this?
Do you know of an efficient and readable way of doing something like
this?
The only readable, maintainable way of doing this is to adhere to the Separation of Concerns. The points here are 1) Decoupling HTML from PHP 2) Implementing a container, like name => HTML content
You should really wrap that into a class, in order to take full advantage of DI and SRP
(see below). So, a class itself would look like as:
class TemplateBlockManager
{
private $blocks = array();
public function define($name, $file, array $vars = array())
{
ob_start();
if (!empty($vars)) {
extract($vars);
}
require($file);
$content = ob_get_clean();
$this->blocks[$name] = $content;
}
public function getBlock($name)
{
return $this->blocks[$name];
}
}
File : test.phtml
<p>
<b>Welcome to <?php echo $foo; ?></b>
</p>
Usage:
<?php
$blockManager = new TemplateBlockManager();
$blockManager->define('header', '/path/to/test.phtml', array('foo' => 'bar'));
// Should output "Welcome to bar"
echo $blockManager->getBlock('header');
This approach has a number of advantages:
You can prepare several blocks at a bootstrap stage, thus your blocks can be shared
across your pages. This reduces code duplication
You can inject an instance of a $blockManager to another classes that generate an output. This is good for unit-testing, as it adheres to the Dependency Injection
You also adhere to the Single-Responsibility Principle
You totally decouple HTML from PHP, since your templates contain basic (or none) php logic
Since your templates are totally decoupled you don't have to worry if they are long or small. You would simply define a path to the one
And finally, both HTML and PHP code are easy to maintain
I am attempting to refactor my app using the MVC paradigm.
My site displays charts. The URLs are of the form
app.com/category1/chart1
app.com/category1/chart2
app.com/category2/chart1
app.com/category2/chart2
I am using Apache Rewrite to route all requests to index.php, and so am doing my URL parsing in PHP.
I am working on the enduring task of adding an active class to my navigation links when a certain page is selected. Specifically, I have both category-level navigation, and chart-level sub-navigation. My question is, what is the best way to do this while staying in the spirit of MVC?
Before my refactoring, since the nav was getting relatively complicated, I decided to put it into an array:
$nav = array(
'25th_monitoring' => array(
'title' => '25th Monitoring',
'charts' => array(
'month_over_month' => array(
'default' => 'month_over_month?who=total&deal=loan&prev='.date('MY', strtotime('-1 month')).'&cur='.date('MY'),
'title' => 'Month over Month'),
'cdu_tracker' => array(
'default' => 'cdu_tracker',
'title' => 'CDU Tracker')
)
),
'internet_connectivity' => array(
'title' => 'Internet Connectivity',
'default' => 'calc_end_to_end',
'charts' => array(
'calc_end_to_end' => array(
'default' => 'calc_end_to_end',
'title' => 'calc End to End'),
'quickcontent_requests' => array(
'default' => 'quickcontent_requests',
'title' => 'Quickcontent Requests')
)
)
);
Again, I need to know both the current category and current chart being accessed. My main nav was
<nav>
<ul>
<?php foreach ($nav as $category => $category_details): ?>
<li class='<?php echo ($current_category == $category) ? null : 'active'; ?>'>
<?php echo $category_details['title']; ?>
</li>
<?php endforeach; ?>
</ul>
</nav>
and the sub-nav was something similar, checking for current_chart instead of current_category.
Before, during parsing, I was exploding $_SERVER['REQUEST_URI'] by /, and breaking the pieces up into $current_category and $current_chart. I was doing this in index.php. Now, I feel this is not in the spirit of the font controller. From references like Symfony 2's docs, it seems like each route should have its own controller. But then, I find myself having to define the current category & chart multiple times, either within the template files themselves (which doesn't seem to be in the spirit of MVC), or in an arbitrary function in the model (which would then have to be called by multiple controllers, which is seemingly redundant).
What is the best practice here?
Update: Here's what my front controller looks like:
// index.php
<?php
// Load libraries
require_once 'model.php';
require_once 'controllers.php';
// Route the request
$uri = str_replace('?'.$_SERVER['QUERY_STRING'], '', $_SERVER['REQUEST_URI']);
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && (!empty($_GET)) && $_GET['action'] == 'get_data') {
$function = $_GET['chart'] . "_data";
$dataJSON = call_user_func($function);
header('Content-type: application/json');
echo $dataJSON;
} elseif ( $uri == '/' ) {
index_action();
} elseif ( $uri == '/25th_monitoring/month_over_month' ) {
month_over_month_action();
} elseif ( $uri == '/25th_monitoring/cdu_tracker' ) {
cdu_tracker_action();
} elseif ( $uri == '/internet_connectivity/intexcalc_end_to_end' ) {
intexcalc_end_to_end_action();
} elseif ( $uri == '/internet_connectivity/quickcontent_requests' ) {
quickcontent_requests_action();
} else {
header('Status: 404 Not Found');
echo '<html><body><h1>Page Not Found</h1></body></html>';
}
?>
It seems like when month_over_month_action() is called, for instance, since the controller knows the current_chart is month_over_month, it should just pass that along. This is where I'm getting tripped up.
There are not "best practices" in this area. Though, there are some, that are more often used then others, and some, that are extremely bad ideas (unfortunately, these two groups tend to overlap).
Routing in MVC
While technically not a part of MVC design pattern, when applied to Web, your application needs to know which controller to initialize and what method(s) to call on it.
Doing explode() to gather this sort of information is a bad idea. It is both hard to debug and maintain. A much better solution is to use regular expressions.
Basically you end up having a list of routes, that contain a regular expression and some fallback values. You loop through that list and on fists match extract the data and apply default values, where data was missing.
This approach also frees you to have much wider possibilities for order of parameters.
To make the solution easier to use, you can also add functionality, that turns a notation string into a regular expression.
For example (taken from some unit-test, that I have):
notation: test[/:id]
expression: #^/test(:?/(?P<id>[^/\.,;?\n]+))?$#
notation: [[/:minor]/:major]
expression: #^(:?(:?/(?P<minor>[^/\.,;?\n]+))?/(?P<major>[^/\.,;?\n]+))?$#
notation: user/:id/:nickname
expression: #^/user/(?P<id>[^/\.,;?\n]+)/(?P<nickname>[^/\.,;?\n]+)$#
While creating such a generator will not be all that easy, it would be quite reusable. IMHO the time invested in making it would be well spent. Also, the use of (?P<key>expression) construct in regular expressions provides you with a very useful array of key-value pairs from the matched route.
Menus and MVC
The decision about which menu item to highlight as active should always be the responsibility of current view instance.
More complicated issue is where the information, that is necessary for making such decision, comes from. There are two source if data that are available to a view instance: information that was passed to view by controller and data, that view requested from model layer.
The controller in MVC takes the user's input and, based on this input, it changes the state of current view and model layer, by passing said values. Controller should not be extracting information from model layer.
IMHO, the better approach in this case is to relay on model layer for information about both menu content and the currently active element in it. While it's possible to both hardcode the currently active element in view and relay on controllers passed informations, MVC is usually used in large scale application, where such practices would end up hurting you.
The view in MVC design pattern is not a dumb template. It's a structure, that is responsible for UI logic. In context of Web that would mean creating a response from multiple template, when necessary, or sometimes just simply sending an HTTP location header.
Well, I had almost the same trouble when was writing CMS-like product.
So I've spend some time trying to figure out how to make this work and keep the code more maintainable and clean as well.
Both CakePHP and Symfony route-mecanisms have a bit inspired me but it wasn't good enough for me.
So I'll try to give you an example of how I do this now.
My question is, what is the best way to do this while staying in the
spirit of MVC?
First, In general, best practice is NOT TO USE procedural approach with MVC in web development at all.
Second, keep the SRP.
From references like Symfony 2's docs, it seems like each route should
have its own controller.
Yeah, that's right approach, but it doesn't mean that another route match can't have the same controller, but different action.
The main disadvantage of your approach (code that you have posted) is that you mix responsibilities and you're not implementing MVC-inspired pattern.
Anyway, MVC in PHP with procedural approach is just a horrible thing.
So, what exactly you are mixing is:
Route mechanism logic (It should be another class) not in a "controller" and route map as well
Request and Response responsibilites (I see that it isn't obvious to you)
Class autoloading
Controller logic
All those "parts" should have one class. Basically, they have to be included in index or bootstrap files.
Also, by doing so:
require_once 'controllers.php';
You automatically include ALL controllers per match (even on no-match). It actually has nothing to do with MVC and leads to memory leaks.
Instead, you should ONLY include and instantiate the controller that matches against URI string.
Also, be careful with include() and require() as they may lead to code duplication if you include the same file somewhere twice.
And also,
} elseif ( $uri == '/' ) {
index_action();
} elseif ( $uri == '/25th_monitoring/month_over_month' ) {
month_over_month_action();
} elseif ( $uri == '/25th_monitoring/cdu_tracker' ) {
cdu_tracker_action();
} elseif ( $uri == '/internet_connectivity/intexcalc_end_to_end' ) {
intexcalc_end_to_end_action();
It's extremely unwise to do a match using if/else/elseif control structures.
Okay, what if you have 50 matches? or even 100? Then you need to write 50 or 100 times to write else/elseif accordingly.
Instead, you should have a map and (an array for example) iterate over it on each HTTP request.
The general approach of using MVC with routing mechanism comes down to:
Matching the request against route map (and keep somewhere parameters if we have them)
Then instantiate appropriate controller
Then pass parameters if we have them
In PHP, the implementation would look like:
File: index.php
<?php
//.....
// -> Load classes here via SPL autoloader or smth like this
// .......
// Then -> define or (better include route map from config dir)
$routes = array(
// -> This should default one
'/' => array('controller' => 'Path_To_home_Controller', 'action' => 'indexAction'),
'/user/:id' => array('controller' => 'Path_to_user_controller', 'action' => 'ViewAction'),
// -> Define the same controller
'/user/:id/edit' => array('controller' => 'Path_to_user_controller', 'action' => 'editAction'),
// -> This match we are going to hanlde in example below:
'/article/:id/:user' => array('controller' => 'SomeArticleController', 'action' => )
);
// -> Also, note you can differently handle this: array('controller' => 'SomeArticleController', 'action' => )
// -> Generally controller key should point to the path of a matched controller, and action should be a method of the controller instance
// -> But if you're still on your own, you can define it the way you want.
// -> Then instantiate common classes
$request = new Request();
$response = new Response();
$router = new Router();
$router->setMap( $routes );
// -> getURI() should return $_SERVER['REQUEST_URI']
$router->setURI( $request->getURI() );
if ( $router->match() !== FALSE ) {
// -> So, let's assume that URI was: '/article/1/foo'
$info = $router->getAll();
print_r ( $info );
/**
* Array( 'parameters' => Array(':id' => '1', ':user' => 'foo'))
* 'controller' => 'Path_To_Controller.php'
* 'action' => 'indexAction'
*/
// -> The next things we are going to do are:
// -> 1. Instantiate the controller
// -> 2. Pass those parameters we got to the indexAction method
$controller = $info['controller'];
// -> Assume that the name of the controller is User_Controller
require ( $controller );
// -> The name of class should also be dynamic, not like this, thats just an example
$controller = new User_Controller();
$arguments = array_values( $info['parameters'] );
call_user_func_array( array($controller, $info['action']), $arguments );
// -> i.e we just called $controller->indexAction('1', 'foo') "dynamically" according to the matched URI string
// -> idealy this should be done like: $response->send( $content ), however
} else {
// -> In order not to show any error
// -> redirect back to "default" controller
$request->redirect('/');
}
In my MVC-inspired applications I do route like this:
(Where I use Dependecy Injection and keep the SRP)
<?php
require (__DIR__ . '/core/System/Auload/Autoloader.php');
Autoloader::boot(); // one method includes all required classes
$map = require(__DIR__ . '/core/System/Route/map.php');
$request = new Request();
$response = new Response();
$mvc = new MVC();
$mvc->setMap( array_values($map) );
// -> array_values($map) isn't accurate here, it'd be a map of controllers
// -> take this as a quick example
$router = new Router();
$router->setMap( $map );
$router->setURI( $request()->getURI() );
if ( $router->match() !== FALSE ) {
// -> Internally, it would automatically find both model and view instances
// -> then do instantiate and invoke appropriate action
$router->run( $mvc );
} else {
// No matches handle here
$request->redirect('/');
}
I found this to be more appropriate for me, after poking around Cake and Symfony.
One thing I want to note:
It's not that easy to find good articles about MVC in PHP. Most of them are just wrong.
(I know how it feels, because first time I've started to learn from them, like so many people do)
So my point here is:
Don't make the same mistake like I did before. If you want to learn MVC, start doing this by reading
Zend Framework or Symfony Tutorials. Even the ones are bit different, the idea behing the scene is the same.
Back to the another part of the question
Again, I need to know both the current category and current chart
being accessed. My main nav was
<nav>
<ul>
<?php foreach($nav as $category => $category_details): ?>
<li class='<?php echo ($current_category == $category) ? null : 'active'; ?>'>
<?php echo $category_details['title']; ?>
</li>
<?php endforeach; ?>
</ul>
</nav>
First of all, don't concatenate the string, instead use printf() like:
<?php echo $category_details['title']; ?>
If you need this to be everywhere (or at least in many different templates), I'd suggest to this to have in a common abstact View class.
For example,
abstract class View
{
// -> bunch of view reusable methods here...
// -> Including this one
final protected function getCategories()
{
return array(
//....
);
}
}
class Customers_View extends View
{
public function render()
{
$categories =& $this->getCategories();
// -> include HTML template and then interate over $categories
}
}