I'm not able to inject these variables through Laravel:
//...class AllowedUsername implements Rule...
public function __construct(Router $router, Filesystem $files, Repository $config)
{
$this->router = $router;
$this->files = $files;
$this->config = $config;
}
I get the error:
Type error: Too few arguments to function ... 0 passed in.
Why is Laravel not doing it automatically?
$request->validate([
'username' => ['required', new AllowedUsername],
]);
In order to leverage Laravel's injection magic you need to use Laravel's API which essentially is:
resolve($class) which is wrapper around app($class)
app($class, $params = []) which is wrapper around:
Note: I've changed $abstract for $class
if (is_null($class)) {
return Container::getInstance();
}
return Container::getInstance()->make($class, $parameters);
Classes that you want to resolve out of container (as seen in your code sample):
public function __construct(Router $router, Filesystem $files, Repository $config)
can be resolved only because Laravel maintainers already defined binding for Router::class, Filesystem:class (example: FilesystemServiceProvider).
Repository::class seems to be simple class that does not require parameters (or require parameters that container already knows how to resolve) while "newing up" - thus Laravel can resolve it without problem.
There is no need to bind classes into the container if they do not depend on any interfaces. The container does not need to be instructed on how to build these objects, since it can automatically resolve these objects using reflection.
Thats why resolve(AllowedUser::class) or resolve(Router::class)... work.
In order to let Laravel know what constructor's parameters should be sent during "newing up" you use bindings mentioned in documentation.
I'm facing strange case. I face an error in production env not while in dev it's working fine.
Development:
Laravel 5.4.28
PHP 7.0.13
MYSQL 5.7.17
Production:
Laravel 5.4.28
PHP 7.2.1
MYSQL 5.7.20
In implementation code. I used:
namespace App;
use Illuminate\Support\Facades\Storage;
use Laravel\Scout\Searchable;
use Illuminate\Database\Eloquent\Model;
class Artwork extends Model
{
use Searchable;
In development it works fine. But in production it gives me this error:
count(): Parameter must be an array or an object that implements Countable
in Builder.php (line 936)
as you can see in this pic:
Any idea what is the reason behind this? and how to fix?
Put this code at the beginning of your route file, it will work fine
if(version_compare(PHP_VERSION, '7.2.0', '>=')) {
error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
}
This is a documented change in PHP 7.2. You need to either update Laravel to 5.6 or downgrade PHP to version 7.1.
Replace
$originalWhereCount = count($query->wheres);
by
$originalWhereCount = count((array)$query->wheres);
in
\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Builder.php
I was facing similar issue in Laravel 5.6. Where I was getting error for object based array. I knew that data in that particular variable will always remain object so i used to convert the object to array. Here is code sample:
$objectData = (array)$objectData;
echo "Total Elements in array are: ".count($objectData);
My server was on PHP 7.1 when I updated to PHP 7.2 I got the same issue.
After searching I found why this occurs. (This occurs because of a PHP update.).
so in my case, the error is solved by typecasting.
I just update all code where I used to count
Before
//this is before
count($adminDetails)
After updated
//after update all i typecast all the code where i used count
count((array)$adminDetails)
Goodluck
This error occurs because you are using a higher PHP version and your Laravel application is on an older PHP version.
✅ Simple solution:
Open: app/Providers/AppServiceProvider.php
And in: public function register() { ... } function add following code:
if(version_compare(PHP_VERSION, '7.2.0', '>=')) {
error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
}
In php 7.2+ count does not work on relation objects, you need to use:
$model->relation()->exists()
Not this (less than php 7.2):
count($model->relation)
i ran into the same problem (PHP 7.2 + Laravel 5.3) but i don't see any "good" answers here. For me, the problem occurs when i tried to start a Builder from a scope method on the model: SomeModel::forUser() calls scopeForUser(). Trying to build a new Query, it trips on a count($this->wheres) that gets no initial value (null). Because the magic static call to the scope starts the builder, no other conditions have been placed in the object so the property is still null at that point.
i thought it's worth sharing my solution first, then perspective on why i consider it better than Ben's answer. It's not personal, i just disagree.
Solution
i took a cue from this answer about overriding some of the core Illuminate\Database classes...
Extend Illuminate\Database\Eloquent\Model
Mine is App\Overrides\Database\Eloquent\Model
Extend Illuminate\Database\Eloquent\Builder
Mine is App\Overrides\Database\Eloquent\Builder
Extend Illuminate\Database\Query\Builder
Can you guess? App\Overrides\Database\Query\Builder
Tell Laravel to use YOUR Eloquent\Model:
config/app.php 'aliases' array, replace the 'Eloquent' value
with your Eloquent\Model FQN
My Model:
namespace App\Overrides\Database\Eloquent;
/*
* Notes:
* * Using replacement Query\Builder with ALIAS
* * Use of Builder in this class is MY Eloquent\Builder
*/
use App\Overrides\Database\Query\Builder as QueryBuilder;
use Illuminate\Database\Eloquent\Model as EloquentModel;
class Model extends EloquentModel
{
public function newEloquentBuilder($query)
{
return new Builder($query);
}
protected function newBaseQueryBuilder()
{
$conn = $this->getConnection();
$grammar = $conn->getQueryGrammar();
return new QueryBuilder($conn, $grammar, $conn->getPostProcessor());
}
}
My Eloquent\Builder:
namespace App\Overrides\Database\Eloquent;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
class Builder extends EloquentBuilder
{
public function __construct($query)
{
parent::__construct($query);
/*
* FIX #1: Set properties treated AS arrays
* to empty arrays on construct.
*/
$this->wheres = [];
// Any other properties treated as arrays should also be initialized.
}
}
My Query\Builder:
namespace App\Overrides\Database\Query;
use Illuminate\Database\Query\Builder as QueryBuilder;
class Builder extends QueryBuilder
{
public function __construct()
{
parent::__construct(...func_get_args());
/*
* FIX #2: Set properties treated AS arrays
* to empty arrays on construct.
*/
$this->wheres = [];
// Any other properties treated as arrays should also be initialized.
}
}
This safely preserves the framework's functionality, since the only actual change you're making is initializing properties that should have been in the first place. Everything else will pass instanceof checks used for dynamic loading and dependency injection.
Opinion
While i agree with #ben-harold about every comment he made saying "NEVER edit vendor code," i disagree with the "solution." It's an oversimplification to a much more complex problem.
Upgrade Laravel: to ensure support for PHP 7.2, jumping up several minor versions - if not major releases - is impractical for a lot of teams. As a long term objective, yes of course. As something i can do to get rid of the bug for my deadline? Nope. Upgrading takes a lot of planning and frequently a lot of rewrites as structures, names, and functionality change. It's something to prioritize, but not a need-it-now answer.
Downgrade PHP: same problem. Downgrading into PHP 5.x means A) PHP is EOL, which may be a deal breaker for a lot of customers who have security policies, and B) any usage of PHP 7.x language features have to be scrapped. As with upgrading the framework this is very likely to cause a lot of headaches. It's also an even less useful solution, since walking backward in the language just puts you farther behind and will require more long-term effort.
place the below line ob code before the class name in your controllers
if (version_compare(PHP_VERSION, '7.2.0', '>=')) {
// Ignores notices and reports all other kinds... and warnings
error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
// error_reporting(E_ALL ^ E_WARNING); // Maybe this is enough
}
I was facing the same issue with an external created table (Not using migration or command),
After creating the model, I just assigned a table name, but the problem was in my model protected $fillable where I assign string instead of array and error occurred.
There is 2 possible solution for that.
Assign an array to your protected $fillable = ['filed1', 'filed2'];
Remove protected $fillable completely (Not Recommended)
class Abc extends Model
{
protected $table = 'cities';
protected $fillable = ['field1','field2', ...];
}
Model looking for countable parameter:
class ClassName extend Model {
protected $fillable=['column_name']; // column in DB of Model is in array
}
Before
count($collection['colors'])
Error:Expected type 'Countable|array'. Found 'string'
After
count((array)$collection['colors'])
It works for me!
'vendor\laravel\framework\src\Illuminate\Database\Eloquent\Builder.php' to:
$originalWhereCount = is_array($query->wheres) ? count($query->wheres) : 0;
I;m using laravel 6.x
for this case you can use this way:
$id = \DB::table('xxxx')->where('id', $id)->count();
I Solve this in Laravel 5.6
// in controller
public function index()
{
$todos = Todo::all();
return view('todos.index')->with(['todos' => $todos]);
}
// in view page
#if(count($todos) > 0)
#foreach($todos as $todo)
<div class="well">
<h3>{{$todo->text}}</h3>
<span class="label label-danger">{{$todo->due}}</span>
</div>
#endforeach
#endif
I installed Mailgun for Laravel. I then tried to run the example
$data = [];
Mailgun::send('emails.welcome', $data, function($message)
{
$message->to('foo#example.com', 'John Smith')->subject('Welcome!');
});
But I got the following error:
"Argument 1 passed to Bogardo\\Mailgun\\Mailgun::__construct() must be an instance of Illuminate\\View\\Environment, instance of Illuminate\\View\\Factory given, called in /Users/koushatalebian/CLG/CL2G/app/vendor/bogardo/mailgun/src/Bogardo/Mailgun/MailgunServiceProvider.php on line 33 and defined"
What is going on?
If you are using Laravel 4.2, Please use Illuminate\View\Factory instead of Illuminate\View\Environment.
Bogardo mail gun package pointing wrong file.
/Users/koushatalebian/CLG/CL2G/app/vendor/bogardo/mailgun/src/Bogardo/Mailgun/MailgunServiceProvider.php
View / Pagination Environment Renamed
If you are directly referencing the Illuminate\View\Environment class or
Illuminate\Pagination\Environment class, update your code to reference Illuminate\View\Factory and
Illuminate\Pagination\Factory instead. These two classes have been renamed to better reflect their
function.
Edit:
You can use the correct class by editing the following file:
vendor/bogardo/mailgun/src/Bogardo/Mailgun/Mailgun.php
in Line 5:
remove use Illuminate\View\Environment; and use use Illuminate\View\Factory;
in line 53:
remove
public function __construct(Environment $views)
{
$this->views = $views;
}
use
public function __construct(Factory $views)
{
$this->views = $views;
}
Hope this will fix.
I am using codeigniter 2.1.3
I am trying to load a model from the library. Initially my code in the construct in the library looks like this
$this->CI=& get_instance(); $this->CI->load->database('default')
Then in one of my library methods
when I tried the line below it doesnt work
$this->load->model('model_name')
but when I tried this
$this->CI->load->model('model_name','',TRUE)
it works, anyone can explain what the instance of CI refers to and the 2 extra parameters when loading the model? Thanks in advance.
A library is not necessarily a part of the way CodeIgniter works.
It could be a homemade library, to solve a task that you want done in your CI application.
This means that if you want to use any of CI's helpers, models or other libraries, you need to do this through the CI instance. This is achieved by doing this:
public function __construct()
{
$this->CI =& get_instance();
}
By assigning the instance to your librarys member named CI, all CI related helpers, models and libraries can be loaded through $this->CI. By trying to do it only with $this you are only referring to the current library - not the CI instance.
To load your model correctly, in your library, $this->CI->load->model('model_name'); is enough. The second parameter allows you to access your model through a different object name. The third parameter is not necessary for loading models, but allows you to autoload the database driver.
If you want to access your model through the same member:
$respone = $this->CI->model_name->method();
I have very simple code that you should use to load model in library
<?php
class Custom_lib
{
private $_CI;
public function __construct()
{
$this->_CI = & get_instance();
$this->_CI->load->model('Dynamic_Model','dm');
}
function currentSession()
{
$session = $this->_CI->dm->fetchSingleData('id,session','session',array('is_active'=>1));
return $session;
}
}
I hope this code will help you
You can tell the model loading function to auto-connect by passing TRUE (boolean) via the third parameter, and connectivity settings, as defined in your database config file will be used:
$this->load->model('Model_name', '', TRUE);
You can more about this at the end of the page of this below link.
http://ellislab.com/codeigniter/user-guide/general/models.html
I want to separate certain functions from controller methods into libraries to make them modular. Based on the URI I'm trying to route to a library method if it exists. But I'd have to load the library to check for the method with the php method_exists function. The only other way I've found to check for it is to put all the library methods in a config array and check for the method name there. Such as:
<?php
/**
* Application_config.php
*/
$config['extensions'] = array(
'News' => array(
'library' => 'articles_library',
'methods' => array(
'articles',
'article',
'edit_article',
'add_article',
'delete_article'
)
)
);
and
<?php
/**
* admin_controller.php
*
* all admin routes go to index
*/
class C3_base_controller extends Controller {
public function index() {
$lib_chk = 0;
$ext = $this->config->item('extensions');
foreach($ext as $item) {
foreach ($item['methods'] as $meth) {
if ($this->uri->segment(2) == $meth) {
$lib = $item['library'];
echo $this->$lib->$meth();
$lib_chk = 1;
}
}
}
if ($lib_chk == 0) {
// rest of controller...
}
}
}
Is there a better way to check for the existence of a library method in each library without loading the libraries? Having to duplicate every method in the application config is just asking for it.
You can use
method_exists
For example, if you are checking for the database object if it's exists
if(method_exists($this->CI->db, 'set')){
// code ...
}
Are you pursuing modularity for reusable code or are you creating an application that has features that may or may not be present...as in plugins?
It's hard for me to imagine your base application having hard-coaded url's that lead to a library that may not exist. Can you test for the library rather than the method? That may be simpler to check a directory and load file names into an array, then see if the library required by a url or uri is in that array.
But if you need to stick to your array of existing method names, could you just regex for the method names by that occur after "function (space)" and followed by parenthesis?