I started studying Laravel and ran into a problem using models. How to load them? For example in CodeIgniter i used it like $model = $this->load->model('some_model'). In Laravel when i call it from controller like Sites::OfUser() it work fine, but when i call Sites::getId() it says that method should be static...
Is it possible to call method without static or i need to create facades for each model?
My model looks like this:
namespace Models;
use Eloquent;
class Sites extends Eloquent {
public function scopeOfUser($query)
{}
public function getId($name)
{}
}
For static method--
$type = Sites ::scopeOfUser($query);
and if you want normal like codeingiter then use--
$model = new Sites ();
$type = $model->scopeOfUser($query);
You can of course make a static method in the model, and do some static work in it (get ID for name or whatever).
That's no problem.
However, you must declare it static if you want to use the ::, which you are doing not.
public static /* <-- this */ function getId($name)
{
// Do work
// return $result;
}
If you want to access a method with ::, you will need to make it a static method or create a Facade.
The reason why Sites::OfUser() is "working" is because you have prefixed that method with scope.
Scopes allow you to easily re-use query logic in your models. To
define a scope, simply prefix a model method with scope.
If you want to use Facades you can follow my answer here on how to create a Facade.
Related
I'm currently trying to use Laravel Relationships to access my achievements Model using User model, I use this relationship code:
public function achievements()
{
return $this->hasMany('App\Models\User\Achievement');
}
I can easily make some eloquent queries, however I can't access any method that I created there, I can't access this method:
class Achievement extends Model
{
public function achievementsAvailableToClaim(): int
{
// Not an eloquent query
}
}
Using the following code:
Auth::user()->achievements()->achievementsAvailableToClaim();
I believe that I am using this Laravel function in the wrong way, because of that I tried something else without using relationship:
public function achievements()
{
return new \App\Models\User\Achievement;
}
But that would have a performance problem, because would I be creating a new class instance every time I use the achievements function inside user model?
What would be the right way of what I'm trying to do?
it's not working because your eloquent relationship is a hasMany so it return a collection. you can not call the related model function from a collection.
you can var dump it on tinker to understand more what i mean.
You can use laravel scopes.Like local scopes allow you to define common sets of constraints that you may easily re-use throughout your application.
In your case you use this like, Define scope in model:
public function scopeAchievementsAvailableToClaim()
{
return $query->where('achivement_avilable', true);
}
And you can use this like :
Auth::user()->achievements()->achievementsAvailableToClaim();
In Laravel Models use functions that are static and the documentation uses static functions to show how Models work. If I create a new Model for my application, it extends the base Model class but why is Laravel using static functions? I thought the idea is static anything is bad? For example, it makes testing harder?
I'm just confused as most things can be retrieved from the DI container? For example, a Model called Flight, why is it not used like this inside a controller:
namespace App\Http\Controllers;
use App\Flight;
class FlightController
{
public __construct(Flight $flight)
{
$this->flight = $flight; // etc.
}
}
And Models are not even using a Facade either? When I create my own models am I suppose to always use static functions as well?
I'm not sure I understand your question correctly, but I think you are mistaking Facades for static methods. Read this https://laravel.com/docs/7.x/facades#how-facades-work, Laravel uses the magic method _callStatic() to resolve to actual instances. So it looks static, but it isn't.
I have a controller with the "getUsers" function in a controller called "UserController" , and inside it I want to call a function of the "CarController" controller called "getCars", the two options I have are:
a) Make the second call as "static" , then I can call it without instantiating the class
b) Do not do that function of the static class and I call it in this way
$ car_id = 100;
$ userController = new UserController ();
$ userController-> getCars ($ car_id);
I do not know which is the best practice, or what pros or cons has one or another.
I'm using laravel.
Thanxs.
It is a bad practice to call a controller from another controller, this usually signals that you have badly designed your code and you should think of a different way to achieve what you want.
None the less, you can do it like this:
app()->call('App\Http\Controllers\CarController#getCars');
If your controller method has parameters you can pass them as the second argument:
app()->call('App\Http\Controllers\CarController#getCars', [$param1, $param2]);
To answer your question, you should not call one controller method from another. As #elfu mentioned, this is not the intended functionality of a controller anyway. His post is correct and in your case you should probably use the User model as the location of this method, but I thought I'd at to it a little.
If you do want to share methods between multiple controllers, a good place to do this is through a Trait. In some cases, you are not referencing a model that is shared between controllers, and a Trait would be your best option.
To include a trait, you can reference it by including it at the top of your controller and then with a 'use' statement after the class declaration for the controller. Here is an example:
use App\Traits\ExampleTrait;
class CarController extends Controller
{
use ExampleTrait;
...
You would do the same in the UserController. Then, any method that you place in the ExampleTrait will be directly accessible from the CarController and the UserController by referencing it as $this->methodName(), just like referencing any other method in the same controller.
In your particular case, I would say that your logic should probably be stored in the User model, since the cars for a user are really an ATTRIBUTE of the User model, but the above gives you another option to work with.
In my humble opinion you should not call another controller in a controller.
It looks like you have some business logic in that controller. So you should move your logic to the entity (User.php) and call it in both controllers methods.
A regular controller returns a view (at least that is what is expected), so if you want to call another controller you should just send that route to that method (in web.php file) instead of calling it in another controller.
Hope that helps you.
You can call one controller function from another but the best way is to create a trait and use it both the controllers like:
trait Common
{
public function method(){}
}
class FirstController extends Controller
{
use Common;
}
class SecondController extends Controller
{
use Common;
}
If you want to bind parameters to the call, you can use:
$videos = app()->call('App\Http\Controllers\StorageController#returnViewVideo',[
'course'=>$course,
'lesson'=>$lesson,
]);
The following code worked for me well. and also it also can be used in routes.php
public function mobileImageUpload(Request $request){
$this->validate($request,[
'data'=>'required',
'filetype'=>'required',
'userid'=>'required',
]);
$namespace = 'App\Http\Controllers';
$controller = app()->make($namespace.'\ImageController');
return $controller->callAction('mobileImageUpload',[$request]);
}
I was just wondering if there is a way to use codeigniter model in other non Codeigniter classes... Let me give you an example.
I have this MyTestClassTests class which extends PHPUNIT_Framework_testCase
<?php
require_once '../../vendor/autoload.php';
use Facebook\WebDriver\Remote\WebDriverCapabilityType;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\Interactions\WebDriverActions;
use Sunra\PhpSimple\HtmlDomParser;
class MyTestClassTests extends PHPUnit_Framework_TestCase
{
public function testDoSomething()
{
// Do some test
// get results
// Store results via Codeigniter Model, if possible?
$results = 'some results';
$this->load->model('results');
$this->results->import($results);
}
}
Now once test is finished i would like to store test results in to the database. Is there a way to call/initialize CodeIgniter model in current class to use it and store data? This file is located in the Codeigniters controllers folder.
If you need any additional information's please let me know and i will provide. Thank you!
Since you appear to be unit testing you should consider using ci_phpunit-test which makes it much easier to use PHPUnit with CodeIgniter 3.x.
Because you're unit testing the following may not apply. These examples only work within an fully instantiated CI framework. Within that context there are a couple ways to give a stand-alone class access to the CI object.
One approach is to capture the CI instance in a class property.
class MyTestClassTests extends PHPUnit_Framework_TestCase
{
protected $CI;
public function __construct()
{
// Assign the CodeIgniter super-object
$this->CI = & get_instance();
}
public function testDoSomething()
{
// Do some test
// get results
// Store results via Codeigniter Model, if possible?
$results = 'some results';
//use the class property to access CI classes and methods
$this->CI->load->model('results');
$this->CI->results->import($results);
}
}
A second approach uses the PHP magic method __get. The advantage is it's much easier to write the code. The disadvantage is it's a tiny bit less efficient because extra code is executed each time you access the CI instance.
class MyTestClassTests extends PHPUnit_Framework_TestCase
{
/**
* Enables the use of CI super-global without having to define an extra variable.
*
* #param $var The CI property or method to access
* #return mixed
*/
public function __get($var)
{
return get_instance()->$var;
}
public function testDoSomething()
{
// Do some test
// get results
// Store results via Codeigniter Model, if possible?
$results = 'some results';
//you get to write code as if you were part of the CI object.
//IOW, you write code normally
$this->load->model('results');
$this->results->import($results);
}
}
In order to use codeigniter model in your non codeigniter class you have to instantiate CI first.
In your case below code will work.
$CI = & get_instance()
$CI->load->model('results');
$CI->results->your_function();
First please be gentle i am a beginner and im only coding for practise.
I try to pass an instance to the model but i always get this error
Argument 1 passed to Store::__construct() must be an instance of Illuminate\Filesystem\Filesystem, none given
my model
<?php
use Illuminate\Filesystem\Filesystem as File;
class Store extends Eloquent
{
public $timestamps = false;
public function __construct(File $file)
{
$this->file = $file;
}
}
Could please somebody tell me what i am doing wrong?
thank you
EDIT
I just used simply like this in my Controller
public function index()
{
$store = new Store;
return View::make('store', $store);
}
The File class is one of Laravels Facades, which means you do not need to pass it into your models construct.
You can access it from anywhere in Laravel using File::someMethod(). If you use namespaces then you have to access via the root namespace \File::someMethod().
Within your store view you can access the File facade directly with the aforementioned method.
Take a look at the documentation on the file system here http://laravel.com/api/class-Illuminate.Filesystem.Filesystem.html
So you can use File::copy() without having to instantiate a class as it is called from a static method.