i have a view where a different tagged component should be rendered depending by the value of a variable where the name is stored. For example
#if( $a['type'] == 'component' )
"<x-{$a['name']} />"
#endif
But i can't find how to do it the right way, because using brakets {{ }} will also print them on the page ( before and after the component ).
The component class also has some function that is being called, so the #component directive would only solve a part of the problem.
I might have figured out the solution and i will post it in here for reference. It currently works but i can't say it won't give me some trouble later on, In case you find a better approach i will be happy to have a look.
After having created a few blade components as usual
php artisan make:component MyComponent1
php artisan make:component MyComponent2
php artisan make:component MyComponent3
and having declared all needed properties and methods, you can either include the components inside a view the regular way
<html>
<head></head>
<body>
#if($somethingHappens)
<x-my-component1 a="" b="" :c="$c" class="" />
#elseif ($somethingElseHappens)
<x-my-component2 a="" b="" :c="$c" class="" />
#else
<x-my-component3 a="" b="" :c="$c" class="" />
#endif
</body>
</html>
Or, in case you would like more flexibility deciding what component should be used at runtime and generate the component tags somewhere else outside the view, i have found this solution
//some code.....
return('myview')->with([
'type' => 'component',
'component' => '<x-my-component3 a="" b="" :c="$vars[\'c\']" class="" />',
'vars' => [ 'c' => 'somevalue' ]
]);
#################
//myview.blade.php
<html>
<head></head
<body>
#php
if($type == 'component')
echo compileStringComponent(
$component,
$__env,
$vars
);
#endphp
</body>
</html>
################
//file containing the function
use Illuminate\View\Factory as ViewFactory;
//This function takes the whole tagged component as string and returns the corresponding html
function compileStringComponent(string $component, ViewFactory $__env, $vars = null )
{
$compiled = Blade::compileString($component);
ob_start();
try {
eval('?>'.$compiled);
} catch (\Exception $e){
ob_get_clean();
throw( $e);
}
$content = ob_get_clean();
return $content;
}
A few notes:
1) Blade::compileString returns a compiled string to be evaluated, and inside the code there are a few references to the $__env variable which is an instance of Illuminate\View\Factory and exists inside the view already. This means that if the function is called outside the view, the $__env variable must be passed to the caller
2) The $vars array is needed in case data is passed to the component through the :attributes for the same reason as above, because those variables will not exist inside the caller and must be passed to it
3) ob_start() and ob_get_clean() are used to avoid sending incomplete views to the user in case any error arises.
I hope it will helps somebody
Related
I'm trying to create a variable accessible by two different controller functins in laravel. How can I do that. The first function gets a value from a blade, it stores it in a variable and then I want to pass that variable with value to another controller function. For example, the following blade passes obj_id to controller:
1) My blade:
<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<head>
<title>test</title>
</head>
<body>
<form method='post' action="/hard">
{{csrf_field()}}
<br>
<legend><i> Fill Data </i></legend>
<br>
<label>
OBJECT ID:
<input name='obj_id' type='text' minlength="8" required="" oninvalid="this.setCustomValidity('8 char at least')">
</label>
<br>
<input type='submit' value="Submit!">
</form>
<br>
<br>
</body>
</html>
2) My controller function Roger correctly gets obj_id (I have tested ot with dd)
public function Roger(Request $p)
{
$t = $p-> get('obj_id'); //I want $t to be global variable
//dd($t);
}
3) and then I want to pass $t to function Roger1 in the same controller
public function Roger1()
{
dd($t);
}
I have tried to declare $t as global with no success. I'm a little bit confused with $this and tried several combinations with no success.
Could you assist please?
You can use the session to store a variable
public function Roger(Request $p)
{
$t = $p-> get('obj_id'); //I want $t to be global variable
$p->session()->put('myvalue', $t);
}
public function Roger1(Request $p)
{
$p->session()->get('myvalue);
}
https://laravel.com/docs/5.8/session#storing-data
Scenatio #01
IF both methods are in the same controller AND your second method is called inside the first method (in the same call), you can just do:
class CoolController extends Controller {
public $var;
public function first_method(Request $value)
{
// Example 1: passing the value as a parameter:
$this->second_method($value);
// Example 2: passing the value through a class variable:
$this->var = $value; // $value: 'some-text'
$this->third_method();
}
public function second_method($value)
{
dd($value); // 'some-text'
}
public function third_method()
{
dd($this->var); // 'some-text';
}
}
Scenatio #02
Now, in the case you want to make a request from your view to set a value in your first method, and then another request calling your second method and getting that value that was "stored" in the first call.. well you can use any of this approaches. Why? because both call are in different lifecycles.
When the first call ended the value assigned in the first method (stored in memory) will be erased when the request is finished. That's why your second call will get a null value if you try to use it.
To store a temporary variable you have several paths:
Store it in the database.
Store it in the cache.
Send the value as a request parameter when doing the second call.
Hey as i am passing a blade view which is having it own controller also i am including it into the view which does not have its own controller. it gives me an undefined variable error can any one help me how to it.
I have a view which does not have any controller only have Route like this Route::get('index', function () { return view('index'); }); in this view i am passing another view which having its own controller and also having some data from an array. but after using this view inside the view i get undefined variable error.
Two steps :
Declare & transfer $variable to View from Controller function.
public function index()
{
return view("index", [ "variable" => $variable ]);
}
Indicate where transferred $variable from Controller appear in view.blade.php.
{{ $variable }}
If you do not make sure, $variable is transferred or not
{{ isset($variable) ? $variable : '' }}
If this helps anyone, I was completely ignorant to the fact that my route was not hooked with the corresponding controller function and was returning the view directly instead, thereby causing this issue. Spent a good half hour banging my head till I realized the blunder.
Edit
Here again to highlight another blunder. Make sure you're passing your array correctly. I was doing ['key', 'value] instead of ['key' => 'value'] and getting this problem.
You can try this:
public function indexYourViews()
{
$test = "Test Views";
$secondViews = view('second',compact('test'));
return view('firstview',compact('secondViews'));
}
and after declare {{$secondViews}} in your main view file(firstview).
Hope this helps you.
public function returnTwoViews() {
$variable = 'foo bar';
$innerView = view('inner.view', ['variable' => $variable]);
return view('wrapper.view, ['innerView' => $innerView]);
}
This may be what you are looking for?
... inside your wrapper.view template:
{!! $innerView !!}
EDIT: to answer the question in the comment: In order to fetch each line you for do this inside your $innerView view:
#foreach($variable as $item)
{{ $item }}
#endforeach
... and in the wrapper view it will still be {!! $innerView !!}
I have a problem understanding how variables work inside the Laravel templating system, Blade.
I set the variables in the controller, I can see them in the first view I make, but not inside the next one.
I'm using a master.blade.php file that holds the header and footer of the page, yielding the content in the middle. I can use the variable inside the master.blade.php file, but not inside the content blade file (variable undefined).
For example, for the contact page:
CONTROLLER FUNCTION:
$this->data['page'] = "contact";
$this->layout->content = View::make('pages.contact');
$this->layout->with('data', $this->data);
MASTER.BLADE.PHP:
if ($data['page'] == 'contact')
{ //do something, it works }
#yield('content')
CONTACT.BLADE.PHP:
if ($data['page'] == 'contact')
{// do something. ErrorException Undefined variable: data}
Am I missing something or is it a known restriction?
Thanks!
The problem was that I was passing the variables only to the layout:
Instead of:
$this->layout->content = View::make('pages.contact');
$this->layout->with('data', $this->data);
I fixed it using:
$this->layout->content = View::make('pages.contact', array('data' => $this->data));
$this->layout->with('data', $this->data);
This way passing the variables to the layout, but also to that particular view.
Hope it helps someone.
I have a project which is using laravel4 and its blade view engine. Occasionally I have had the need to call controller methods via a view file to output dynamic data; incidentally this time its a call to a method that generates javascript code for the page. Regardless of whether this is the best way to go about things is a moot point atm as I am simply upgrading from L3 to L4.
My View is similar to:
#extends('en/frontend/layouts/default')
{{-- Page title --}}
#section('title')
Page Title
#parent
#stop
{{-- Page content --}}
#section('pageContent')
...
#stop
{{-- Scripts --}}
#section('scripts')
<?php echo CaseStudy::script(); ?>
#stop
I have set up CaseStudy to load via the laravel facades and the class at current is simply:
class CaseStudy
{
public function display()
{
}
/**
* Returns the javascript needed to produce the case study
* interactivity
*
* #return \Illuminate\View\View|void
*/
public function script()
{
$language = \Config::get('app.locale');
$scriptElementView = $language . '.frontend.elements.casestudy_script';
if ( ! \View::exists($scriptElementView))
{
$scriptElementView = "Training::" . $scriptElementView;
}
return \View::make($scriptElementView, array());
}
}
It would appear that echoing the response of CaseStudy::script is what is causing the blank body; however with no further error message I do not know what is going on. I assume that this is because my static CaseStudy's instance of View is conflicting with the instance being used by the blade engine. How would I go about having CaseStudy::script() returning a string form of the rendered view?
Thank you.
In your view
{{-- Scripts --}}
#section('scripts')
{{ CaseStudy::script() }}
#stop
In your library
class CaseStudy
{
public function script()
{
$string = "your script here";
return $string;
}
}
Note - CaseStudy should really be a "library" or "helper" or something. Not a controller - that does not really conform to MVC approach.
i'm trying to learn codeigniter (following a book) but don't understand why the web page comes out empty.
my controller is
class Welcome extends Controller {
function Welcome()
{
parent::Controller();
}
function index()
{
$data['title'] = "Welcome to Claudia's Kids";
$data['navlist'] = $this->MCats->getCategoriesNav();
$data['mainf'] = $this->MProducts->getMainFeature();
$skip = $data['mainf']['id'];
$data['sidef'] = $this->MProducts->getRandomProducts(3, $skip);
$data['main'] = "home";
$this->load->vars($data);
$this->load->view('template');
}
the view is:
<--doctype declaration etc etc.. -->
</head>
<body>
<div id="wrapper">
<div id="header">
<?php $this->load->view('header');?>
</div>
<div id='nav'>
<?php $this->load->view('navigation');?>
</div>
<div id="main">
<?php $this->load->view($main);?>
</div>
<div id="footer">
<?php $this->load->view('footer');?>
</div>
</div>
</body>
</html>
Now I know the model is passing back the right variables, but the page appears completely blank. I would expect at least to see an error, or the basic html structure, but the page is just empty. Moreover, the controller doesn't work even if I modify it as follows:
function index()
{
echo "hello.";
}
What am I doing wrong?
Everything was working until I made some changes to the model - but even if I delete all those new changes, the page is still blank.. i'm really confused!
thanks,
P.
I've isolated the function that gives me problems.
here it is:
function getMainFeature()
{
$data = array();
$this->db->select("id, name, shortdesc, image");
$this->db->where("featured", "true");
$this->db->where("status", "active");
$this->db->orderby("rand()");
$this->db->limit(1);
$Q = $this->db->get("products");
if ($Q->num_rows() > 0)
{
foreach($Q->result_arry() as $row)
{
$data = array(
"id" => $row['id'],
"name" => $row['name'],
"shortdesc" => $row['shortdesc'],
"image" => $row['image']
);
}
}
$Q->free_result();
return $data;
}
I'm quite convinced there must be a syntax error somewhere - but still don't understand why it doesn't show any error, even if I've set up error_reporting E_ALL in the index function..
First port of call is to run php -l on the command line against your controller and all the models you changed and then reverted.
% php -l somefile.php
It's likely that there is a parse error in one of the files, and you have Display Errors set to Off in your php.ini. You should set Display Errors on for development and off for production, in case you haven't already.
(Edit: in the example above you have missed off the closing } of the class. It might be that.)
Make sure error_reporting in index.php is set to E_ALL and post your code for the model in question.
After looking through your function I suspect it's caused by $this->db->orderby("rand()");
For active record this should be $this->db->order_by('id', 'random');
Note that orderby is deprecated, you can still use it for now but the new function name is order_by
Not sure, but it can be also caused by php's "display_errors" is set to false.
You can change it in your php.ini file.