I've been testing out the Imagine Library in my Laravel application and have been running the code straight in the Routes file which has worked fine. However, now when I'm trying to use it in a Model or Controller, it can't seem to find the library anymore even though I've included it the same way I did before with use Imagine\Image\Box; and use Imagine\Gd;. The code is also exactly the same as in the Routes file but I still get class 'App\Imagine\Gd\Imagine' not found.
Do I have to do something different when including stuff in a Model or controller?
Related
Please point out any naivete or incorrect assumptions I'm making about Laravel, Composer, PHPUnit, etc.
I had a class called SpeechToTextHelper that was inside a Laravel project, and it used facades like this:
use Cache;
use Log;
use Storage;
Then, since I wanted to share it between multiple Laravel projects, I moved it into a separate repo and required it (into the first project) as a dependency via Composer.
The code all seems to run fine.
My question is different from Using Laravel Facades outside Laravel
What I want to know is:
Now that I also want to write PHPUnit tests for SpeechToTextHelper in my new tools repo, I see errors like RuntimeException: A facade root has not been set. and Error: Class 'Log' not found, presumably because this tools repo has no awareness of Laravel. I guess this means my production code has been working just by side-effect.
In my new tools repo (where my SpeechToTextHelper now is), how am I supposed to indicate (maybe somewhere in composer.json?) that the code will only work if Laravel's facades exist and are initiated properly?
How can I fix my separate repo's code so that its tests can run and also so that it ensures that it can only be "required" by a Laravel project?
P.S. https://laravel.com/docs/5.7/facades says "When building a third-party package that interacts with Laravel, it's better to inject Laravel contracts (https://laravel.com/docs/5.7/contracts) [which live in their own GitHub repository] instead of using facades." "If you are building a package, you should strongly consider using contracts since they will be easier to test in a package context."
But I do not see contracts for Log or Storage at all.
I think you are looking for Laravel component repositories
Cache - This component shows how to use Laravel's Cache features in non-Laravel applications.
Log - This component shows how to use Laravel's Log features in non-Laravel applications.
This video shows, how you can use eloquent outside laravel, I think that will give you better idea.
I'm not positive that this is the best approach, so I'd love if others
would provide better answers.
For production code
My composer.json still has this in the "require" section: "laravel/framework": "5.7.*",.
I plan to only ever require this tools library from within a Laravel app. I'm not sure that this is the right way to make that a rule, but my production code at least seems to be working.
For tests
As for tests, what seems to have been necessary was to add these files from https://github.com/laravel/laravel/tree/2a1f3761e89df690190e9f50a6b4ac5ebb8b35a3:
app/Console/Kernel.php
app/Providers/AppServiceProvider.php
app/Providers/AuthServiceProvider.php
app/Providers/EventServiceProvider.php
app/Providers/RouteServiceProvider.php
bootstrap/cache/.gitignore
bootstrap/app.php
bootstrap/autoload.php
config/app.php
config/database.php
config/logging.php
config/view.php
storage/logs/laravel.log
tests/CreatesApplication.php
tests/TestCase.php
Perhaps those are the minimum set of barebones Laravel files without which tests can't run.
Then I made sure that each test class extended tests/TestCase.php. And I adjusted the namespaces.
I have a Codeigniter framework setup that I move cross multiple domain setups as a default starting point. However when I was going to apply it for the first time to a one.com domain I got an error.
An Error Was Encountered
Unable to load the requested class: Form
So far I have tried with checking the source for this. I went into the autoload.php and first tried to change from "form" to "Form" as I found out on another site because of Linux being sensitive to capital letters, but to no use.
I then removed the form all together and then I got the same error, but from the helper "url". I removed that and it went up to libraries and started printing same error for the first in that array.
$autoload['libraries'] = array('Database', 'Session', 'User_agent', 'Upload');
$autoload['drivers'] = array('Form', 'Url');
If there is anything more I can add to shine light on this or make the question better please tell me and I will add it. I am not sure at all where the fault might lie so therefore the information is a bit pale.
You are trying to load a CI helper as a driver ! So the framework looks for a driver Form.php file, which doesn't exist (not in the standard CI installation).
| These classes are located in system/libraries/ or in your
| application/libraries/ directory, but are also placed inside their
| own subdirectory and they extend the CI_Driver_Library class
What you want to do is to load the "form" helper (and the others). A helper is loaded like: $this->load->helper('form'); or autoloaded.
CI - helper
CI - autoload
CI - driver
I'm starting a new project and I want to reuse some parts of it, mainly the stuff related to user registration and authentication. I can copy and paste all of the code but I want to use again. I know there is Package Development in Laravel but it's not easy and feel like there must be a better way.
Some days ago I find a pingpong/modules but I don't know about it. It's third party plugin and don't trust it.
Use this plugin is true? Is this plugin is updated later? What's different between Embedd Package Laravel and pingpong/modules? or Do you have any suggestion?
Pingpong modules seems to be build for the earlier version of Laravel 5 and in how far they are compatible with future versions (and maybe current 5.1.11) I cannot say.
There isn't much activity going look the commit history for 2.1, as of today(18 dec) the last commit was over 6 months ago.
But is the package specifically designed for Laravel? It seems to. They offer a bunch of features which are useful for development. The only unfortunate thing is you get a LOT of code within your own git environment (is it a good thing? I don't know, what do you prefer).
Personally I don't like it in this way for development, I prefer them in the vendor/ folder else it's a pain to update it to newer a version.
Since Laravel 5 Taylor wanted to make package development not too specific anymore, like in Laravel 4. The only thing what you can do (but not have to) to make your package using Laravel is using the ServiceProvider's. The ServiceProvider is the bootstrap into the Laravel application.
If you want to extend or implement your own functionality, fork the repo and build it yourself on top off it and host it (through github/packagist or a private repo using Satis).
Pingpong modules (2.1) is build for Laravel 5 and they you described (Embedded Laravel Package) is more for Laravel 4, because the more specific way you have to write the package.
But, there is alternative?
Whenever you want a more active project/package for development you should tryout Asgard CMS. They are pretty modular and I thought I read somewhere it was inspired by this package (totally not sure).
How about building yourself?
Of course you can build your own packages to achieve the same result. And create it as modular as you want. I created a lot modules for my company and we can create pretty easy a entire system and using and extending/overriding modules. Even small parts from a module can be overwritten to project specific needs.
We have chosen for almost the same structure as the app/ folder which Laravel projects, in case of CMS/API modules.
A packages look like:
tests/
src/
Acme/
Controllers/
Requests/
Models/
Module.php // contains some specifc calculations for example
ModelServiceProvider.php
composer.json
In the composer.json file we autoload: "Module\\": "src/"
And in the config/app.php we register the ModuleServiceProvider. Now we injected the functionality into Laravel's container and can we use it through the app() instance.
But whenever we only want to use the Models with in another project or standalone, we can still use it because the autoloaded features from composer and the way we build the package. Possible to use:
<?php
require_once __DIR__ .'/vendor/autoload.php';
use Module\Models\Module;
$module = new Module;
Edit
The package structure we like to use, to have a section for API or CMS stuff:
tests/
src/
Cms/
Controllers/
Requests/
Api/
Controllers/
Transformers/
Models/
Module.php // contains some specifc calculations for example
Providers/
CmsServiceProvider.php // includes `ModuleServiceProvider`
ApiServiceProvider.php // includes `ModuleServiceProvider`
ModuleServiceProvider.php // contains global stuff like commands etc.
composer.json
and instead of registering ModuleServiceProvider in config/app.php we register the ApiServiceProvider or CmsServiceProvider depending on the wishes of the client/project.
To reuse your classes simply use php namespaces or use to call back your clases.
Using the namespace
namespace Acme\Tools;
class Foo
{
echo "me";
}
You can the call class foo
<?php
$foo = new \Acme\Tools\Foo();
Using Use.
You can also use use Statement as below :
<?php
use \Acme\Tools\Foo;
$foo = new Foo();
Use Middleware
You should also use middleware to filter who should use the scripts ie the Auth middle-ware , which will help you in filtering users , registrations , logins READ MORE http://laravel.com/docs/5.1/middleware
Use Eloquent
Use ORM to create REST apis to your models , its very simple , always let your controller class extend eloquent use Illuminate\Database\Eloquent\Model; ie as :
use Illuminate\Database\Eloquent\Model; .Read More http://laravel.com/docs/5.1/eloquent
Lastly Use Laravel In built Helper functions
There are numerous Laravel In built Helper functions , to use simply go over the documentation to help you
I've used pingpong modules. It a pretty cool package. I'm not sure if it's updated much. But it's a very simple package. The only thing it does is create a folder with almost the same structure as in the app folder + views. But these are modules. You can reuse it if you program them right. The same goes for the other answer from jimmy if you have a good structure you can reuse anything.
EDIT
In the image below you'll see an example of pingpong modules. As you it's pretty much the same structure as the app folder. Maybe more the root folder. Normally it runs start.php and you have a routes.php file int he Http folder. I customized mine a bit. And load the frontend and backend routes within the RouteServiceProvider. This is build with laravel 5.1.
I have an iPhone application which perform calls to an API developed with codeigniter. Since I am new to the framework, I want to know where such API are normally located ? The url requested from the iPhone application to the API is the following:
http://example.com/site/welcome/admin/api/processingdocuments/
I got a look on the application/libraries folder and there is a bench of php files like rest.php and REST_Controller.php. Are these the files I am looking for? Since the URL above doesn't point to specific file, how to know which API is being called? Thank you in advance.
When using Phil Sturgeon's CodeIgniter Restserver (which is what it seems you are using), you set up a controller within application/controllers directory and extend his class.
Let's say you call your controller Foobar, and it looks like this:
class Foobar extends Rest_Controller {
//... your methods here
}
In this case, you will access this endpoint at http://example.com/foobar
The URL references your controllers, and not the Rest_Controller directly.
URLs look like this:
http://example.com/{controller}/{method}/{param1}/{param2}/.../{paramN}
If method is not specified, it defaults to index()
Further, the Restserver allows you to map methods to HTTP request methods. Such that
GET example.com/foobar will map to the method index_get()
POST example.com/foobar will map to the method index_post()
..and so on.
I highly recommend you read the documentation
In your example, you would expect the controller that is being called to be located at application/controllers/site.
However, this might have been modified using htaccess rewrite rules (check for a .htaccess file), or via redefined CI routes (check application/config/routes.php).
If all else fails:
Under default configurations, that is where you should find them, however, CI is very malleable with routes and it is hard to say where they might be. Your best bet would be to grep the directory for the words extends Rest_Controller since wherever the controllers are, they would be extending that class.
I currently test my CodeIgniter app with phpunit by using CIUnit (https://bitbucket.org/kenjis/my-ciunit). The problem is that I have multiple controllers with the same name. I have a controller in the root controller directory named "Blog" and I have a controller called "Blog" in the controller/ajax/ directory.
The reason is to seperate all ajax requests from the main controller.
When I am running tests on both files, I get the following error:
PHP Fatal error: Cannot redeclare class Blog in ...
Well, I am not suprised I am getting this error.
What are my options to resolve this?
Prefix controllers in ajax directory with "ajax" (looks only a bit stupid url/ajax/ajax_blog)
Use namespaces (I guess I need to namespace codeigniter too then)
Create 3 seperate phpunit.xml files
This aren't really solutions I am looking for. Do I have any other options? Is it somehow possible to run each testsuite seperatly, but still in one command? Can I "clean" objects between testsuites? Anything else?
There are no other options except those you mentioned, as it is impossible to "unload" class definitions in PHP.
Naming two controllers the same is not a problem when you run CI normally, since only one controller is instantiated per request, but something that should be avoided.
If it is just the ajax-url you don't like, maybe override it in a route (in config/routes.php):
$routes['ajax/blog'] = 'ajax/ajax_blog';