How does Laravel's "withVariableName" works? - php

Looking at Laravel code I found they are passing variable from 'routes' to 'views' using the following method:
$arraysan = ['mike','robert','john']; **//Variable to be passed**
return view('home')->withArraysan($arraysan); **//Variable passed with** name "withArraysan"
In that above syntax they call a function named withArraysan which doesn't exist.
Can somebody explain how its been handled in Laravel?

For a while now, PHP has had the concept of magic methods - these are special methods that can be added to a class to intercept method calls that do not exist.
It appears that Laravel Views implement __call - this then intercepts a call to an undefined method on the object, and is passed both the name of the method being called as well as the arguments. In this way, the View object can then see that the withArraysan call began with and call the concrete method with, passing the second part Arraysan as the first argument, and the argument to withArraysan as the second part.

If I've got your question then in Laravel they had a class View using magic method __call to handle the above function and the code for that function is like as follows
public function __call($method, $parameters)
{
if (Str::startsWith($method, 'with')) {
return $this->with(Str::snake(substr($method, 4)), $parameters[0]);
}
throw new BadMethodCallException("Method [$method] does not exist on view.");
}
And you can find this within
your_project_folder/vendor/laravel/framework/src/Illuminate/View/View.php

$arraysan = ['mike', 'robert', 'john']; // Variable to be passed
return view('home')->with('AnyVariable', $arraysan);
Try this! This will work.
Also check in home.blade.php,
<?php
print_r($AnyVariable);die;
?>

Related

Laravel app::call('SomeController#method') not working

