I have created Bundles and they share some Common code. (File Upload Class, Gmailer Class) Now I want to create a separate file within my Bundles or Anywhere, where i can put this common code and then I want to create objects of its classes inside all my bundles.
Here is my folder structure
-src
-College
-StudentBundle
-Controller
-Entity
-OtherApplication
-All3rdPartyClasseshere.php
-UserBundle
-TeacherBundle
Now when I tried to auto load it like this
autoload.php
$loader->registerPrefixes(array(
'Twig_Extensions_' => __DIR__.'/../vendor/twig-extensions/lib',
'Twig_' => __DIR__.'/../vendor/twig/lib',
'Uploader_' => __DIR__.'/../../src/College/StudentBundle/OtherApplications',
But when i try to create an object in my controller it gives an error. I didnt use or include anything inside my controller. How could i create objects of the classes that i separated in another file.
First of all, third-part libraries, even if they are specifically related to your bundle, should not be inside the bundle structure.
The recommended way to handle your non-bundle common code is to treat it as external libraries, and manage them with composer.json.
About the Bundle structure, maybe this question can help you get in the right path.
Related
I would like to use shared resx file to specify all the translatable strings (both for translator convenience, and more importantly to avoid having dozens of separate resx files that clash with DRY principle). I got it working with IStringLocalizer for controllers and views, but I just can't figure out how to implement it for model's data annotations.
It works by using separate files like Models.AccountViewModels.LoginViewModel.en.resx, but how would I go and use shared resource file for data annotations instead of specific ones? Can anyone share example of implementation?
P.S. Environment is .NET Core 1.1 so both validation and display annotations should be in that version available for localization
Step 1: Create a simple class, named ValidationMessages.cs and leave it empty. I will assume that your class is located in /Validation folder.
Step 2: Modify provider for data annotations localizer in your Startup.cs file to be like this:
mvcBuilder.AddDataAnnotationsLocalization(options =>
{
options.DataAnnotationLocalizerProvider = (type, factory) =>
{
return factory.Create(typeof(ValidationMessages));
};
});
Step 3: Create folder /Validation in /Resources (I assume that you are keeping all resource files in that folder) and then add ValidationMessages.fr-FR.resx file there (for French culture i.e.).
Step 4: Add entries to the resource files with keys of your liking. I assume that you will have keys like RequiredError, MaxLengthError, etc.
Step 5: Decorate properties on your model class with [Required(ErrorMessage="RequiredError")].
Next time property validation fails, validation messages will be pulled from ValidationMessages.{culture}.resx files.
Keep in mind though, that not only validation messages will be searched there, but also property names if you use DisplayAttribute.
I have followed this tutorial to create a send email custom action using Java backed Webscript:
http://ecmstuff.blogspot.com/2012/04/adding-document-library-actions-in.html?showComment=1403279845779#c303784066266925848
As has been mentioned above, there is an AbstractWebScript class defined just to execute the action without using a freemaker template, but I get this error:
Cannot locate template processor for template sendDocInEmail.get.html
I guess, there is a problem with the -context.xml file
My files are placed in the following folders:
1. the java .class files are in \tomcat\webapps\alfresco\WEB-INF\classes (placed with the package structure)
2. sendDocInEmail.get.desc in \tomcat\shared\classes\alfresco\extension\templates\webscripts folder (with the package structure)
3. services-context.xml file in the folder \tomcat\webapps\alfresco\WEB-INF\classes\alfresco\module (again with the package structure)
Please help!
Thanks in advance.
You most likely derived your class from DeclarativeWebScript which extends AbstractWebScript and adds the template processing. Make sure to derive your class from the latter.
So i am starting a new project and want to use some of the Symfony Components. I have not used name spaces before with PHP, put i am familiar with the concept from my work in java.
i have this simple piece of code and when i run it i get the error:
PHP Fatal error: Class 'Symfony\Component\CssSelector\XPath\Translator' not found in /home/me/scrapes/Symfony/Component/CssSelector/CssSelector/CssSelector.php on line 52
I am thinking it my lack of knowledge of the name space thing.
/home/me/scrapes/Symfony/Component/CssSelector/CssSelector/XPath/Translator.php does exist.
<?php
set_include_path('/home/me/html/inc');
require 'functions.php';
require 'Symfony/Component/DomCrawler/Crawler/Crawler.php';
require 'Symfony/Component/CssSelector/CssSelector/CssSelector.php';
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\CssSelector\CssSelector;
$crawler = new Crawler();
$crawler->addContent('<html><body><p>Hello World!</p></body></html>');
print $crawler->filter('body > p')->text();
curl_close($ch);
require 'cleanup.php';
?>
thanks for any help
I think this is caused because, if you look in the files you required (for example Symfony/Component/DomCrawler/Crawler/Crawler.php) you'll see that those files use their own use statements (to load other classes).
Namespaces
Let's start with the namespaces. A namespace is used to easily create classes with the same name in different packages. Let's say I have a package called Foo and a package called Bar. Both packages contain a Client class that is used to do some client work (one to call the Google Maps API for example and the other to call the Facebook Graph API). Let's also assume neither of the packages uses namespaces.
If I execute the following code:
<?php
require 'Foo/Client.php';
require 'Bar/Client.php';
This is not going to work, because both packages declare a Client class. Oops, how is PHP going to know which Client class to use if you do this?
<?php
$client = new Client();
It's not going to know which Client to use, so it gives up and throws an error.
If you use namespaces (declared using the namespace keyword in PHP at the top of your file, directly below <?php) you can prevent this from happening. The Foo package can create a Client class in the Foo namespace and the Bar package in the Bar namespace. Now we can
actually use both files and create a client:
<?php
require 'Foo/Client.php'
require 'Bar/Client.php'
$fooClient = new Foo\Client();
$barClient = new Bar\Client();
This will work fine.
I think you might have encountered the Foo_Client notation in older PHP libraries. This is an old way to create namespaces before PHP natively supported them.
"But", I hear you say, "it's quite cumbersome to write Foo\Bar\Baz\Client() every time I want to instantiated a class".
It is, and that's where the use keyword comes in. When using the use keyword, I can tell PHP I want to use a specific client and just use the class name, like so:
<?php
require 'Foo/Bar/Baz/Client.php'
use Foo\Bar\Baz\Client;
$client = new Client();
This will work, if you use the use Foo\Bar\Baz\Client statement, because you tell PHP "Okay, I want to use the Client class from the Foo\Bar\Baz namespace to be used when I use the Client class.
Autoloading
Now, what happens if you use a lot of different classes and you seperated them into several files (which you should do). You get a lot of different require and use statements on the top of a file. That's where autoloading comes in.
There has been a spl_register_autoloader function for quite some time in PHP. This function is used by PHP to find out which files to use when you instantiate a class that is not known because you did not require the file. This function is used both when creating a class, or, and this is the key part when you use a class.
And that's what's happening in your code. You don't have an autoloader registered that can translate the use statements in the files you required to actual class declarations.
Great, how do I fix it?
To fix it, I suggest you read up on the PHP-FIG and PSR-4. These people created standards (which you can follow but are not obliged to). To create easy to use libraries, such as the Symfony component. After you've done that, read up on Composer. After you've done this, you can drop the require statements from your code and use Composer to autoload all the classes you need.
I'm relatively new to Symfony2, so I'm learning by doing. My controller classes are getting pretty big. I'd like to break it up with functions() or objects->method(). Unfortunately I can't figure out where to put the code. (actually its really simple functions... but I can wrap that in an object...)
--I can't add it to the bottom of my DefaultController.php file. It errors out, and not pretty code to boot, either inside or outside of the { }.
--I can't simply add a new NewObject.php file to the controller directory. That errors out. The error: FatalErrorException: ...NewObject not found.
--I've toyed with manual mods to ../app/autoload.php but that doesn't really make sense for a simple class add to my ./SRC/ bundle. Perhaps I should build a ./src/autoload.php file (similiar to ./vender/autoload.php) but the contents of that file don't make sense to me at all. I simply can't figure out how the AnnotationRegistry Loader works.
Am I missing something? This seems way too hard.. what I want is a wrapped up 'include' so I can use the class in dev and after deployment.
How do I include NewObject.php (and the accompanying $newObject->function() ) in my code?
I'm told I can add a service, yet that seems like outrageous overhead for such a seemingly simple task (again, all I'm trying to do is clean up my very long controller php code...)
thanks in advance for your advice.
So you've got a project structure that looks something like this, right?
project
-- app
-- bin
-- src
-- SomeName
-- SomeBundle
-- Controller
-- Entity
-- Resources
-- ...
-- vendor
-- web
And you're just looking to have some kind of "helper" class that's used throughout your bundle. Is that correct?
If so, then you can really put it wherever you want to inside your src/ directory... Just make sure that the class name matches the file name, and that the path to the file matches the namespace you define at the top of your PHP code.
Sometimes when I do this, I'll create a simple directory under my bundle called "Helper/". Other times, when the application is more complex, I might be a little bit more explicit. But here's what the first case would look like...
First, add your /Helper directory under your bundle, and create the class file:
project
-- app
-- bin
-- src
-- SomeName
-- SomeBundle
-- Controller
-- Entity
-- Helper
-- SomeHelper.php
-- Resources
-- ...
-- vendor
-- web
The contents of SomeHelper.php might look like this:
<?php
namespace SomeName\SomeBundle\Helper;
class SomeHelper
{
public function doSomething()
{
...
}
}
Because your namespace matches the file path, it gets autoloaded, so you don't need to worry about include statements. You can instantiate that class anywhere in your bundle, as long as you include a use statement:
<?php
namespace SomeName\SomeBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use SomeName\SomeBundle\Helper\SomeHelper;
class DefaultController extends Controller
{
public function indexAction()
{
...
$helper = new SomeHelper();
$helper->doSomething();
...
}
}
Regarding the usage of services... Yes, that might be overkill, depending on what you're using it for. It's helpful to create services when the class needs to be aware of the application around it. For example, if you're creating a service that emails a User, it might want to access your database through the Doctrine service, or it might want to log the email activity through the Monolog service.
However, if your class doesn't need to know about the application (referred to as the "service container"), for example if it's just used to transfer data, then a helper class is probably more appropriate.
I am new with Symfony 2. I would like to add classes like libraries in my project but I dont know how.
Suppose I have 2 classes A and B.
I located them at this position : vendor/my_vendor_name/xxxx/A.php and vendor/my_vendor_name/xxxx/B.php
in each classes I defined the same namespace :
namespace my_vendor_name/xxxx
Now I would like to use those 2 classes in my bundles by calling :
use my_vendor_name/xxxx/A or my_vendor_name/xxxx/B
But It is like my namespaces do not exist (class not found)... maybe I have to declare those namespaces somewhere, to register them.
My app/autoload.php
<?php
use Doctrine\Common\Annotations\AnnotationRegistry;
$loader = require __DIR__.'/../vendor/autoload.php';
// intl
if (!function_exists('intl_get_error_code')) {
require_once __DIR__.'/../vendor/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs/functions.php';
$loader->add('', __DIR__.'/../vendor/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs');
}
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
return $loader;
This is not the correct way to procede.
You have, in this order:
Create a bundle under src/ directory
Register your bundle into app/AppKernel.php file
Create your classes under your bundle
Use those classes wherever you want
Real example:
Bundle Creation
Create a directory under src/ dir. This dir wll contains all your bundles. By convention, this directory should have to be your "company" name (for our example, say it is Foo).
After that, create a directory for your bundle, with name of your bundle. For our example. we decide to call it FooBundle.
So, you'll have this directory tree: src/Foo/FooBundle/
Into FooBundle/ you have to create a file that is used for bundle registration. This file is reported here:
<?php
namespace Foo\FooBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class FooBundle extends Bundle
{
}
File name is FooFooBundle.php
Register your bundle
Go into app/AppKernel.php file and add this line
public function registerBundles()
{
[...]
$bundles = array(
[...]
new Foo\FooBundle\FooFooBundle());
[...]
Congratulation! Your bundle is now registered!
Create your classes
Simply create your classes into your bundle. I suggest you to pack them into a directory like Core or whatever you want
Use your classes
Suppose that you have defined a class called A, into your brand new bundle.
Use it is quite simple:
use Foo\FooBundle\Core\A
into the file you want to use it
All should work now
Little Note:
A bundle inserted into src is different from a bundle inserted into vendor one only because your bundle (src one) is used by you, into your project only. A vendor bundle is someone else bundle that you use into your project. Behaviours (how to create bundle, how to register and use it) are exactly the same.
Little Note 2:
If you have to use external library or "old" php plain classes, Ahmed answer gives you a good point of start
Take a deeper look at the documentation. It's well explained in the The ClassLoader Component section.
From the documentation,
If the classes to autoload use namespaces, use the registerNamespace() or registerNamespaces() methods.
For classes that follow the PEAR naming convention, use the registerPrefix() or registerPrefixes() methods.
Note, The documentation is full of examples that fit your needs (Adding external classes or PHP libraries to your project)
Also, Take a look at the autoload section of Composer documentation.