Check if a view exists and do an #include in Laravel Blade - laravel

With Laravel Blade, is there an elegant way to check if a view exists before doing an #include?
For example I'm currently doing this:
#if(View::exists('some-view'))
#include('some-view')
#endif
Which gets quite cumbersome when 'some-view' is a long string with variables inside.
Ideally I'm looking for something like this:
#includeifexists('some-view')
Or to make #include just output an empty string if the view doesn't exist.
As an aside, I would also like to provide a set of views and the first one that exists is used, e.g.:
#includefirstthatexists(['first-view', 'second-view', 'third-view'])
And if none exist an empty string is output.
How would I go about doing this? Would I need to extend BladeCompiler or is there another way?

Had a similar issue. Turns out that from Laravel 5.3 there is an #includeIf blade directive for this purpose.
Simply do #includeIf('some-view')

I created this blade directive for including the first view that exists, and returns nothing if none of the views exist:
Blade::directive('includeFirstIfExists', function ($expression) {
// Strip parentheses
if (Str::startsWith($expression, '(')) {
$expression = substr($expression, 1, -1);
}
// Generate the string of code to render in the blade
$code = "<?php ";
$code .= "foreach ( {$expression} as \$view ) { ";
$code .= "if ( view()->exists(\$view) ) { ";
$code .= "echo view()->make(\$view, \Illuminate\Support\Arr::except(get_defined_vars(), array('__data', '__path')))->render(); ";
$code .= "break; } } ";
$code .= "echo ''; ";
$code .= "?>";
return $code;
});

Related

Using namespace in laravel view

How to use namespace in laravel View? I mean I have three different folders admin, frontend and client in app/views folder.
If I want to load a partial template lets say from admin section views/admin/partials/flush.blade.php in views/admin/account/profile.blade.php I have to include it like:
#include('admin/partials/flush')
instead I want to just use
#include('partials/flush')
How can i do that?
You can extend blade and write a function that fits your needs. Like this:
Blade::extend(function($view, $compiler)
{
$pattern = $compiler->createMatcher('includeNamespaced');
$viewPath = realpath($compiler->getPath());
$parts = explode(DIRECTORY_SEPARATOR, $viewPath);
$viewsDirectoryIndex = array_search('views', $parts);
$namespace = $parts[$viewsDirectoryIndex + 1];
$php = '$1<?php ';
$php .= 'if($__env->exists(\''.$namespace.'.\'.$2)){';
$php .= 'echo $__env->make(\''.$namespace.'.\'.$2)->render();';
$php .= '}';
$php .= 'else {';
$php .= 'echo $__env->make($2)->render();';
$php .= '}';
$php .= '?>';
return preg_replace($pattern, $php, $view);
});
And then use it like you described but with includeNamespaced
#includeNamespaced('partials/flush')
If you want to you could also override #include by naming it createMatcher('include')
Note "your" #includeNamespaced / #include wont have the option to pass arguments to the view your including (second parameter)
A little tip: When you change the code inside Blade::extend you have to delete the cached views in storage/views for the changes to show up in your browser.

How to concatenate variables comes from model in controller

I need to concatenate variables come from model.I send the role_id from controller to model and get the role name according to its id.
controller:
function get_role_name(){
$data['rec']=$this->amodel->get_section();
foreach($data['rec'] as $i)
{
$name['x']=$this->amodel->get_name($i->role_id);
}
$this->load->view('sections',array_merge($data,$name));
}
I write $name['x'].=$this->amodel->get_name($i->role_id); but it shows the error which undefined index:x.How can I concatenate the role name in cotroller to send it to view?
you probably didnt define $name
$name = array();
// your foreach
foreach ()
btw, the concatenating was ok
$var = "foo";
$var .= "foo"
// will result in "foofoo"
If you want to append something using the .= syntax you need to make sure the variable or array exists first.
Try this:
function get_role_name(){
$data['rec']=$this->amodel->get_section();
$name = array();
foreach($data['rec'] as $i) {
if (isset($name['x'])) {
$name['x'] .= $this->amodel->get_name($i->role_id);
} else {
$name['x'] = $this->amodel->get_name($i->role_id);
}
}
$this->load->view('sections',array_merge($data,$name));
}

Article Tags shown in Article List-Layout

So I've been adding tags you add to articles in Joomla!, which works fine. But now I want to show the tags in the article list layout that is default in Joomla.
I found and made an override for the list-layout and tried to add the tags code from a single article layout to the list-layout. Underneath is the code I tried to add in the list-layout. But none of the tags are shown in the layout..
<?php
// set tags
$tags = '';
if (!empty($this->item->tags->itemTags)) {
JLoader::register('TagsHelperRoute', JPATH_BASE . '/components/com_tags/helpers/route.php');
foreach ($this->item->tags->itemTags as $i => $tag) {
if (in_array($tag->access, JAccess::getAuthorisedViewLevels(JFactory::getUser()->get('id')))) {
if($i > 0) $tags .= ', ';
$tags .= ''.$this->escape($tag->title).'';
}
}
}
$args['tags'] = $tags;
?>
If this isn't clear, I can try to explain it a different way.
Your php works in the sense that it builds a set of "tag" links but it doesn't actually echo it out to the page. You need to add this line either at the end of your code or somewhere after, where you want to display the tags.
echo $tags;
e.g.
<?php
// set tags
$tags = '';
if (!empty($this->item->tags->itemTags)) {
JLoader::register('TagsHelperRoute', JPATH_BASE . '/components/com_tags/helpers/route.php');
foreach ($this->item->tags->itemTags as $i => $tag) {
if (in_array($tag->access, JAccess::getAuthorisedViewLevels(JFactory::getUser()->get('id')))) {
if($i > 0) $tags .= ', ';
$tags .= ''.$this->escape($tag->title).'';
}
}
}
$args['tags'] = $tags;
echo $tags;
?>
I'm not sure what you're using $args for either, it could probably be removed, unless you're using somewhere else.