I want to be able to call a method inside a controller in the following manner:
App::call('SomeController#method');
I figured it happens like this when defining a route:
Route::get('/route', 'SomeController#method');
So maybe there's an underlying mechanism I can use more generally in my code on other places in the project, turns out there is (App::call()).
The problem I'm running into is that this generates an error:
ReflectionException (-1)
Class SomeController does not exist
## \vendor\laravel\framework\src\Illuminate\Container\Container.php
public function build($concrete)
{
// If the concrete type is actually a Closure, we will just execute it and
// hand back the results of the functions, which allows functions to be
// used as resolvers for more fine-tuned resolution of these objects.
if ($concrete instanceof Closure) {
return $concrete($this, $this->getLastParameterOverride());
}
$reflector = new ReflectionClass($concrete);
// If the type is not instantiable, the developer is attempting to resolve
// an abstract type such as an Interface of Abstract Class and there is
// no binding registered for the abstractions so we need to bail out.
if (! $reflector->isInstantiable()) {
return $this->notInstantiable($concrete);
}
$this->buildStack[] = $concrete;
$constructor = $reflector->getConstructor();
I'm pretty sure I must include some stuff somewhere but since Laravel is pretty big I'm asking this community.
Try giving the full namespace like:
App::call('App\Http\Controllers\SomeController#method');
Another way is:
app()->call(['\App\Http\Controllers\SomeController', 'index']);
where index is the name of the method. You can add a second parameter to send some data like so:
app()->call(['\App\Http\Controllers\SomeController', 'index'], [
'name' => 'Strawberry'
]);
You can call the method by using the app() helper. Syntax is app($fullControllerClassName)->methodYouWantToCall():
app('App\Http\Controllers\SomeController')->method();

PHP - Static methods in call_user_func_array()

I have a MVC Project and I have used call_user_func_array function to pass the arguments to the specific method in the controller, but the main problem here is that the method must be static, and someTimes I do really need to use $this inside that static method which is the method of the controller :/
Here's that message which explain everything: Deprecated: Non-static method home::index() should not be called statically in [Location..]
My Question here is: is there any other way to solve that problem and work with the regular methods .. !-- Maybe other function instead of the call_user_func_array or anything else :)) -> Thanks!
You can all methods non-statically via an array as shown in the example in the manual for call_user_func_array:
<?php
$parameters = ['one', 'two'];
$class = new className;
call_user_func_array([$class, 'method'], $parameters);
class className
{
public function method($one, $two)
....

With in Laravel and Validate double -> operator

I'm newbye of OOP and Laravel , but i have noticed that the operator with in laravel is used for a lot of things: for example i have found this part of code in the documentation:
return Redirect::to('register')->withErrors($validator);
withErrors? I know that with is used to pass multiple element to a view: is there more that i need to know about this operator?
Another Question: the validate class in php have this type of operator:
$validator->required('You must supply an email address.')->email('You must supply a valid email address')->validate('email', 'Email');
why i can use multiple "->" for a instance of the class validator? I know that in this way:
$object = new object();
$object->something(); //metod or attribute
but i know that it's impossible use the operator "-" for indicate multiple method/attribute for a class(even if it is a library).
thank you for all and i'm sorry for,maybe,the stupid question! Thank you!
Well Redirect::to() returns an instance of Illuminate\Http\RedirectResponse. This class has a method withErrors which is called in the example.
However this with* method is a bit different than the one to pass data to a view. withErrors flashes the data to the session so it is available for the next request (after the redirect happens)
Regarding your second question, this: $validator->required()->email() is called method chaining. It is used a lot (not only in Laravel) to achieve a nice and brief syntax.
What happens is that the methods return $this so you can call the next method on the same object right away.
Let's look at another example:
$result = User::where('active', true)->where('name', 'like', 'a%')->get();
If we now take a look at the where() method in Illuminate\Database\Eloquent\Builder you can see that after the where logic happens it returns $this so we can continue calling methods.
public function where($column, $operator = null, $value = null, $boolean = 'and')
{
// code omitted for brevity
return $this;
}
Many Laravel classes implement this so-called Fluent Interface that allows method chaining for nearly every function call. Only methods that have an obvious return value can't be chained. Like retrieving a result with get(). Of course it has to return the result and it can't return $this as well.
You seem to understand the purpose of with() just fine.
As for your second question, you can "chain" object methods if the methods each return the object like this:
<?php
class MyClass {
public function myMethod()
{
// do stuff
return $this;
}

Why I'm getting 'Non-static method should not be called statically' when invoking a method in a Eloquent model?

Im trying to load my model in my controller and tried this:
return Post::getAll();
got the error Non-static method Post::getAll() should not be called statically, assuming $this from incompatible context
The function in the model looks like this:
public function getAll()
{
return $posts = $this->all()->take(2)->get();
}
What's the correct way to load the model in a controller and then return it's contents?
You defined your method as non-static and you are trying to invoke it as static. That said...
1.if you want to invoke a static method, you should use the :: and define your method as static.
// Defining a static method in a Foo class.
public static function getAll() { /* code */ }
// Invoking that static method
Foo::getAll();
2.otherwise, if you want to invoke an instance method you should instance your class, use ->.
// Defining a non-static method in a Foo class.
public function getAll() { /* code */ }
// Invoking that non-static method.
$foo = new Foo();
$foo->getAll();
Note: In Laravel, almost all Eloquent methods return an instance of your model, allowing you to chain methods as shown below:
$foos = Foo::all()->take(10)->get();
In that code we are statically calling the all method via Facade. After that, all other methods are being called as instance methods.
Why not try adding Scope? Scope is a very good feature of Eloquent.
class User extends Eloquent {
public function scopePopular($query)
{
return $query->where('votes', '>', 100);
}
public function scopeWomen($query)
{
return $query->whereGender('W');
}
}
$users = User::popular()->women()->orderBy('created_at')->get();
Eloquent #scopes in Laravel Docs
TL;DR. You can get around this by expressing your queries as MyModel::query()->find(10); instead of MyModel::find(10);.
To the best of my knowledge, starting PhpStorm 2017.2 code inspection fails for methods such as MyModel::where(), MyModel::find(), etc (check this thread), and this could get quite annoying.
One (elegant) way to get around this is to explicitly call ::query() wherever it makes sense to. This will let you benefit from free auto-completion and a nice formatting/indentating for your queries.
Examples
BAD
Snippet where inspection complains about static method calls
// static call complaint
$myModel = MyModel::find(10);
// another poorly formatted query with code inspection complaints
$myFilteredModels = MyModel::where('is_foo', true)
->where('is_bar', false)
->get();
GOOD
Well formatted code with no complaints
// no complaint
$myModel = MyModel::query()->find(10);
// a nicely formatted and indented query with no complaints
$myFilteredModels = MyModel::query()
->where('is_foo', true)
->where('is_bar', false)
->get();
Just in case this helps someone, I was getting this error because I completely missed the stated fact that the scope prefix must not be used when calling a local scope. So if you defined a local scope in your model like this:
public function scopeRecentFirst($query)
{
return $query->orderBy('updated_at', 'desc');
}
You should call it like:
$CurrentUsers = \App\Models\Users::recentFirst()->get();
Note that the prefix scope is not present in the call.
Solution to the original question
You called a non-static method statically. To make a public function static in the model, would look like this:
public static function {
}
In General:
Post::get()
In this particular instance:
Post::take(2)->get()
One thing to be careful of, when defining relationships and scope, that I had an issue with that caused a 'non-static method should not be called statically' error is when they are named the same, for example:
public function category(){
return $this->belongsTo('App\Category');
}
public function scopeCategory(){
return $query->where('category', 1);
}
When I do the following, I get the non-static error:
Event::category()->get();
The issue, is that Laravel is using my relationship method called category, rather than my category scope (scopeCategory). This can be resolved by renaming the scope or the relationship. I chose to rename the relationship:
public function cat(){
return $this->belongsTo('App\Category', 'category_id');
}
Please observe that I defined the foreign key (category_id) because otherwise Laravel would have looked for cat_id instead, and it wouldn't have found it, as I had defined it as category_id in the database.
You can give like this
public static function getAll()
{
return $posts = $this->all()->take(2)->get();
}
And when you call statically inside your controller function also..
I've literally just arrived at the answer in my case.
I'm creating a system that has implemented a create method, so I was getting this actual error because I was accessing the overridden version not the one from Eloquent.
Hope that help?
Check if you do not have declared the method getAll() in the model. That causes the controller to think that you are calling a non-static method.
For use the syntax like return Post::getAll(); you should have a magic function __callStatic in your class where handle all static calls:
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters);
}

Codeigniter routing behavior with the controllers magic method __call

The segments in a URI normally follow this pattern in Codeigniter:
XYZ.com/Class/Method/param1/param2
This works as expected when the called method is defined in the controller, but nothing works if I supply the URI with some undefined method to invoke the __call magic method that takes care of any undefined method.
__call is only invoked if its called from within the controller itself, not when I call some undefined method from the URI
Any explanation?
Thanks
In CodeIgniter, there is _remap. So if you go to
XYZ.com/Class/UndefinedMethod/param1/param2
then _remap will be called (actually _remap will always be called, so we need to make sure that methods that do exist are called correctly).
function _remap($method, $params=array()){
$funcs = get_class_methods($this);
if(in_array($method, $funcs)){ // We are trying to go to a method in this class
return call_user_func_array(array($this, $method), $params);
}
// else do something else
}
Look in the server (Apache?) log file. Undoubtedly you will see PHP errors which caused processing to abort. Unless you cover undefined functions by remapping them to an error page, random URLs will cause "nothing" to seem to happen.

Categories