Codeigniter: Creating helper and global message arrays for feedback & errors

So there are instances where there could be one or more errors to report to the user (and to notify me about) that could be caused at a controller level (input, validation) or model level.
I'm considering creating a basic helper for 'feedback' that basically has global message arrays (notice, error, success)
Then either at the model or controller level, if something goes wrong (or right!), I can call the feedback function.
feedback('error','Connection is temporarily down blah')
I won't need to pass it through to my views as it will be globally set so I can just call something like $this->feedback->display_all().
Is this an ok/MVC friendly way to do things? It seems like a straight-foward method for me to implement
For my project, I created a tiny mdl_error model.
This model has one public function, throwError, and some private helpers that will show flash notices to the user and send an email to me with current values and session data if need be. The model is autoloaded and is only called if needed.
Here is basically what it looks like:
<?php
class mdl_error extends CI_Model
{
//types: error, alert, good
function throwError($type, $message, $info="", $flash=true, $email=true)
{
if($flash){
$alert = $type."|".$message;
$this->session->set_userdata(array("flash" => $alert));
}
if($email){
$problems = $this->recursivePrintingOfVariables($info);
$sessionData = $this->recursivePrintingOfVariables($this->session->userdata);
$emailMessage = "Name<br/> <br/>Something has happened. <br/> <br/>";
$emailMessage .= "The type was: {$type}<br/>The message was: {$message}<br/> <br/> <br/>";
$emailMessage .= "Here is the local variables at the time:<br/> <br/>{$problems}<br/> <br/> <br/>";
$emailMessage .= "Here is the session data:<br/> <br/>{$sessionData}<br/> <br/> <br/>";
$emailMessage .= "Please solve this problem or we are all dooooooomed.<br/><br/>Love,<br/>Website";
$this->load->library('email');
$this->email->from("my email");
$this->email->to("error#whatever.com");
$this->email->subject($type.' Message from Website');
$this->email->message($emailMessage);
$this->email->send();
}
}
function recursivePrintingOfVariables($info)
{
$keys = array_keys($info);
$string = "";
foreach($keys as $key){
$string .= $key." => ";
if(is_array($info[$key])){
$string .= "Inner Array<br/>";
$string .= "<div style='margin-left:15px;'>";
$string .= $this->recursivePrintingOfVariables($info[$key]);
$string .= "</div>";
}else{
$string .= $info[$key];
}
$string .= "<br/><br/>";
}
return $string;
}
}
Then, if there is a spot in my code where an error happens, I just call:
$this->mdl_error->throwError("error","something happend", get_defined_vars());
If you use the show_error('Your error message'); function in your controller you will achieve the same. If you want to customise the look of the error you need to work with the error_general.php file found in applications/errors.
If you also want to log the errors you could use the log_message('level', 'message'); function in your controller.

Having Problem with $_get in Codeigniter

I have a page called list.php which retrieves from database and shows all the student names with their respective ids in a list. In raw php, this is how I have done this-
include("connect.php");
$query = "SELECT * FROM marks ";
$result = mysql_query($query);
$num = mysql_num_rows ($result);
mysql_close();
if ($num > 0 ) {
$i=0;
while ($i < $num) {
$studentname = mysql_result($result,$i,"studentname");
$studentid = mysql_result($result,$i,"studentid");
?>
And then---
<? echo $studentname ?>
<?
++$i; } } else { echo "No Record Found"; }
?>
When a user clicks on any of the student names, it takes the user to the page of that particular student and in that page I have a code like following-
include("connect.php");
$number = $_GET['studentid'];
$qP = "SELECT * FROM student WHERE studentid = '$number' ";
$rsP = mysql_query($qP);
$row = mysql_fetch_array($rsP);
extract($row);
$studentid = trim($studentid);
$studentname = trim($studentname);
$studentgender = trim($studentgender);
The above code is working just fine. Now as far as I know $_get is disable in Codeigniter. But how to do the exact same thing that I mentioned above in codeigniter if $_get is disabled ? I went through some tutorials on alternative way of using $_get, but I didn't understand those well. Would you please kindly help? Thanks in Advance :)
The usage of $_GET is discouraged in CI.
The simpliest way to rewrite that files is not using $_GET. Just add method='post' to your forms and tell your ajax requests to use post, if you have any. Use $_POST in PHP instead of $_GET.
If you are absolutely sure you need get requests passing parameters, you have to enable query strings. You can do it in your CI's config file:
$config['enable_query_strings'] = TRUE;
See section 'Enabling query strings' for details. But enabling query strings will cause Url helper and other helpers that generate URLs to malfunction.
So my suggestion is to use POST requests.
UPDATE Replace
<? echo $studentname ?>
With
<? echo $studentname ?>
Create method studentprofile:
<?php
class Yourcontroller extends CI_Controller {
public function studentprofile($id)
{
include("connect.php");
$number = $id;
$qP = "SELECT * FROM student WHERE studentid = '$number' ";
$rsP = mysql_query($qP);
$row = mysql_fetch_array($rsP);
extract($row);
$studentid = trim($studentid);
$studentname = trim($studentname);
$studentgender = trim($studentgender);
// and so on...
}
}
?>

Resources